(基于Java)编写编译器和解释器-第8A章:基于Antlr解析&解释执行Pascal控制语句(连载)Posted on 2012-07-29 22:02 Bang 阅读(204) 评论(0) 编辑 收藏在第7,8章我们分别学习了Pascal控制语句的解析,解释执行,还涉及到了一点点优化,虽然好像花的时间不多,但是用Antlr之后就会发现还是很啰嗦。Antlr对于编译器作者来说,或许不是性能最好的,但是对于语言前期的论证,运行时原型的快速构建都有非常重要意义,尤其语法较多(也就是EBNF Rule条数很多)。更进一步说,即使有很多优化,Antlr的源代码和代码生成(Codegen)这一块完全可以定制。我们可以在语言,运行时稳定之后来个手写版:)。好了,废话不多说了,先看控制语句的语法。 ==>> 本章中文版源代码下载:svn co http://wci./svn/branches/ch8_antlr/ 源代码使用了UTF-8编码,下载到本地请修改! 控制语句的语法这几个控制语句,FOR最复杂,CASE其次,下面的语法描述严格遵循第7章的分析树显示。 1: statement: 2: compound_statement | assignment_statement | control_statement; 3: control_statement: 4: while_statement | repeat_statement | for_statement | if_statement | case_statement; 5: while_statement: 6: WHILE t1=expression DO s1=statement ->^(LOOP ^(NOT $t1) $s1); 7: repeat_statement: 8: REPEAT s1=statement_list UNTIL t1=expression ->^(LOOP $s1 $t1); 9: for_statement 10: @init{ 11: PascalNode id_node = null; 12: PascalNode id_cp1=null; 13: PascalNode id_cp2=null; 14: PascalNode id_cp3=null; 15: PascalNode op_node=null; 16: boolean increment = true; 17: PascalNode one_constant = (PascalNode)adaptor.create(NUMBER,"1"); 18: ((PascalAntlrToken)one_constant.getToken()).setValue(new Integer(1)); 19: }: 20: (FOR a1=assignment_statement { 21: id_node =(PascalNode) ((PascalNode)a1.getTree()).getChild(0); 22: id_cp1 = (PascalNode)id_node.dupNode(); 23: id_cp2= (PascalNode)id_node.dupNode(); 24: id_cp3= (PascalNode)id_node.dupNode(); 25: } 26: (TO{op_node=(PascalNode) adaptor.create(PLUS,"+");} | DOWNTO{increment=false;op_node=(PascalNode) adaptor.create(MINUS,"-");}) 27: q=(e11=expression->{increment}?^(GT {id_cp1} $e11)->^(LT {id_cp1} $e11)) 28: DO s2=statement) ->^(COMPOUND $a1 ^(LOOP ^(TEST $q) $s2 ^(ASSIGN {id_cp2} ^({op_node} {id_cp3} {one_constant})))); 29: if_statement: 30: IF t1=expression THEN s1=statement ((ELSE)=>ELSE s2=statement)? -> ^(IF $t1 $s1 $s2?); 31: case_statement: 32: CASE e1=expression OF bhs=case_branches END ->^(SELECT $e1 $bhs); 33: case_branches: 34: case_branch (SEMI case_branch)* SEMI? -> case_branch+; 35: case_branch: 36: c1=constant_list COLON s1=statement ->^(SELECT_BRANCH $c1 $s1); 37: constant_list: 38: constant(COMMA constant)* -> ^(SELECT_CONSTANTS constant+); 39: constant: 40: NUMBER | NUMBER_REAL | STRING; 这个语法有几个地方要说明一下:
如果使用了如下的"foo.txt"进行语法树构建 1: BEGIN {FOR statements} 2: j := 1; 3: 4: FOR k := j TO 5 DO n := k; 5: 6: FOR k := n DOWNTO 1 DO j := k; 7: 8: FOR i := 1 TO 2 DO BEGIN 9: FOR j := 1 TO 3 DO BEGIN 10: k := i*j 11: END 12: END 13: END. 那么Antlr生成的分析树图形将会是(图太大,只截取后面两个循环的):
控制语句的语义(即解释执行) |
|