ANTLR(语言识别的另一工具)的简介之四[翻译]

通过抽象语法树(AST)求值

现在你已经看到了基本的语法指导的翻译/计算,在此文法/语法指示了什么时候去执行动作。一个更为强大的策略是创建一个中介表达,它拥有所有或绝大部分的输入符号,并在数据的结构中,将这些记号之间的关系编码。比如:输入“3+4”会被表达成如下所示的AST:

  +

 / /

3   4

对这种类型的树,你会使用一个树遍历程序(由ANTLR从树形语法生成)计算出和前面一样的值,但是却使用了不同的策略。

为了确定计算什么,或进行语法树的重写,或者向另一种语言进行树变形,你必须对语法树进行多重遍历。这时,AST的效果会变得清晰。

AST构造

对许多语法,让ANTLR生成一个有用的AST是相当简单的。在我们这里,打开buildAST选项并且添加少许后缀操作符来告诉ANTLR那些记号应该是子树的根。

class ExprParser extends Parser;

 

options {

        buildAST=true;

}

 

expr:   mexpr ((PLUS^|MINUS^) mexpr)*

    ;

 

mexpr

    :   atom (STAR^ atom)*

    ;

 

atom:   INT

    |   LPAREN! expr RPAREN!

    ;

同样,lexer不变。主程序询问目标语法树,并将其打印:

import antlr.*;

import antlr.collections.*;

 

public class Main {  

    public static void main(String[] args) throws Exception {   

        ExprLexer lexer = new ExprLexer(System.in);

        ExprParser parser = new ExprParser(lexer);

        parser.expr();

        AST t = parser.getAST();

        System.out.println(t.toStringTree());

    }   

}   

$ java Main

3+4

 ( + 3 4 )

$ java Main

3+4*5

 ( + 3 ( * 4 5 ) )

$ java Main

(3+4)*5

 ( * ( + 3 4 ) 5 )

$

AST解析和求值

有上面的parser创建的语法树非常简单。语法树解析程序中的单一规则就足够了。

class ExprTreeParser extends TreeParser;

 

options {

    importVocab=ExprParser;

}

 

expr returns [int r=0]

{ int a,b; }

    :   #(PLUS  a=expr b=expr)  {r = a+b;}

    |   #(MINUS a=expr b=expr)  {r = a-b;}  

    |   #(STAR  a=expr b=expr)  {r = a*b;}

    |   i:INT                   {r = (int)Integer.parseInt(i.getText());}

    ;

主程序则修改为使用新的语法树parser来求值:

import antlr.*;

import antlr.collections.*;

 

public class Main {

    public static void main(String[] args) throws Exception {   

        ExprLexer lexer = new ExprLexer(System.in);

        ExprParser parser = new ExprParser(lexer);

        parser.expr();

        AST t = parser.getAST();

        System.out.println(t.toStringTree());

        ExprTreeParser treeParser = new ExprTreeParser();

        int x = treeParser.expr(t);

        System.out.println(x);

    }   

}

现在你得到了树形结构和结果值。

$ java Main

3+4

 ( + 3 4 )

7

$ java Main

3+(4*5)+10

 ( + ( + 3 ( * 4 5 ) ) 10 )

33

$

  • 0
    点赞
  • 0
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值