2017-01-24 7 views
0

私はCのためのパーサを書くことを試みています。私が手にエラーがある: "競合を削減/削減"reduce/reduce conflict - yacc(識別子)

1)規則EXPは、例えばIDENTIFIER に取得する必要があります:AB(識別子識別子) - >EXP-EXP - >EXP

2)規則ident_listIDENTIFIERに取得する必要があります。このルールは変数の宣言に使用されます。 a、b、c(識別子、識別子、識別子) - >ident_listのように、 を入力します。

そのため私はに行くために、ルールの両方、ident_listEXPを必要とする - .Thisは "競合を削減/削減" の原因となっている>IDENTIFIER。どのようにこれを解決するための任意のアイデア?

-------------*yac code*:--------------- 


%{ 
     #include <stdio.h> 
     #include <stdlib.h> 
     #include <string.h> 
     typedef struct node 
     { 
       char* token; 
       struct node* left; 
       struct node* right; 
       char* type; 
     }node; 
     typedef struct obj 
     { 
       char* type; 
       char* name; 
       struct obj* next; 


     }obj; 

     typedef struct symTbl 
     { 
       struct obj* first; 
       struct obj* last; 
       int size; 
     }symTbl; 


     node* mknode (char* token,node* left, node* right,char* Type); 
     void put(symTbl* tbl, char* type,char* name); 
     void printtree(node* tree); 
     #define YYSTYPE struct node* 
%} 
%start s 
%token WHILELOOP 
%token STATIF 
%token ELSE 
%token MAIN 
%token POINTERERR 
%token COMMENT 
%token POINTER 
%token GREATEREQUAL 
%token LESSEREQUAL 
%token DBLAND 
%token GREATER 
%token LESSER 
%token POWER 
%token MULTIPLY 
%token MINUS 
%token PLUS 
%token AND 
%token OR 
%token NOT 
%token NOTEQUAL 
%token CHARERROR 
%token STRINGERROR 
%token POINTER 
%token INTEGER 
%token BOOLEAN 
%token DEVIDE 
%token ASSIGN 
%token EQUAL 
%token TYPE 
%token IDENTIFIER 
%token HEX IF 
%token LITERCHAR 
%token OCTAL 
%token BINARYINT 
%token LTRLSTRING 
%token COMMA COLON SEMICOLON VAR RETURN RPARENC LPARENC 
%left COMMA LPAREN RPAREN ELSE 
%left PLUS IF WHILELOOP TYPE 
%left MINUS DEVIDE RPARENC LPARENC 
%left MULTIPLY EQUAL NOTEQUAL OR AND LESSEREQUAL GREATEREQUAL GREATER LESSER 
%% 
s:progrem{printtree($1);} 
     progrem:exp|var_dec|if_stnt|ident_list|bool_exp| mul_ident; 

     exp: exp PLUS exp{$$=mknode("+",$1,$3,"arit");} 
      |exp MINUS exp {$$=mknode("-",$1,$3,"arit");} 
      |exp DEVIDE exp {$$=mknode("/",$1,$3,"arit");} 
      |exp MULTIPLY exp {$$=mknode("*",$1,$3,"arit");} 
      |MINUS exp {$$=mknode("-",$2,NULL,"arit");} 
      |IDENTIFIER {$$=mknode(yytext,NULL,NULL,"id");} 
    |LPAREN exp RPAREN {$$= $2;}; 
     bool_exp : exp EQUAL exp {$$=mknode("=",$1,$3,"bool");} 
      |exp NOTEQUAL exp {$$=mknode("!=",$1,$3,"bool");} 
      |exp OR exp {$$=mknode("||",$1,$3,"bool");} 
      |exp AND exp {$$=mknode("&&",$1,$3,"bool");} 
      |exp GREATEREQUAL exp {$$=mknode(">=",$1,$3,"bool");} 
      |exp LESSER exp {$$=mknode("<",$1,$3,"bool");} 
      |exp LESSEREQUAL exp {$$=mknode("<=",$1,$3,"bool");} 
      |exp GREATER exp {$$=mknode(">",$1,$3,"bool");} 
      |LPAREN bool_exp RPAREN {$$= $2;}; 


      var_dec:ident_list COLON ident_list {$$=mknode(":",$1,$3,"dec");}; 

      ident_list: ident_list COMMA ident_list {$$=mknode(",", $1, $3,"id_list");} 
        |ident_list TYPE ident_list{$$=mknode(yytext,$1,NULL,"id");} 
        |VAR {$$= mknode("var",NULL,NULL,"id");} 
        |SEMICOLON {$$= mknode(";",NULL,NULL,"id");}; 
        |IDENTIFIER {$$=$1;} 


     if_stnt:IF LPAREN bool_exp RPAREN {$$=mknode("if",$3,NULL,"if_state");}; 
%% 
#include "lex.yy.c" 
main() 
{ 
     yyin=fopen("text.txt","r"); 
     return yyparse(); 
} 
node* mknode(char* token,node*left,node* right,char* Type) 
{ 

     node* newnode=(node*)malloc(sizeof(node)); 
     char* newstr=(char*)malloc(sizeof(token)+1); 
     char* type = (char*)malloc (sizeof(Type)+1); 
     type[sizeof(token)]='\0'; 
     newstr[sizeof(token)]='\0'; 
     strcpy(newstr,token); 
     strcpy(type,Type); 
     newnode->left=left; 
     newnode->type=type; 
     newnode->right=right; 
     newnode->token=newstr; 
     return newnode; 
} 

void put(symTbl* tbl, char* type,char* name) 
{ 
     symTbl* tbl1=(symTbl*)malloc(sizeof(symTbl)); 

     int size = tbl->size; 
     obj* newobj=(obj*)malloc(sizeof(obj)); 
     newobj= tbl->first; 
     int i; 
       for(i =0; i<size; i++){ 
         if(newobj->name == name){ 

yyerror(); 
         newobj=newobj->next; 
       } 
      } 
     tbl->last->next=newobj; 
     tbl->last=tbl->last->next; 

} 

void printtree(node* tree) 
{ 

     printf("%s",tree->token); 
     if(tree->left)printtree(tree->left); 
     if(tree->right)printtree(tree->right); 
} 
int yyerror() 
{ 
     printf("bla bla\n"); 
     return 0; 
} 

-------- のlexコード:------------

minus "-" 
colon ":" 
semicolon ";" 
space " " 
parcent "%" 
backslash "/" 
charptr charptr 
plus "+" 
not "!" 
notequal "!=" 
or "||" 
and "&&" 
multiply "*" 
power "^" 
dbland "&" 
greater ">" 
lesser "<" 
type boolean|string|char|integer|intptr|charptr 
return "return" 
greaterequal {greater}{assign} 
lesserequal {lesser}{assign} 
singleQuotes \' 
charERR {singleQuotes}+(({digit})+)*(({letter})+)*{singleQuotes}+ 
stringERR {doubleQuotes}{doubleQuotes}+|{doubleQuotes} 
doubleQuotes \" 
var "var"{space}* 
octalDigit [1-7] 
decimal {digit}|{digitNoZero}{digit}+ 
digitNoZero[1-9] 
octal "0"{octalDigit}("0")*{octalDigit}* 
integer {binaryInt}|{hex}|{octal}|{decimal} 
binaryInt ("0"|"1")+"b" 
hexLetter A|B|C|D|E|F 
hex 0(x|X){digit}+{hexLetter}*|0(x|X){digit}*{hexLetter}+ 
literBool true|false 
letter [a-zA-Z] 
letters {letter}+ 
digit [0-9] 
low "_" 
equal "==" 
assign "=" 
devide "/" 
lparen "(" 
rparen ")" 
lparenc "{" 
rparenc "}" 
identifier {letter}+{digit}*{letter}+{space}*|{space}*{letter}{space}* 
literChar {singleQuotes}{letter}{singleQuotes} 
ltrlString {doubleQuotes}{letters}*{decimal}*{hex}*{octal}*{binaryInt}*{dbland}*{devide}*{assign}*{equal}*{greater}*{lesser}*{greaterequal}*{lesserequal}*{mi$ 
pointer {colon}{space}{charptr}|"="{space}"&"{identifier} 
comment {backslash}{parcent}{space}*({letters}*{space}*{identifier}*{space}*{decimal}*{space}*{hex}*{space}*{octal}*{space}*{binaryInt}*{space}*{dbland}*{dev$ 
pointerErr "&"{identifier}|{charptr} 
statif "if"{space}* 
ELSE "else"{space}* 
comma "," 
whileLoop "while"{space}* 
main "main" 
%% 
{lparen} return LPAREN; 
{rparen} return RPAREN; 
{colon} return COLON; 
{type} return TYPE; 
{semicolon} return SEMICOLON; 
{var} return VAR; 
{whileLoop} return WHILELOOP; 
{ELSE} return ELSE; 
{statif} return IF; 
{pointerErr} return POINTERERR; 
{comment} return COMMENT; 
{pointer} return POINTER; 
{literChar} return LITERCHAR; 
{charERR} return CHARERROR; 
{stringERR} return STRINGERROR; 
{ltrlString} return LTRLSTRING; 
{binaryInt} return BINARYINT; 
{octal} return OCTAL; 
{hex} return HEX; 
{return} return RETURN; 
{greaterequal} return GREATEREQUAL; 
{lesserequal} return LESSEREQUAL; 
{dbland} return DBLAND; 
{greater} return GREATER; 
{lesser} return LESSER; 
{lparenc} return LPARENC; 
{rparenc} return RPARENC; 
{power} return POWER; 
{multiply} return MULTIPLY; 
{plus} return PLUS; 
{or} return OR; 
{and} return AND; 
{comma} return COMMA; 
{not} return NOT; 
{main} return MAIN; 
{notequal} return NOTEQUAL; 
{minus} return MINUS; 
{integer} return INTEGER; 
{literBool} return BOOLEAN; 
{identifier} return IDENTIFIER; 
{equal} return EQUAL; 
{assign} return ASSIGN; 
{devide} return DEVIDE; 
. return yytext[0]; 
+0

私はここで少し混乱しています。変数宣言はどのように見えますか? – cHao

+2

フレックス・マクロ定義の膨大なリストを作成するこのスタイルの原点は、ファイル内でわずかに下に1回だけ使用することですか?実際に教科書に示唆されていることがありますか?大学のインストラクターのアイデアですか?もしそうなら、私は彼らに直接不平を言うことができるように私に彼らの電子メールアドレスを渡すことができますか? – rici

+0

また、 'mul_ident'が参照されているが定義されていないため、あなたのファイルはbisonエラーを引き起こします。 [mcve] – rici

答えて

1

あなたはprogramは、いずれかになりますことを言っていますexpまたはident_listである。これは特に賢明ではありません、あなたの意図は何らかのデバッグを行うことです。しかし、1つの識別子が1つの識別子または1つの識別子を含む式またはリストになる可能性があり、パーサーがあなたが意味するものを推測する明白な方法がないため、これは機能しません。それはあなたの文法を曖昧にします。

この場合、yacc/bisonは文法ファイルのどのプロダクションが先に来るかを選択します。それは好みを定義する非常に正確な方法ではないので、それはあなたに紛争について警告します。しかし、あなたの好みを表現することが可能になります。

それ以外の場合は、あいまいさを解消する必要があります。たとえば、単一の識別子がexpであると判断した場合は、トップレベルの識別子リストに少なくとも2つの識別子があると主張できます。

+0

'exp'のように思えますが、識別子ではなくident_listについて気にするとかなり奇妙な結果が得られます。 – cHao

+0

@cHao:確かに、それはありません。トップレベル以外の 'ident_list'は宣言でのみ使われ、' ident'と混同することはできません。 – rici

+0

'progrem'は' exp'でもかまいません。 'exp'または' ident_list'であれば、単一の識別子はどのように解析されますか? – cHao