我的语法有问题,我真的不知道如何解决它。我正面临着操作中优先级和关联性的问题。我包括了整个语法,但我避免把所有的标记放在一起,否则它会太长。
PARSER_BEGIN(UcParse) Node Start() : { Node tree = new Node(Id.PROGRAM); Node td; } { ( td = TopLevelDeclaration() { tree.add(td); } )* <EOF> { return tree; } } Node TopLevelDeclaration() : { Node n; } { LOOKAHEAD(3) n = Declaration() <SEMI> { return n; } | n = Function() { return n; } | n = IncludeFile() {return n; } } Node Function() : { Node tld = new Node(Id.FUNC); Node bt; Node dr; Node body; Node formals; Node s; } { bt = ReturnType() { tld.add(bt); } Declarator(tld) ( FunctionParameters(tld) ( body = CompoundStatement() { tld.add(body); } | <SEMI> ) | { } ) { return tld; } } //List FunctionParameters () : void FunctionParameters (Node func) : { Node f; } { <LPAREN> ( <VOID> { func.add(new Node(Id.VOID)); } | f = Declaration() { func.add(f); } ( <COMMA> f = Declaration() { func.add(f); } )* ) <RPAREN> } Node Declaration () : { Node d = new Node(Id.VARDEC); Node bt; Node dr; } { bt = DeclarationType() { d.add(bt); } Declarator(d) { return d; } } Node SimpleDeclaration () : { Node d = new Node(Id.VARDEC); Node bt; Node id; } { bt = DeclarationType() { d.add(bt); } id = Identifier() { d.add(id); } <SEMI> { return d; } } Node ReturnType () : {} { <CHAR> { return new Node(Id.CHAR); } | <INT> { return new Node(Id.INT); } | <VOID> { return new Node(Id.VOID); } } Node DeclarationType () : {} { <CHAR> { return new Node(Id.CHAR); } | <INT> { return new Node(Id.INT); } } void Declarator (Node p) : { Node id; Node r; } { id = Identifier() { p.add(id); } ( <LBRACK> ( r = IntegerLiteral() { p.add(r); } ) * <RBRACK> | { } ) } Node CompoundStatement () : { Node cs = new Node(Id.COMPOUND_STMNT); Node d; Node s; } { <LBRACE> ( d = Declaration() { cs.add(d); } <SEMI> )* ( s = Statement() { cs.add(s); } )* <RBRACE> { return cs; } } Node Statement() : { Node stmt = new Node(Id.STMNT); Node s; Token t; Node c; Node s1; Node s2; } { (s = SimpleCompoundStatement() { stmt.add(s); } | Expression(stmt) <SEMI> // expr; | <SEMI> { stmt.add(new Node(Id.EMPTY_STMNT)); } //; | t = { s = new Node(Id.IF); stmt.add(s); } <LPAREN> Expression(s) <RPAREN> s1 = Statement() { s.add(s1); } ( LOOKAHEAD(1) <ELSE> s2 = Statement() { s.add(s2); } ) * | t = <WHILE> { s = new Node(Id.WHILE); stmt.add(s); } <LPAREN> Expression(s) <RPAREN> s2 = Statement() { s.add(s2); } | (Expression(stmt)) * <SEMI>) //return expr*; { return stmt; } } Node SimpleCompoundStatement() : { Node scs = new Node(Id.SIMPLE_COMPOUND_STMNT); Token left; Token right; Node s; } { left = <LBRACE> ( s = Statement() { scs.add(s); } )* right = <RBRACE> { return scs; } } void Expression (Node e) : { Node exp; Node id; Node p; Node op; } { ( op = IntegerLiteral() OperatorExpression(e, op) | exp = CharLiteral() OperatorExpression(e, exp) | <LPAREN> { p = new Node(Id.PAREN); } Expression(p) <RPAREN> OperatorExpression(e, p) | id = Identifier() ( <LBRACK> Expression(e) <RBRACK> | <LPAREN> ( Expression(e) ( <COMMA> Expression(e) )* | { } ) <RPAREN> | { } ) OperatorExpression(e, id) | exp = Unary() Expression(e) OperatorExpression(e, exp) ) } void OperatorExpression(Node par, Node op) : { Node n; Node p; } { ( LOOKAHEAD(2) n = BinaryMulDiv() { par.add(n); } { n.add(op); } Expression(n) | OperatorExpressionPlusMin(par, op) ) } void OperatorExpressionPlusMin(Node par, Node op) : { Node n; } { ( LOOKAHEAD(2) n = BinaryPlusMin() { par.add(n); } { n.add(op); } Expression(n) | OperatorExpressionComp(par, op)) } void OperatorExpressionComp(Node par, Node op) : { Node n; } { ( LOOKAHEAD(2) n = BinaryComp() { par.add(n); } { n.add(op); } Expression(par) | {} {par.add(op);} ) } Node BinaryComp () : { Token t; } { (t = <LT> // > | t = <GT> // // // >= | t = <EQ> // = | t = <EQEQ> // == | t = <NOTEQ> // != | t = <ANDAND> // && | t = <OROR>) // || {return new Node(Id.BINARY, t.image); } } Node BinaryMulDiv () : { Token t; } { (t = <MUL> // * | t = <DIV>) // / {return new Node(Id.BINARY, t.image); } } Node BinaryPlusMin () : { Token t; } { (t = <PLUS> // + | t = <MINUS>) // - {return new Node(Id.BINARY, t.image); } } Node Unary() : { Token t; } { t = <MINUS> { return new Node(Id.UNARY, t.image); } | t = <NOT> { return new Node(Id.UNARY, t.image); } // ! } Node Identifier() : { Token t; } { t = <IDENT> { return new Node(Id.IDENT, t.image); } } Node IntegerLiteral() : { Token t; } { t = <INTEGER_LITERAL> { return new Node(Id.INTEGER_LITERAL, t.image); } } Node CharLiteral() : { Token t; } { t = <CHAR_LITERAL> { return new Node(Id.CHAR_LITERAL, t.image); } } Node FileName() : { Token dot; } { (<IDENT> <DOT> <IDENT>) { return new Node(Id.FILE_NAME); } } Node IncludeFile() : { Node include = new Node(Id.INCLUDE); Node name; Token incl; Token lt; Token gt; } { incl = <INCLUDE> lt = <LT> name = FileName() { include.add(name); } gt = <GT> { return include; } }
这是我用于测试的程序。
int main(void) { int i; 1!=!3; 4&&(6); 7* 8+10; // wrong tree 10+8*7; // right tree (11-12)+(12/16); 17=27>28; }
我想在我的语法中不起作用的部分是 OperatorExpression(),因为当我打印上面代码的语法树时,我获得了两行不同的分支评论。 这里是语法树
PROGRAM FUNC INT IDENT ( main ) VOID COMPOUND_STMNT VARDEC INT IDENT ( i ) STMNT BINARY ( != ) INTEGER_LITERAL ( 1 ) INTEGER_LITERAL ( 3 ) UNARY ( ! ) STMNT BINARY ( && ) INTEGER_LITERAL ( 4 ) PAREN INTEGER_LITERAL ( 6 ) STMNT BINARY ( * ) INTEGER_LITERAL ( 7 ) BINARY ( + ) INTEGER_LITERAL ( 8 ) INTEGER_LITERAL ( 10 ) STMNT BINARY ( + ) INTEGER_LITERAL ( 10 ) BINARY ( * ) INTEGER_LITERAL ( 8 ) INTEGER_LITERAL ( 7 ) STMNT BINARY ( + ) PAREN BINARY ( - ) INTEGER_LITERAL ( 11 ) INTEGER_LITERAL ( 12 ) PAREN BINARY ( / ) INTEGER_LITERAL ( 12 ) INTEGER_LITERAL ( 16 ) STMNT BINARY ( = ) INTEGER_LITERAL ( 25 ) BINARY ( > ) INTEGER_LITERAL ( 27 ) INTEGER_LITERAL ( 28 )
任何帮助都非常感谢!感谢
答案 0 :(得分:3)
有一个名为Parsing Expressions by Recursive Descent的写作,它概述了在递归下降解析器中获得优先级和关联性的3种方法。这三种技术都可以应用于JavaCC解析器。第二个(&#34;经典&#34;算法)可能最简单易用。