编译Yacc代码

时间:2016-02-21 19:41:46

标签: yacc

下面是我解析C源代码的yacc代码。我对此有点新,这是一个已经存在的代码。

{

%{
  #include <stdio.h>
  #include <string.h>
  #include "Expression.c"

%}


%token Identifier
%token Number
%token '=' '+' '-' '*' '/' ',' ';' '(' ')' '{' '}' '[' ']' '<' '>'
%token INT
%token CHAR
%token FLOAT
%token LONG
%token DOUBLE
%token RETURN
%token IF
%token ELSE
%token EQ       /* == */
%token BADTOKEN

%%

program
 : function 
     { $$ = $1; }
 | program function 
    { $$ = binaryNode("",$1,$2);}
 | error '}'    

function: 
 typename Identifier '(' formal.arguments ')' function.body
    { $$ = attachAllChildren($2,$1,$4,$6); }

typename
 : INT 
    { $$ = leafNode("INT");}
 | CHAR 
    { $$ = leafNode("CHAR"); }
 | DOUBLE 
    { $$ = leafNode("DOUBLE"); }
 | LONG 
    { $$ = leafNode("LONG"); }
 | FLOAT
    { $$ = leafNode("FLOAT"); }

formal.arguments
 :  /* empty */
    { $$ = NULL; }
 | formal.argument.list
    { $$ = $1; }

formal.argument.list
 : formal.argument
    { $$ = $1; }
 | formal.argument.list ',' formal.argument
    { $$ = binaryNode(",", $1, $3); }

formal.argument
 : typename Identifier
    { $$ = attachChild($2, $1); }

function.body
 : '{' '}'
    { $$ = NULL; }
 | '{' statements '}'
    { $$ = $2; }

statements
 : statement
    { $$ = $1; }
 | statements statement
    { $$ = attachChild($1,$2);}

statement
 : declaration
    { $$ = $1; }
 | RETURN expression ';'        /* return statement */
    { $$ = unaryNode("RETURN", $2); }
 | if.statement
    { $$ =$1; }
 | term '=' expression ';'      /* assignment */
    { $$ = binaryNode("=", $1, $3); }
 | expression ';'
    { $$ = $1; }

 | '{' statements '}'
    { $$ = $2; }

 | ';'              /* null statement */
    { $$ = NULL; }

declaration
 : typename Identifier ';'
    { $$ = attachChild($2,$1); }

 | typename Identifier '[' Number ']' ';'   /* array */
    { $$ = attachSiblings($2, $1, $4); }

if.statement
 : IF '(' expression ')' statement
    { $$ = ternaryNode("IF",$3,$5, NULL); }

 | IF '(' expression ')' statement ELSE statement
    { $$ = ternaryNode("IF", $3, $5, $7); }

expression
 : additive.expression
    { $$ = $1; }
 | expression EQ additive.expression
    { $$ = binaryNode("=",$1, $3); }
 | expression '>' additive.expression
    { $$ = binaryNode(">", $1, $3); }
 | expression '<' additive.expression
    { $$ = binaryNode("<", $1, $3); }

additive.expression
 : term
    { $$ = $1; }
 | additive.expression '+' term
    { $$ = binaryNode("+", $1, $3);}
 | additive.expression '-' term
    { $$ = binaryNode("-", $1, $3);}

term
 : Identifier
    { $$ = leafNode($1);}
 | Number
    { $$ = leafNode($1);}
 | Identifier '(' opt.actual.arguments ')'  /* function call */
    { $$ = attachChild($1,$3);}
 | Identifier '[' expression ']'        /* array access */
    { $$ = attachChild($1,$3); }
 | '(' expression ')'
    { $$ = $2;}


 opt.actual.arguments
  : /* empty */
    { $$ = NULL;}
  | actual.arguments
    { $$=$1; }


 actual.arguments
   : expression
    { $$ = $1; }

   | actual.arguments ',' expression
    { $$ = binaryNode(",",$1, $3); }

 %%

 yyerror(msg)
 char* msg;
 {
   #if !defined(YYBISON)
   extern int yynerrs;

   ++yynerrs;
   #endif
   fprintf(stderr, "Error: %s\n",msg);
  }             

 main()
 {
    extern int yynerrs;
    yyparse();
    fprintf(stderr, "%d errors.\n", yynerrs);
    return 0;
  }
 }

在编译上面的代码时,我收到警告,代码中有1个shift / reduce冲突。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

使用yacc的-v选项,这将生成一个y.output文件,告诉您冲突的位置以及冲突的方式。请注意,冲突不是错误 - 您仍然从yacc获得有效的解析器 - 但该解析器可能无法准确识别语法定义的语言。

在你的情况下,你会得到类似的东西:

State 81 conflicts: 1 shift/reduce
        :
State 81

   28 if.statement: IF '(' expression ')' statement .
   29             | IF '(' expression ')' statement . ELSE statement

    ELSE  shift, and go to state 83

    ELSE      [reduce using rule 28 (if.statement)]
    $default  reduce using rule 28 (if.statement)

告诉你你有经典的dangling else ambiguity,所以你可以忽略冲突,因为生成的解析器会通过将else绑定到最近的if来解决歧义,这可能是你想要的。