我在 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 是一个单词,后跟几行开头为“-”的文本行。那些'自负由一个空行分隔
但它发现了一个转移/减少冲突..我是新手,我不知道为什么
对不起我的英语
谢谢
最佳答案
使用 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)
这会告诉您冲突的确切位置——在减少 Attributos
并查看 SEP
前瞻之后,解析器不知道是否应该将 SEP
解析其后的另一个 Atributo
,或者减少 Conceito
,这只有在有另一个 SEP
时才有效在 SEP
之后(需要两个 token 先行)。
避免这种情况的一种方法是让您的词法分析器将多个 SEP
(空行)作为单个标记返回:
\n return SEP;
\n\n return SEP_SEP;
您可能希望在空白行或多个空白行上允许空格:
\n([ \t]*\n)+ return SEP_SEP;
关于c - Yacc/Flex 中的移位/减少冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16703338/