首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >bison shift而不是reduce使用reduce/reduce错误

bison shift而不是reduce使用reduce/reduce错误
EN

Stack Overflow用户
提问于 2009-11-19 21:19:42
回答 3查看 1.2K关注 0票数 2

我可以用我的语言写

代码语言:javascript
复制
a = 1

b = 2
if true { } else { }
if true { } **Here is the problem**
else {}

我的语法不支持语句之间的换行符。else只能与if一起使用。当我在规则中添加optionalNL时

代码语言:javascript
复制
IfExpr:
  IF rval optionalNL codeBlock optionalNL ELSE codeBlock
| IF rval optionalNL codeBlock

else之前的optionalNL导致3个reduce/reduce。原因是它可以减少使用IfExpr中的第二个规则,或者减少到exprLoop,其中它允许在表达式之间有许多换行符。

无论我做什么(我试着在optionalNL之前写%prec,或者其他),它总是减少到exprLoop,这会在bison上给我一个同步错误。我如何告诉bison在这一点上转移(到optionalNL else)而不是reduce?(to exprLoop导致else是一个错误)。

用于测试的示例文件

代码语言:javascript
复制
%%
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.output http://www.pastie.org/707448

备用.y和输出。你可以看到它向前看,看到一个\n,不知道是减少规则还是继续前进。我改变了规则的顺序以获得不同的结果。但它要么总是期望\n,要么总是期望其他值,因此一个规则总是被忽略。状态15

代码语言:javascript
复制
    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)

感谢his answer的Kinopiko

我更改了他的代码,使其没有冲突,然后努力使其更灵活。这是我的档案

test.y

代码语言:javascript
复制
%{
#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;
}

test.y

代码语言:javascript
复制
%{
#include <stdio.h>
#include "y.tab.h"
%}    
%option noyywrap
%%
[ \t]               { }
\n                  { return *yytext; }
.                   { return *yytext; }
%%
int yyerror ()
{
    printf ("syntax error\n");
    exit (1);
}

编译后自动运行的测试文件

代码语言:javascript
复制
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 
{ }
EN

回答 3

Stack Overflow用户

发布于 2009-11-21 10:39:48

根据'Lex & Yacc‘,reduce/reduce的默认解析是第一个定义的规则,所以正如您所说的,exprLoop获胜,所以我将假设它是首先定义的。

但是,改变顺序可能不会像您期望的那样解决问题。

进一步阅读(第237页)似乎你需要更多地向前看,这不是标准yacc/bison的选项。但野牛确实有一个GLR mode,这可能是有用的。

票数 1
EN

Stack Overflow用户

发布于 2009-11-21 11:39:25

您可以做的一件事是完全使用lex规则解析出换行符。这样,换行符在哪里就无关紧要了。这就是C/C++做的.换行符在很大程度上被忽略。

票数 0
EN

Stack Overflow用户

发布于 2009-11-23 03:54:03

问题是:

代码语言:javascript
复制
IfExpr:
  IF rval optionalNL codeBlock optionalNL ELSE codeBlock
| IF rval optionalNL codeBlock

在代码块之后需要两个标记的先行查找,才能看到换行符后面的'else‘。您可以通过在两个if规则中复制optionalNL来避免这种情况:

代码语言:javascript
复制
IfExpr:
  IF rval optionalNL codeBlock optionalNL ELSE codeBlock
| IF rval optionalNL codeBlock optionalNL

现在,在解析optionalNL之前,解析器不必在两个规则之间做出决定,让它在单令牌先行查找中看到ELSE (或它的缺失)。

这里的一个潜在缺点是,第二个if规则(但不是第一个)现在将吸收所有尾随的换行符,因此如果您的程序语法需要在每条语句之间换行,那么它不会在没有elses的if后面找到一个,并且它已经被使用了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1763243

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档