转移/减少Yacc / Flex中的冲突

时间:2013-05-22 23:39:18

标签: c yacc flex-lexer lr

我在yacc中有这个语法:

%{
    #include <stdio.h>
%}

%token texto SEP ERRO word

%start Ini

%%

Ini: Directivas SEP SEP Conceitos '$'
            { printf("Terminou bem...\n"); return 0; };

Directivas: Directiva
          | Directivas SEP Directiva
          ;

Conceitos: Conceito
         | Conceitos SEP SEP Conceito
         ;

Conceito: word SEP Atributos;

Atributos: Atributo
         | Atributos SEP Atributo
         ;

Directiva: texto;
Atributo: '-' texto;

%%

int main(){
    yyparse();
}

int yyerror(char *s){
    fprintf(stderr, "%s\n", s);
}

在flex中:

%{
    #include "y.tab.h"
%}

%%

[a-zA-Z]+           return word;

[a-zA-Z ]+          return texto;

\-                  return '-';

\n                  return SEP;

[ \t]               ;

.                   return ERRO;

<<EOF>>             return '$';

我想做一个像以下那样的解析:

text line
text line
text line

word
-text line
-text line
-text line

word
-text line

其中第一行是'Directivas'然后是一个空白行,然后是'Conceitos',其中一个Conceito是一个单词,后面是几个文本行,在开头有一个' - '。那些'Conceitos被一个空行隔开

但它找到了一个转移/减少混乱..我是新的,我无法找到原因

抱歉我的英文

谢谢

1 个答案:

答案 0 :(得分:2)

使用yacc(或bison's)-v选项获取生成的解析器的完整列表以及y.output文件中的语法冲突。当你用你的语法做这件事时,你会得到类似的东西(来自野牛):

State 16 conflicts: 1 shift/reduce
        :
state 16

    6 Conceito: word SEP Atributos .
    8 Atributos: Atributos . SEP Atributo

    SEP  shift, and go to state 20

    SEP       [reduce using rule 6 (Conceito)]
    $default  reduce using rule 6 (Conceito)

这可以准确地告诉您冲突的确切位置 - 在减少Attributos并查看SEP前瞻后,解析器不知道它是否应该将SEP转换为解析另一个Atributo之后,或者缩小Conceito,只有在SEP之后还有另一个SEP(需要两个令牌前瞻)时才会有效。

避免这种情况的一种方法是让你的词法分析器将多个SEP(空行)作为单个标记返回:

\n      return SEP;
\n\n    return SEP_SEP;

您可能希望允许空白行上的空格或多个空行:

\n([ \t]*\n)+  return SEP_SEP;