本文介紹了使用ANTLR進行Java表達式解析的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我正在用Java編寫一個使用Java表達式解析的工具包。我想我應(yīng)該試著使用ANTLR,因為
-
它似乎無處不在地用于這類事情
開源替代方案似乎不多
不久前我實際上曾嘗試編寫自己的通用解析器,但最終放棄了。那東西很難。
我不得不說,在我感覺自己閱讀和嘗試了很多不同的東西(無論如何,比我預(yù)期的要多)之后,ANTLR似乎非常難以使用。該API非常不直觀–我從來不太確定我調(diào)用它是否正確。
盡管ANTLR教程和示例比比皆是,但我還沒有找到任何涉及解析Java表達式的示例–其他人似乎都想解析整個Java文件。
我一開始是這樣稱呼它的:
Java8Lexer lexer = new Java8Lexer(CharStreams.fromString(text));
CommonTokenStream tokens = new CommonTokenStream(lexer);
Java8Parser parser = new Java8Parser(tokens);
ParseTree result = parser.expression();
但這不會解析整個表達式。例如,對于TEXT&QOOT;A.B&QOOT;,它將返回只包含&QOOT;A&QOOT;部分的結(jié)果,僅在它可以分析的第一個內(nèi)容之后退出。
好的。因此我更改為:
String input = "return " + text + ";";
Java8Lexer lexer = new Java8Lexer(CharStreams.fromString(input));
CommonTokenStream tokens = new CommonTokenStream(lexer);
Java8Parser parser = new Java8Parser(tokens);
ParseTree result = parser.returnStatement();
result = result.getChild(1);
認為這會迫使它解析整個表達式,然后我可以只提取我關(guān)心的部分。這適用于像";a.b";這樣的名稱表達式,但是如果我試圖解析像";a.bc(D)";這樣的方法表達式,它會給出一個錯誤:
line 1:12 mismatched input '(' expecting '.'
有趣的是,a()
、a.b()
和a.b.c
解析正常,但a.b.c()
也會死,但也會出現(xiàn)相同的錯誤。
這里有沒有ANTLR專家可能知道我做錯了什么?
另外,上面的錯誤被打印到stderr,但是我在Result對象中找不到它,這讓我相當困擾。我希望能夠向輸入表達式的用戶顯示該錯誤消息(盡管很模糊)–他們可能沒有查看控制臺,即使他們正在查看控制臺,也沒有上下文。有沒有辦法在我返回的結(jié)果中找到該信息?
非常感謝您的幫助。
ANTLR
對于expression
這樣的規(guī)則,一旦識別到表達式,推薦答案將停止分析。
您可以通過將`EOF添加到您的啟動規(guī)則來強制它繼續(xù)。
(您不想修改實際的`表達式規(guī)則,但可以添加如下規(guī)則:
expressionStart: expressions EOF;
然后您可以使用:
ParseTree result = parser.expressionStart();
這將強制ANTLR繼續(xù)分析您的輸入,直到它到達您的輸入的末尾。
Re:rereturn Statement
當我通過IntelliJ中的ANTLR預(yù)覽運行return a.b.c();
時,我得到以下解析樹:
稍微遵循一下語法規(guī)則,我就偶然發(fā)現(xiàn)了這些規(guī)則:
typeName: Identifier | packageOrTypeName '.' Identifier;
packageOrTypeName
: Identifier
| packageOrTypeName '.' Identifier
;
這兩個規(guī)則都包含packageOrTypeName '.' Identifier
的替代規(guī)則,這在我看來是有問題的。
在樹中,我們看到primaryNoNewArray_lfno_primary:2
,表示匹配此規(guī)則中的第二個選項:
primaryNoNewArray_lfno_primary
: literal
| typeName ('[' ']')* '.' 'class' // <-- trying to match this rule
| unannPrimitiveType ('[' ']')* '.' 'class'
| 'void' '.' 'class'
| 'this'
| typeName '.' 'this'
| '(' expression ')'
| classInstanceCreationExpression_lfno_primary
| fieldAccess_lfno_primary
| arrayAccess_lfno_primary
| methodInvocation_lfno_primary
| methodReference_lfno_primary
;
我現(xiàn)在沒時間了,但我會繼續(xù)關(guān)注的。在Java8Parser.g4中似乎不太可能出現(xiàn)這個明顯的錯誤,但目前看起來肯定是一個錯誤。我不確定上下文會改變它的解析方式(按上下文,這意味著語法中本地調(diào)用returnStatement
的位置)。
我嘗試了此輸入(從compilationUnit
規(guī)則開始:
class Test {
class A {
public B b;
}
class B {
String c() {
return "";
}
}
String test() {
A a = new A();
return a.b.c();
}
}
并且它可以正確解析(因此,我們沒有在Java8Parser語法