Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么我的bison/flex不能按预期工作?_C_Linux_Bison_Flex Lexer - Fatal编程技术网

C 为什么我的bison/flex不能按预期工作?

C 为什么我的bison/flex不能按预期工作?,c,linux,bison,flex-lexer,C,Linux,Bison,Flex Lexer,我有一个家庭作业,我必须把一些输入转换成一个特定的输出。我遇到的问题是,我只能将第一行转换为所需的输出,其他行返回“语法错误”错误 此外,如果我更改行顺序,则不会转换任何行,因此只有一个特定的行在工作 这是我的输入文件: 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,

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

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

这是我的输入文件:

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
这是我应该得到的输出:

输出

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.h”
#包括
int-yylex();
int计数器=0;
接种成本=10;
%}
%联合{
字符*代码;
字符*名称;
浮动值;
整数;
};
%令牌逗号权重日期服务
%令牌码
%令牌名
%代币价值
%代币数量
%类型名
%键入
code
%类型值
%类型数量
%类型服务
%开始
%%
开始:/*空*/
|畜生
;
动物:代码名重量日期服务{printf(“%s(%s)已支付%d服务/疫苗%.2f\n“,$2$1,计数器,$5);计数器=0;}
|代码名日期服务{printf(“%s(%s)已支付%d个服务/疫苗%.2f\n“,$2$1,计数器$4);计数器=0;}
;
服务:服务逗号服务值{$$=$1+$4;计数器++;}
|服务逗号疫苗数量{$$=$1+$4*疫苗成本;计数器++;}
|服务值{$$=$2;计数器++;}
|疫苗价值
{$$=$2*接种成本;计数器++;}
;
%%
int main(){
yyparse();
返回0;
}
无效错误(字符常量*s){
fprintf(标准字符,“%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;

%%
%选项noyywrap
%{
#包括“file.h”
#包括“file.tab.h”
#包括
#包括
%}
/*图案*/
第20年[0-9]{2}
第0个月[1-9]| 1[0-2]
第0天[1-9]|[1-2][0-9]| 3[0-1]
%%
,{返回逗号,;}
[A-Z][0-9]{4}{yylval.code=strdup(yytext);返回代码;}
[A-Z][A-Z]*{yylval.name=strdup(yytext);返回名称;}
[0-9]+[.][0-9]{返回权重;}
{年}/{月}/{日}{返回日期;}
(巴尼奥|马萨吉姆|托斯基亚){回程服务;}
[0-9]+\.[0-9]{2}{yylval.value=atof(yytext);返回值;}
(V8 | V10 |抗狂犬病|贾第鞭毛虫|投掷|钩端螺旋体){返回疫苗;}
[1-9]{yylval.quantity=atoi(yytext);返回数量;}
\n
.       
返回0;
%%
以下是我执行的命令:

bison -d file.y
flex -o file.c file.flex
gcc file.tab.c file.c -o exec -lfl
./exec < Input.txt
bison-d文件.y
flex-o file.c file.flex
gcc file.tab.c file.c-o exec-lfl
./exec
有人能给我指出正确的方向或告诉我我的代码有什么问题吗


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

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

  • 您的顶级语法最多只接受一个
    动物

    inicio: /*vazio*/
        | animal
    
    因此,不允许包含多行的输入。您需要一个可接受任意数量的
    animal
    s的顶层。(顺便说一下,现代bison版本允许您将
    %empty
    作为空产品的右侧,而不必(错误地)使用注释

  • 扫描仪规则的顺序意味着您想识别为
    VACINA
    的大多数单词将被识别为
    NOME
    。回想一下,当两个模式匹配同一标记时,文件中的第一个模式将获胜。因此使用这些规则:

    [A-Z][a-z]*          {yylval.nome = strdup(yytext); return NOME;}
    (V8|V10|Anti-Rabatica|Giardiase|Tosse|Leptospirose)          {return VACINA;}
    
    可以匹配任一规则的
    town
    标记将被假定与第一个规则匹配。只有不匹配的V8和Anti-rabatic将落入第二个规则。因此,第一个输入行不会触发此问题,但所有其他输入行都会触发此问题

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

    最后

    <<EOF>> return 0;
    
    返回0;
    

    是不必要的。默认情况下,扫描仪就是这样处理fike结束的。
    规则通常是多余的,应该只在明确需要时使用(并且要非常小心)。

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

  • 您的顶级语法最多只接受一个
    动物

    inicio: /*vazio*/
        | animal
    
    因此,包含多行的输入是不允许的。您需要一个顶层,它可以接受任意数量的
    动物
    。(顺便说一下,现代野牛版本允许您将
    %empty
    作为空产品的右侧,而不必(错误地)使用注释

  • 扫描仪规则的顺序意味着您想识别为
    VACINA
    的大多数单词将被识别为
    NOME
    。回想一下,当两个模式匹配同一标记时,文件中的第一个模式将获胜。因此使用这些规则:

    [A-Z][a-z]*          {yylval.nome = strdup(yytext); return NOME;}
    (V8|V10|Anti-Rabatica|Giardiase|Tosse|Leptospirose)          {return VACINA;}
    
    可以匹配任一规则的
    town
    标记将被假定与第一个规则匹配。只有不匹配的V8和Anti-rabatic将落入第二个规则。因此,第一个输入行不会触发此问题,但所有其他输入行都会触发此问题

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

    最后

    <<EOF>> return 0;
    
    返回0;
    
    是不必要的。默认情况下,扫描器就是这样处理菲克的结尾的。
    规则经常被写入或重新写入