用我的语言我可以写
a = 1
b = 2
if true { } else { }
if true { } **Here is the problem**
else {}
我的语法不支持语句之间的换行符。 else 只能与 if 一起使用。当我在规则中添加可选NL时
IfExpr:
IF rval optionalNL codeBlock optionalNL ELSE codeBlock
| IF rval optionalNL codeBlock
else之前的可选NL会导致3个reduce/reduce。原因是它可以减少使用 IfExpr 中的第二条规则或减少到 exprLoop ,它允许表达式之间有许多换行符。
无论我做什么(我尝试在 optionNL 和 ELSE 之前编写 %prec),它总是会简化为 exprLoop,这种情况下 bison 会在 else 上给我一个语法错误。我如何告诉 Bison 此时转移(到可选的NL else)而不是减少? (exprLoop 导致 else 出错)。
用于测试的示例文件
%%
program:
exprLoop;
exprLoop:
exprLoop2 expr
| exprLoop2
exprLoop2:
| exprLoop2 expr EOS
| exprLoop2 EOS
;
expr:
'i' Var optEOS '{' '}'
| 'i' Var optEOS '{' '}' optEOS 'e' '{' '}'
EOS: '\n' ;
Var: 'v';
optEOS: | optEOS EOS
%%
//this can be added to the lex file
[iev] { return *yytext; }
y.输出http://www.pastie.org/707448
替代 .y 和输出。你可以看到它向前看,看到一个\n 并且不知道减少规则或继续。我改变规则的顺序以获得不同的结果。但它要么总是期望一个\n,要么总是期望一个 else,因此一条规则最终总是被忽略。 状态15
9 expr: 'i' Var optEOS '{' '}' . [$end, '\n']
10 | 'i' Var optEOS '{' '}' . 'e' '{' '}'
11 | 'i' Var optEOS '{' '}' . '\n' 'e' '{' '}'
'e' shift, and go to state 16
'\n' shift, and go to state 17
'\n' [reduce using rule 9 (expr)]
$default reduce using rule 9 (expr)
感谢 Kinopiko his answer
我更改了他的代码,使其不存在冲突,然后努力使其更加灵活。这是我的文件
测试.y
%{
#include <stdio.h>
%}
%%
program: expr { printf ("First expr\n"); }
| program expr { printf ("Another expr\n"); }
expr:
if optEOS { printf ("IF only\n"); }
| if optEOS else optEOS { printf ("IF/ELSE\n"); }
if: 'i' Var optEOS '{' optEOS '}'
else: 'e' optEOS '{' optEOS '}'
EOS: '\n'
Var: 'v'
optEOS:
| EOS optEOS { ;}//printf ("many EOS\n"); }
%%
int main(int argc, char **argv)
{
int i;
printf("starting\n");
if(argc < 2) {
printf("Reading from stdin\n");
yyparse();
return 0;
}
for(i = 1; i < argc; i++) {
FILE *f;
char fn[260];
sprintf(fn, "./%s", argv[i]);
f = fopen(fn, "r");
if(!f) {
perror(argv[i]);
return (1);
}
printf("Running '%s'\n", argv[i]);
yyrestart(f);
yyparse();
fclose(f);
printf("done\n");
}
return 0;
}
测试.y
%{
#include <stdio.h>
#include "y.tab.h"
%}
%option noyywrap
%%
[ \t] { }
\n { return *yytext; }
. { return *yytext; }
%%
int yyerror ()
{
printf ("syntax error\n");
exit (1);
}
编译后自动运行的测试文件
i v { }
i v { }
e { }
i v { }
e { }
i v {
} e {
}
i v { }
i v { } i v { } e { }
i v
{ } i v { } e { } i v { } e {
} i v {
} e
{ }
最佳答案
我不太明白你的问题,所以我从头开始:
这是我的语法:
%{
#include <stdio.h>
%}
%%
program: expr { printf ("First expr\n") }
| program EOS { printf ("Ate an EOS\n") }
| program expr { printf ("Another expr\n") }
expr:
ifeos { printf ("IF only\n"); }
| ifelse { printf ("IF/ELSE\n"); }
ifelse: ifeos else
| if else
ifeos: if EOS
| ifeos EOS
if: 'i' Var optEOS '{' '}'
else: 'e' '{' '}'
EOS: '\n'
Var: 'v'
optEOS:
| EOS optEOS { printf ("many EOS\n") }
%%
这是词法分析器:
%{
#include <stdio.h>
#include "1763243.tab.h"
%}
%option noyywrap
%%
[iev\{\}\n] { return *yytext; }
\x20 { }
%%
int yyerror ()
{
printf ("syntax error\n");
exit (1);
}
int main () {
yyparse ();
}
这是一些测试输入:
i v { } i v { } e { } i v { } e { } i v { } e { } i v { }
这是输出:
IF only First expr IF/ELSE Another expr Ate an EOS IF/ELSE Another expr Ate an EOS IF/ELSE Another expr Ate an EOS IF only Another expr
有一个shift/reduce conflict剩余。
关于yacc - Bison 转移而不是减少。减少/减少错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1763243/