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

    技术2022-05-11  128

    通过抽象语法树(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)