警告:由于冲突,规则在解析器中无用:$ @ 1:/ * empty * /

时间:2017-10-22 07:16:55

标签: parsing syntax bison yacc shift-reduce-conflict

当我在规则的中间放置代码{printf(“something”);}时,我有这个警告,如果我放在规则的末尾,我没有错误,一切正常。< / p>

这会在tittle中抛出警告并抛出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");};

这不会抛出警告和0冲突,工作正常

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");};
%%

抱歉我的英语不好(如果你能用西班牙语回答,那就更好了)

2 个答案:

答案 0 :(得分:1)

bison manual解释了这种情况。基本上,使用中规则操作(MRA) - 即规则中间的操作 - 会降低解析器将减少决策推迟到规则末尾的能力。实际上,在解析中的那一点,语法必须是可预测的,就像它是LL(1)语法一样。因此,只有在必要时才应使用MRA。

具体而言,请考虑以下两个备选方案(截断):

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

现在,假设解析器只识别ID,输入流中的下一个标记为ASIG。此时,解析器需要决定是否执行MRA { printf("something"); }。在幕后,执行MRA与减少标记非终端(右侧为空的终端)相同,因此解析器必须决定是否执行缩减。但它还没有足够的信息;在看到 ASIG之后的令牌是否为CTE_STRING之前,无法做出决定。所以解决方案需要两个先行令牌。

这是一个转移/减少冲突:解析器无法决定是否转移 ASIG或减少标记(执行MRA)。由于bison / yacc解析器总是通过移位解决移位/减少冲突,因此减少将永远不会发生; MRA无法执行,包含它的右侧被有效阻止。因此警告。

请注意,您无法通过在两个点插入相同的MRA来解决问题:

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

即使MRA相同,bison / yacc也会为这两个规则插入不同的标记,这会产生减少/减少冲突。通过选择输入文件中较早出现的缩减来解决减少/减少冲突,因此分辨率将与文件中的默认分辨率不同,但它仍会阻止一个(或多个)规则,因此您仍会看到相同的警告。

如果您只是想看看解析器正在做什么,我强烈建议您删除所有这些printfs,而是依赖于bison's built-in trace facility,这非常容易启用(和禁用),以及更全面地了解了解析的进展情况。

答案 1 :(得分:0)

解决这种冲突的一种优雅方式,尤其是当两个动作相同时,是使用一个空的产生式和一​​个称为子例程的动作。

subroutine:
  %empty  { prepare_for_local_variables (); }
;

compound:
  subroutine '{' declarations statements '}'
| subroutine '{' statements '}'
;

这里有更多信息: https://www.gnu.org/software/bison/manual/html_node/Mid_002dRule-Conflicts.html#Mid_002dRule-Conflicts