0

我在 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 由一个空行分隔

但它发现了一个转变/减少冲突..我是新来的,我不知道为什么

对不起我的英语不好

谢谢

4

1 回答 1

2

使用 yacc 的(或 bison 的)-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)

这会告诉您冲突的确切位置——在减少 an并Attributos查看前瞻之后,解析器SEP不知道它是否应该将(需要两个令牌前瞻)。SEPAtributoConceitoSEPSEP

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

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

您可能希望在空行上允许空格或多个空行代替:

\n([ \t]*\n)+  return SEP_SEP;
于 2013-05-23T01:33:29.563 回答