2016-02-21 201 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,那麼你可以擺脫它們 - 動作對解析的語言沒有影響(除非它們將信息反饋給詞法分析器),它們只是在解析器減少規則時運行。 –