优先级和相关性 - 使用JavaCC的语法错误

时间:2015-02-15 12:23:31

标签: grammar operator-precedence javacc

我的语法有问题,我真的不知道如何解决它。我正面临着操作中优先级和关联性的问题。我包括了整个语法,但我避免把所有的标记放在一起,否则它会太长。

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 个答案:

答案 0 :(得分:3)

有一个名为Parsing Expressions by Recursive Descent的写作,它概述了在递归下降解析器中获得优先级和关联性的3种方法。这三种技术都可以应用于JavaCC解析器。第二个(&#34;经典&#34;算法)可能最简单易用。