如何解决添加新令牌重写以创建不在输入流上的AST节点的正确方法是什么
| 我在这里有一个适用于ANTLR的非常基本的数学表达式语法,并且感兴趣的是处理括号之间的隐式*
运算符,例如(2-3)(4+5)(6*7)
实际上应该是(2-3)*(4+5)*(6*7)
。
给定输入(2-3)(4+5)(6*7)
,我试图在解析时将丢失的add0 missing运算符添加到AST树中,在以下语法中,我认为我已经成功实现了这一点,但是我想知道这是否正确,最优雅办法?
grammar G;
options {
language = Java;
output=AST;
ASTLabelType=CommonTree;
}
tokens {
ADD = \'+\' ;
SUB = \'-\' ;
MUL = \'*\' ;
DIV = \'/\' ;
OPARN = \'(\' ;
CPARN = \')\' ;
}
start
: expression EOF!
;
expression
: mult (( ADD^ | SUB^ ) mult)*
;
mult
: atom (( MUL^ | DIV^) atom)*
;
atom
: INTEGER
| (
OPARN expression CPARN -> expression
)
(
OPARN expression CPARN -> ^(MUL expression)+
)*
;
INTEGER : (\'0\'..\'9\')+ ;
WS : (\' \' | \'\\t\' | \'\\n\' | \'\\r\' | \'\\f\')+ {$channel = HIDDEN;};
该语法似乎在ANTLRworks中输出正确的AST树:
我只是刚开始接触解析和ANTLR,没有太多经验,因此非常感谢您提供反馈!
提前致谢!卡尔
解决方法
首先,鉴于您以前从未使用过ANTLR,因此您做得很好。
您可以省略默认值
language=Java
和ASTLabelType=CommonTree
。因此,您可以执行以下操作:
options {
output=AST;
}
同样,您不必为每个运算符分别指定根节点。因此您不必做:
(ADD^ | SUB^)
但以下内容:
(ADD | SUB)^
就足够了。仅使用两个运算符就没有太大区别,但是在实现关系运算符(>=
,<=
,>
和<
)时,后者要容易一些。
现在,对您来说AST:您可能要创建一个二叉树:这样,所有内部节点都是运算符,而叶子将是操作数,这使表达式的实际求值变得容易得多。要获得二叉树,您必须稍微更改atom
规则:
atom
: INTEGER
| (
OPARN expression CPARN -> expression
)
(
OPARN e=expression CPARN -> ^(MUL $atom $e)
)*
;
给定输入\"(2-3)(4+5)(6*7)\"
,它将产生以下AST:
(图像产生:graphviz-dev.appspot.com)
DOT文件是使用以下测试类生成的:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
GLexer lexer = new GLexer(new ANTLRStringStream(\"(2-3)(4+5)(6*7)\"));
GParser parser = new GParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.start().getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。