本教程将介绍使用ANTLR进行Java表达式解析的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。
问题描述
我正在用Java编写一个使用Java表达式解析的工具包。我想我应该试着使用ANTLR,因为
它似乎无处不在地用于这类事情
开源替代方案似乎不多
不久前我实际上曾尝试编写自己的通用解析器,但最终放弃了。那东西很难。
我不得不说,在我感觉自己阅读和尝试了很多不同的东西(无论怎么,比我预期的要多)之后,ANTLR似乎非常难以使用。该API非常不直观–我从来不太确定我调用它是否正确。
尽管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;部分的结果,仅在它可以分析的第一个内容之后退出。
好的。因此我更改为:
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);
认为这会迫使它解析整个表达式,然后我可以只提取我关心的部分。这适用于像";a.b";这样的名称表达式,但是如果我试图解析像";a.bc(D)";这样的方法表达式,它会给出一个错误:
line 1:12 mismatched input '(' expecting '.'
有趣的是,a()
、a.b()
和a.b.c
解析正常,但a.b.c()
也会死,但也会出现相同的错误。
这里有什么ANTLR专家可能知道我做错了什么?
另外,上面的错误被打印到stderr,但是我在Result对象中找不到它,这让我相当困扰。我希望能够向输入表达式的用户显示该错误消息(尽管很模糊)–他们可能没有查看控制台,即使他们正在查看控制台,也没有上下文。有什么办法在我返回的结果中找到该信息?
非常感谢您的帮助。
ANTLR
对于expression
这样的规则,一旦识别到表达式,推荐答案将停止分析。
您可以通过将`EOF添加到您的启动规则来强制它继续。
(您不想修改实际的`表达式规则,但可以添加如下规则:
expressionStart: expressions EOF;
然后您可以使用:
ParseTree result = parser.expressionStart();
这将强制ANTLR继续分析您的输入,直到它到达您的输入的末尾。
Re:rereturn Statement
当我通过IntelliJ中的ANTLR预览运行return a.b.c();
时,我得到以下解析树:
稍微遵循一下语法规则,我就偶然发现了这些规则:
typeName: Identifier | packageOrTypeName '.' Identifier;
packageOrTypeName
: Identifier
| packageOrTypeName '.' Identifier
;
这两个规则都包含packageOrTypeName '.' Identifier
的替代规则,这在我看来是有问题的。
在树中,我们看到primaryNoNewArray_lfno_primary:2
,表示匹配此规则中的第二个选项:
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
;
我现在没时间了,但我会继续关注的。在Java8Parser.g4中似乎不太可能出现这个明显的错误,但目前看起来肯定是一个错误。我不确定上下文会改变它的解析方式(按上下文,这意味着语法中本地调用returnStatement
的位置)。
我尝试了此输入(从compilationUnit
规则开始:
class Test {
class A {
public B b;
}
class B {
String c() {
return "";
}
}
String test() {
A a = new A();
return a.b.c();
}
}
并且它可以正确解析(因此,我们没有在Java8Parser语法?中发现重大错误):
尽管如此,这似乎不太对。
越来越近:
如果我从block
规则开始,并用大括号({return a.b.c();}
)括起来,它可以很好地解析。
我同意这样的理论,即ANTLR需要更多的前瞻来解决歧义(&Q;&Q;&Q;)。
好了关于使用ANTLR进行Java表达式解析的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。