为什么我会遇到冲突:1 班次/减少

发布于 2024-10-03 09:03:15 字数 2579 浏览 7 评论 0原文

我是野牛新手,我收到“冲突: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 文件 测试.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 */;

%%

I'm new to bison and I'm getting a "conflicts: 1 shift/reduce" error. Can anyone shed some light on this?

Here's the y file.

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();
}

Here's the lex file
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 */;

%%

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萌辣 2024-10-10 09:03:15

bison -r test.y 将编写一个文件 test.output,其中包含生成的状态机的详细描述,使您可以查看正在发生的情况 - 例如状态发生移位/归约冲突。

就您而言,问题出在启动状态(对应于您的启动非终端,inputs)。假设第一个标记是 VAR_LOCAL。您的解析器可以做两件事:

  • 它可以匹配变量大小写。
  • 它还可以匹配 inputs stmt WS_LINEBRK 情况:inputs 匹配空字符串(第一行),stmt 匹配 variable "= “exps

对于野牛解析器使用的前瞻这一单一标记,我们无法判断。你需要改变你的语法来摆脱这种情况。

bison -r test.y will write a file test.output with a detailed description of the generated state machine that allows you to see what's going on - such as the state where the shift/reduce conflict occurs.

In your case, the problem is in the start state (corresponding to your start nonterminal, inputs). Say the first token is VAR_LOCAL. There's two things your parser could do:

  • It could match the variable case.
  • It could also match the inputs stmt WS_LINEBRK case: inputs matches the empty string (first line), and stmt matches variable "=" exps.

With the one token of lookahead that bison parsers use, there's no way to tell. You need to change your grammar to get rid of this case.

半世蒼涼 2024-10-10 09:03:15

要修复语法,正如 Fabian 建议的那样,将变量文字输入移动到exps的末尾

inputs: 
    | variable
    | literal 

exps:
...
    | variable
    | literal

这允许使用 x= y,x="aliteral" 语法。

要允许空输入行,请将 /* 空标记 */ 规则更改为 WS_LINEBREAK

inputs: WS_LINEBRK
    | stmt WS_LINEBRK
    | inputs stmt WS_LINEBRK
    ;

另一方面,由于扫描器仍会查找 SYMB em>_ 等于 ;但解析器不再定义它(它被注释掉),需要做一些事情才能编译。一种选择是取消注释 %token 定义并使用 SYMB_ EQUAL 而不是解析器 .y 文件中的文字“=”。

To fix the grammar, as Fabian has suggested, move the variable and literal to the end of exps from inputs

inputs: 
    | variable
    | literal 

exps:
...
    | variable
    | literal

That allows x= y,x="aliteral" syntax.

To allow for empty input lines, change the /* empty token */ rule to WS_LINEBREAK:

inputs: WS_LINEBRK
    | stmt WS_LINEBRK
    | inputs stmt WS_LINEBRK
    ;

On another note, since the scanner still looks for the SYMB_ EQUAL ; but the parser no longer defines it (its commented out), something needs to be done in order to compile. One option is to uncomment the %token definition and use SYMB_ EQUAL instead of the literal "=" in the parser .y file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文