我在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被一个空行隔开
但它找到了一个转移/减少混乱..我是新的,我无法找到原因
抱歉我的英文
谢谢
答案 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;