【问题标题】:Why is my bison/flex not working as intended?为什么我的 bison/flex 没有按预期工作?
【发布时间】:2019-08-28 20:41:41
【问题描述】:

我有一个家庭作业,我必须将一些输入转换为特定的输出。我遇到的问题是我只能将第一行转换为我需要的输出,其他行返回“语法错误”错误。

此外,如果我更改行顺序,则不会转换任何行,因此只有一个特定的行在工作。

这是我的输入文件:

Input.txt

B0102 Bobi 2017/01/16 V8 1, massage 12.50
J1841 Jeco 20.2 2017/01/17 V8 2, Tosse 2, tosquia 22.50
B2232 Bobi 2017/01/17 Tosse 1, Leptospirose 1, bath 30.00, massage 12.50
B1841 Jeco 21.4 2017/01/18 Leptospirose 1, Giardiase 2

这是我应该得到的输出:

输出

Bobi (B0102) paid 2 services/vaccines 22.50
Jeco (J1841) paid 3 services/vaccines 62.50
Bobi (B2232) paid 4 services/vaccines 62.50
Jeco (B1841) paid 2 services/vaccines 30.00

如果我更改输入文件中的行顺序,甚至第一行都不会被转换。 但是,如果顺序如上所示,这是我的输出:

Bobi (B0102) paid 2 services/vaccines 22.50
syntax error

这是我的代码:

file.y

%{
    #include "file.h"
    #include <stdio.h>
    int yylex();
    int counter = 0;
    int vaccineCost = 10;
%}

%union{
    char* code;
    char* name;
    float value;
    int quantity;
};

%token COMMA WEIGHT DATE SERVICE VACCINE
%token CODE
%token NAME
%token VALUE
%token QUANTITY

%type <name> NAME
%type <code> CODE
%type <value> VALUE
%type <quantity> QUANTITY
%type <value> services


%start begining

%%

begining: /*empty*/
    | animal
    ;

animal: CODE NAME WEIGHT DATE services {printf("%s (%s) paid %d services/vaccines %.2f\n", $2, $1, counter, $5); counter = 0;}
    | CODE NAME DATE services {printf("%s (%s) paid %d services/vaccines %.2f\n", $2, $1, counter, $4); counter = 0;}
    ;

services: services COMMA SERVICE VALUE {$$ = $1 + $4; counter++;}
    | services COMMA VACCINE QUANTITY{$$ = $1 + $4*vaccineCost;counter++;}
    | SERVICE VALUE{$$ = $2;counter++;}
    | VACCINE VALUE 
{$$ = $2*vaccineCost;counter++;}
    ;

%%

int main(){
    yyparse();
    return 0;
}

void yyerror (char const *s) {
    fprintf (stderr, "%s\n", s);
}

file.flex

%option noyywrap

%{
    #include "file.h"
    #include "file.tab.h"
    #include <stdio.h>
    #include <string.h>
%}

/*Patterns*/
YEAR 20[0-9]{2}
MONTH 0[1-9]|1[0-2]
DAY 0[1-9]|[1-2][0-9]|3[0-1]

%%
,                                   {return COMMA,;}
[A-Z][0-9]{4}            {yylval.code = strdup(yytext); return CODE;}       
[A-Z][a-z]*          {yylval.name = strdup(yytext); return NAME;}
[0-9]+[.][0-9]                             {return WEIGHT;}
{YEAR}"/"{MONTH}"/"{DAY}                           {return DATE;}
(banho|massagem|tosquia)                    {return SERVICE;}
[0-9]+\.[0-9]{2}              {yylval.value = atof(yytext);return VALUE;}
(V8|V10|Anti-Rabatica|Giardiase|Tosse|Leptospirose)          {return VACCINE;}
[1-9]           {yylval.quantity = atoi(yytext);return QUANTITY;}
\n  
.       
<<EOF>> return 0;

%%

这些是我执行的命令:

bison -d file.y
flex -o file.c file.flex
gcc file.tab.c file.c -o exec -lfl
./exec < Input.txt

谁能指出我正确的方向或告诉我我的代码有什么问题?

谢谢,如果我的解释不够好,我会尽力解释得更好!!

【问题讨论】:

  • 请将 %define parse.error verbose 添加到您的 bison 文件的顶部以启用更好的错误消息,然后发布您使用该选项获得的扩展语法错误消息。另外请考虑将您的令牌和非终端名称翻译成英文,以便更容易理解您的代码。
  • 对不起,我会翻译....我添加了你说的那一行,我得到了这个输出:syntax error, unexpected $undefined, expecting $end
  • 不要将VIRGULA翻译成COMMA,而是考虑使用',',它不需要翻译,而且更清晰。
  • 那么 flex 文件呢?我是删除 COMMA 条目还是保留它?

标签: c linux bison flex-lexer


【解决方案1】:

至少有两个不同的问题会导致这些症状。

  1. 您的顶级语法最多只接受一个animal

    inicio: /*vazio*/
        | animal
    

    因此不允许输入包含多于一行。您需要一个接受任意数量的animals 的顶层。 (顺便说一句,现代野牛版本让您可以将%empty 写为空作品的右侧,而不必(错误)使用评论。

  2. 扫描器规则的顺序意味着您想要识别为VACINA 的大部分单词将被识别为NOME。回想一下,当两个模式匹配相同的标记时,文件中的第一个将获胜。所以有了这些规则:

    [A-Z][a-z]*          {yylval.nome = strdup(yytext); return NOME;}
    (V8|V10|Anti-Rabatica|Giardiase|Tosse|Leptospirose)          {return VACINA;}
    

    Tosse 这样可以匹配任一规则的标记将被假定匹配第一个规则。只有[A-Z][a-z]* 不匹配的 V8 和 Anti-Rabatical 将落入第二条规则。所以你的第一行输入不会触发这个问题,但所有其他的都会触发。

您可能应该在语法上处理换行符,除非您允许将处理记录拆分为多行。请注意,许多 (f)lex 版本不允许空操作,如您的最后两个 flex 规则。这可能会导致词法错误。

最后

<<EOF>> return 0;

是不必要的。这就是扫描仪默认处理 end-of-fike 的方式。 &lt;&lt;EOF&gt;&gt; 规则通常是错误的或多余的,只有在明确需要时才应使用(并且非常小心)。

【讨论】:

  • 1.如果我这样做begining: | begining '\n' animal,我会实现它吗?
  • 2.我理解我的错误,我会修复它并发布结果...感谢您的回复!
  • 我成功了!都谢谢你!!谢谢你的回答:)
猜你喜欢
  • 1970-01-01
  • 2020-02-29
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-04
  • 2021-01-03
  • 2018-11-08
相关资源
最近更新 更多