2016-02-21 239 views
0

下面是我解析C源代码的yacc代码。我对此有点新,这是一个已经存在的代码。编译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冲突。我该如何解决这个问题?

回答

3

-v选项用于yacc,它将生成一个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,所以你可能忽略的冲突,所生成的解析器将通过绑定解决歧义否则到最近如果,这可能是你想要的。

+0

绝对是的,但是我的词法分析器应该生成什么样的标记(我主要希望只生成算术操作及其相应的操作符?我也可以直接删除节点赋值语句,直到抽象语法树在上面的解析器中有关吗? –

+0

@AbhijeetMohanty:我不确定我是否理解你的后续问题,你的词法分析器需要生成你的解析器使用的标记,你的.y文件的赋值语句(在动作中)建立一个AST 。如果你不想要/需要一个AST,那么你可以摆脱它们 - 动作对解析的语言没有影响(除非它们将信息反馈给词法分析器),它们只是在解析器减少规则时运行。 –