2017-10-22 13 views
0

규칙의 중간에 코드 {printf ("something");}를 넣을 때이 경고 메시지가 표시됩니다. 규칙의 끝, 나는 오류가 없어 모든 것이 잘 작동한다.

이것을 획에 경고를 던져 1 개 교대를 던져/충돌을

sent_asig: ID {printf("something");} ASIG exp {printf("sent_asig: ID ASIG exp \n");} 
| ID ASIG CTE_STRING {printf("sent_asig: ID ASIG CTE_STRING \n");} 
| ID ASIG CTE_STRING CONCAT ID {printf("sent_asig: ID ASIG CTE_STRING CONCAT ID \n");} 
| ID ASIG ID CONCAT CTE_STRING {printf("sent_asig: ID ASIG ID CONCAT CTE_STRING \n");}; 

을 줄이고이 경고와 공의 충돌을 포기하지, 잘 작동

sent_asig: ID ASIG exp {printf("sent_asig: ID ASIG exp \n");} 
| ID ASIG CTE_STRING {printf("sent_asig: ID ASIG CTE_STRING \n");} 
| ID ASIG CTE_STRING CONCAT ID {printf("sent_asig: ID ASIG CTE_STRING CONCAT ID \n");} 
| ID ASIG ID CONCAT CTE_STRING {printf("sent_asig: ID ASIG ID CONCAT CTE_STRING \n");}; 

누군가가하고자하는 경우 다른 부분에서이 오류의 원인이 아마도 여기에 있기 때문에 전체 규칙을 참조하십시오. 여기에

%token ID 
%token CTE 
%token ABREPAR 
%token FINPAREN 
%token AND 
%token OR 
%token COMA 
%token ASIG 
%token COMP 
%token RESTASIG 
%token CONCAT 
%token SUMASIG 
%token MULTASIG 
%token DIVASIG 
%token MENOR_IGU 
%token MENOR 
%token MAYOR_IGU 
%token MAYOR 
%token NOT 
%token DIST 
%token CTE_REAL 
%token CTE_STRING 

%token DO 
%token IF 
%token ENDIF 
%token ELSE 
%token PUT 
%token GET 
%token DECLARE 
%token ENDDECLARE 
%token BEGIN 
%token ENDPROGRAM 
%token INT 
%token REAL 
%token STRING 
%token REPEAT 
%token CONST 

%left AND OR 
%left OP_SUM OP_RESTA 
%left OP_MULT 
%left OP_DIV 
%right ASIG 
%right SUMASIG 
%right RESTASIG 
%right MULTASIG 
%right DIVASIG 

%% 

programa: BEGIN declar sentencias ENDPROGRAM {printf("programa: BEGIN declar sentencias ENDPROGRAM \n");} 
| BEGIN sentencias ENDPROGRAM {printf("programa: BEGIN sentencias ENDPROGRAM \n");}; 

sentencias: sentencia {printf("sentencia: sentencia \n");} 
    | sentencias sentencia {printf("sentencias: sentencia \n");}; 
sentencia: sent_asig {printf("sentencia: sent_asig\n");} 
    | sent_mult_asig {printf("sentencia: sent_mult_asig\n");} 
    | sent_sum_asig {printf("sentencia: sent_sum_asig");} 
    | sent_rest_asig {printf("sentencia: sent_rest_asig \n");} 
    | sent_div_asig {printf("sentencia: sent_div_asig \n");} 
    | asig_const {printf("sentencia: asig_const \n");} 
    | entrada {printf("sentencia: entrada \n");} 
    | salida {printf("sentencia: salida \n");} 
    | sent_if {printf("sentencia: sent_if \n");} 
    | sent_repeat {printf("sentencia: sent_repeat \n");}; 
sent_asig: ID {printf("something");} ASIG exp {printf("sent_asig: ID ASIG exp \n");} 
    | ID ASIG CTE_STRING {printf("sent_asig: ID ASIG CTE_STRING \n");} 
    | ID ASIG CTE_STRING CONCAT ID {printf("sent_asig: ID ASIG CTE_STRING CONCAT ID \n");} 
    | ID ASIG ID CONCAT CTE_STRING {printf("sent_asig: ID ASIG ID CONCAT CTE_STRING \n");}; 
exp:  exp OP_SUM ter {printf("exp: exp OP_SUM ter\n");escribirPolaca("+");} 
    | exp OP_RESTA ter {printf("exp: exp OP_RESTA ter\n");escribirPolaca("-");} 
    | ter {printf("exp: ter\n");}; 

ter: ter OP_MULT factor {printf("ter: ter OP_MULT factor\n");escribirPolaca("*");} 
    | ter OP_DIV factor {printf("ter: ter OP_DIV factor\n");escribirPolaca("/");} 
    | factor {printf("ter: factor\n");}; 
factor: ID {printf("factor: ID\n"); escribirPolaca(Simbolos[nosalemal][0]);} 
    | CTE {printf("factor: CTE\n");escribirPolaca(Simbolos[nosalemal][1]);} 
    | CTE_REAL {printf("factor: CTE_REAL \n");escribirPolaca("CTE_REAL");}; 
    | ABREPAR exp FINPAREN {printf("factor: ABREPAR exp FINPAREN\n");} 
sent_sum_asig : ID SUMASIG ID {printf("factor: sent_sum_asig \n");} 
    | ID SUMASIG CTE {printf("factor: ID SUMASIG CTE \n");} 
    | ID SUMASIG CTE_REAL {printf("factor: ID SUMASIG CTE_REAL \n");} ; 
sent_rest_asig : ID RESTASIG ID {printf("sent_rest_asig: ID RESTASIG ID \n");} 
    | ID RESTASIG CTE {printf("sent_rest_asig: ID RESTASIG CTE \n");} 
    | ID RESTASIG CTE_REAL {printf("sent_rest_asig: ID RESTASIG CTE_REAL \n");}; 
sent_mult_asig : ID MULTASIG ID {printf("sent_mult_asig: ID MULTASIG ID \n");} 
    | ID MULTASIG CTE {printf("sent_mult_asig: ID MULTASIG CTE \n");} 
    | ID MULTASIG CTE_REAL {printf("sent_mult_asig: ID MULTASIG CTE_REAL \n");}; 
sent_div_asig : ID DIVASIG ID {printf("sent_div_asig: ID DIVASIG ID \n");} 
    | ID DIVASIG CTE {printf("sent_div_asig : ID DIVASIG ID \n");} 
    | ID DIVASIG CTE_REAL {printf("sent_div_asig: ID DIVASIG ID \n");}; 
declar: DECLARE declaraciones ENDDECLARE {printf("declar: DECLARE declaraciones ENDDECLARE \n");}; 
declaraciones: dec {printf("declaraciones: dec \n");} 
    | dec declaraciones {printf("declaraciones: dec declaraciones \n");}; 
dec: REAL var {printf("dec: REAL var \n");} 
    | INT var {printf("dec: INT var \n");} 
    | STRING var {printf("dec: STRING var \n");} ; 
var: ID {printf("var: ID \n");} 
    | ID COMA var {printf("var: ID COMA var \n");}; 
asig_const: CONST ID ASIG CTE {printf("asig_const: CONST ID ASIG CTE \n");} 
    | CONST ID ASIG CTE_REAL {printf("asig_const: CONST ID ASIG CTE_REAL \n");} 
    | CONST ID ASIG CTE_STRING {printf("asig_const: CONST ID ASIG CTE_STRING \n");}; 
entrada: PUT CTE_STRING {printf("entrada: PUT CTE_STRING \n");} 
    | PUT ID {printf("entrada: PUT ID \n");}; 
salida: GET ID {printf("salida: GET ID \n");}; 
sent_if: IF ABREPAR condicion FINPAREN sentencias ENDIF {printf("sent_if: IF ABREPAR condicion FINPAREN sentencias ENDIF \n");} 
    | IF ABREPAR condicion FINPAREN sentencias ELSE sentencias ENDIF {printf("sent_if: IF ABREPAR condicion FINPAREN sentencias ELSE sentencias ENDIF \n");} 
condicion: cond {printf("condicion: cond \n");} 
    | cond AND cond {printf("condicion: cond AND cond\n");} 
    | cond OR cond {printf("condicion: cond OR cond \n");} 
    | NOT cond {printf("condicion: NOT cond \n");}; 
cond: exp MENOR exp {printf("cond: exp MENOR exp \n");apilarPilaIteracion(posicionVectorPolaca);escribirPolaca("CMP");posicionVectorPolaca++;} 
    | exp MAYOR exp {printf("cond: exp MENOR exp \n");} 
    | exp MENOR_IGU exp {printf("cond: exp MENOR exp \n");} 
    | exp MAYOR_IGU exp {printf("cond: exp MENOR exp \n");} 
    | exp COMP exp {printf("cond: exp MENOR exp \n");escribirPolaca("CMP");} 
    | exp DIST exp {printf("cond: exp MENOR exp \n");} 
sent_repeat: DO sentencias REPEAT ABREPAR condicion FINPAREN {printf("sent_repeat: DO sentencias REPEAT ABREPAR condicion FINPAREN \n");}; 
%% 

죄송합니다. 영어 불쾌 함 (스페인어로 더 잘 답변 할 수 있다면)

답변

1

이 상황은 bison manual에 설명되어 있습니다. 기본적으로 규칙 중간의 작업 인 중간 규칙 작업 (MRA)을 사용하면 구문 분석기가 규칙의 끝까지 감축 결정을 연기 할 수있는 기능이 줄어 듭니다. 사실 구문 분석의 그 시점에서 문법은 마치 LL (1) 문법처럼 예측 가능해야합니다. 이러한 이유로 엄격하게 필요한 경우에만 MRA를 사용해야합니다. 단지 ID 입력 스트림 내의 다음의 토큰 ASIG입니다 인식

이제
sent_asig: ID {printf("something");} ASIG exp … 
     | ID ASIG CTE_STRING … 

, 파서를 가정 :

는 구체적으로, 단지 다음과 같은 두 가지 대안 (절단)을 고려한다. 이 시점에서 파서는 MRA { printf("something"); }을 수행할지 여부를 결정해야합니다. 뒤에서 마커 비 터미널 (오른쪽이 비어있는 터미널)을 줄이는 것과 MRA를 수행하는 것과 동일하므로 파서는 축소를 수행할지 여부를 결정해야합니다. 그러나 아직 충분한 정보가 없습니다. 토큰 ASIG이면 CTE_STRING인지 여부를 확인할 때까지는 결정할 수 없습니다. 따라서 해결에는 두 개의 미리보기 토큰이 필요합니다.

이동/축소 충돌입니다. 파서는 ASIG으로 이동할지 또는 MRA를 실행할지 결정할 수 없습니다. bison/yacc 파서는 항상 시프트를 통해 시프트/감소 충돌을 해결하기 때문에 절대로 감소하지 않습니다. MRA는 실행될 수 없으며 MRA를 포함하는 오른쪽이 효과적으로 차단됩니다. 그러므로 경고. 당신이 두 지점에서 같은 MRA를 삽입하여 문제를 해결할 수 없습니다

참고 :

MRAS이 동일하더라도, 들소/Yacc에은을 만들 것 두 가지 규칙에 대해 다른 마커를 삽입
sent_asig: ID {printf("something");} ASIG exp … 
     | ID {printf("something");} ASIG CTE_STRING … 

충돌을 줄이거 나 줄일 수 있습니다. 줄이기/줄이기 충돌은 입력 파일의 앞부분에 나타나는 축소를 선택하여 해상도가 파일의 기본 해상도와 다를 수 있지만 여전히 하나 이상의 (또는 그 이상의) 규칙을 차단하므로 여전히 동일하게 나타납니다 경고. 당신은 단지 파서가 무엇을하고 있는지 확인하려는 경우


, 나는 강하게 당신이 그 printfs을 모두 제거하고 사용이 매우 간편하다, bison's built-in trace facility 대신에 의존 (비활성화) 제안하고있는 구문 분석이 어떻게 진행되고 있는지 훨씬 더 완벽하게 보여줍니다.