2017-01-24 1 views
0

나는 간단한 C 파서를 작성하려고합니다. 내가 오류가 있습니다 : "/ 감소 충돌을 줄이기"reduce/reduce conflict - yacc (식별자)

1) 규칙 특급 필요가 IDENTIFIER에 도착 예를 들어 : AB (식별자 식별자) ->EXP-특급 ->특급

2) 규칙 ident_listIDENTIFIER에 도착해야합니다. 이 룰은 변수 선언에 사용됩니다. 예 : a, b, c (식별자, 식별자, 식별자) ->ident_list. >IDENTIFIER .This는 "감소/감소 충돌"을 일으키는 -

는 그 때문에 내가 이동하는 규칙의 모두 ident_list특급이 필요합니다. 어떤 생각이 어떻게 해결할 수 있습니까?

-------------*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; 
} 

-------- 렉스 코드 : ------------

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

플렉스 매크로 정의의 엄청난 목록을 만드는 스타일의 원점은 파일에서 정확히 한 번만 사용하는 것입니다. 일부 교과서에서 실제로 그렇게 할 것을 제안 할 수 있습니까? 일부 대학 강사의 왜곡 된 생각입니까? 그렇다면 직접 전자 메일 주소를 전달하여 직접 불평 할 수 있습니까? – rici

+0

또한 mul_ident가 참조되었지만 정의되지 않았기 때문에 파일에서 bison 오류가 발생합니다. [mcve] – rici

답변

1

당신은 program이 어느 쪽인가를 할 수 있다는 말을하는지 exp 또는 ident_list 등이 있습니다. 이것은 특히 시작하는 것이 현명하지 않으며, 여러분의 의도는 일종의 디버깅을하는 것이라고 생각합니다. 그러나 하나의 식별자가 정확히 하나의 식별자를 포함하는 표현식이나 목록 일 수 있기 때문에 작동하지 않을 것이고 파서가 당신이 의미 한 것을 추측 할 분명한 방법이 없기 때문에 작동하지 않을 것입니다. 그것은 문법을 모호하게 만든다.

이 경우 yacc/bison은 문법 파일의 앞부분에 나오는 작품을 선택하는 것입니다. 이것은 환경 설정을 정의하는 정확한 방법이 아니기 때문에 충돌에 대해 경고합니다. 그러나 그것은 당신이 당신의 취향을 표현할 수있게합니다.

그렇지 않으면 모호성을 제거해야합니다. 예를 들어 단일 식별자가 exp이어야한다고 결정한 경우 최상위 식별자 목록에 적어도 두 개의 식별자가 있어야한다고 주장 할 수 있습니다.

+0

식별자 대신 ident_lists에 관심이 있다면'exp'와 같은데 꽤 기괴한 결과를 얻을 수 있습니다. – cHao

+0

@cHao : 실제로 그렇지만 그렇게하지는 않습니다. 최상위 레벨 이외에,'ident_list'는 선언문에서만 사용되며'ident'와 혼동 될 수 없습니다. – rici

+0

'progrem'도'exp' 일 수 있습니다. 'exp' 또는'ident_list' 일 수 있다면, 단일 식별자는 무엇으로 파싱됩니까? – cHao