我的语法有问题,我真的不知道如何解决它 . 我正面临着操作中优先级和关联性的问题 . 我包括了整个语法,但我避免把所有的标记放在一起,否则它会太长 .
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 )
任何帮助真的很感激!谢谢
1 回答
有一个名为Parsing Expressions by Recursive Descent的写作,它概述了在递归下降解析器中获得优先级和关联性的3种方法 . 这三种技术都可以应用于JavaCC解析器 . 第二个("classic"算法)可能最简单 .