我是野牛新手,我遇到了“冲突:1班/减少”的错误。任何人都可以对此有所了解吗?
这是y文件。
test.y:
%{
#include <stdio.h>
#include <string.h>
#define YYERROR_VERBOSE
#define YYDEBUG 1
void yyerror(const char *str);
int yywrap();
%}
%union
{
int integer;
char *string;
}
%token <string> VAR_LOCAL
%token <integer> LIT_NUMBER
%token <string> LIT_STRING
%token WS_LINEBRK
//%token SYMB_EQL
%token SYMB_PLUS
%token SYMB_MINUS
%token SYMB_MUL
%token SYMB_DIV
%%
/*
// Sample input
num = 10
str = "this is a string"
*/
inputs: /* empty token */
| literal
| variable
| inputs stmt WS_LINEBRK
;
stmt: variable "=" exps
;
exps: variable op literal
| variable op variable
| literal op literal
| literal op variable
;
op: SYMB_PLUS | SYMB_MINUS | SYMB_MUL | SYMB_DIV ;
variable: VAR_LOCAL
{
printf("variable: %s\n", $1);
}
;
literal:
number | string
;
string: LIT_STRING
{
printf("word: %s\n", $1);
}
;
number: LIT_NUMBER
{
printf("number: %d\n", $1);
}
;
%%
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
int yywrap()
{
return 1;
}
main()
{
yyparse();
}
这是lex文件 test.l:
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
int line_no = 0;
%}
%%
[a-z][a-zA-Z0-9]* {
// local variable
yylval.string=strdup(yytext);
return VAR_LOCAL;
}
[0-9]+ {
//number literal
yylval.integer=atoi(yytext);
return LIT_NUMBER;
}
= return SYMB_EQL;
\+ return SYMB_PLUS;
\- return SYMB_MINUS;
\* return SYMB_MUL;
\/ return SYMB_DIV;
\"[-+\!\.a-zA-Z0-9' ]+\" {
// word literal
yylval.string=strdup(yytext);
return LIT_STRING;
}
\n {
// line break
printf("\n");
return WS_LINEBRK;
}
[ \t]+ /* ignore whitespace */;
%%
答案 0 :(得分:1)
bison -r test.y
将写一个文件test.output
,其中包含生成的状态机的详细说明,可以让您查看正在发生的情况 - 例如发生转换/减少冲突的状态。
在您的情况下,问题处于开始状态(对应于您的开始非终结,inputs
)。假设第一个标记是VAR_LOCAL。解析器可以做两件事:
variable
案例。inputs stmt WS_LINEBRK
案例:inputs
匹配空字符串(第一行),stmt
匹配variable "=" exps
。使用野牛解析器使用的一个前瞻标记,没有办法说出来。你需要改变你的语法来摆脱这种情况。
答案 1 :(得分:0)
要修复语法,正如Fabian所建议的那样,将变量和 literal 从输入<移动到 exps 的末尾/ em>的
inputs:
| variable
| literal
exps:
...
| variable
| literal
这允许x= y
,x="aliteral"
语法。
要允许空输入行,请将/* empty token */
规则更改为WS_LINEBREAK
:
inputs: WS_LINEBRK
| stmt WS_LINEBRK
| inputs stmt WS_LINEBRK
;
另一方面,由于扫描仪仍然在寻找 SYMB _ EQUAL ;但是解析器不再定义它(它被注释掉),需要做一些事情来编译。一种选择是取消注释%token
定义并使用 SYMB _ EQUAL 而不是解析器.y文件中的文字“=”。