野牛& flex错误

时间:2017-06-06 15:48:30

标签: bison flex-lexer

我在野牛和弯曲方面不是很有经验,我需要一些帮助。

我的.y文件中有一些错误。

语法明智它的罚款,它编译时我和B#-B"它 但是当我尝试使用gcc进行编译时,它会给我一些错误,我不确定如何解决(这里总noob):

https://i.stack.imgur.com/fUeR7.png

.lex文件:

%{
#include "meals.tab.h"
#include <string.h> 

extern void exit(int);
int line = 1;

#define VEGETABLE 1
#define FRUIT 2
#define BREAD 3
#define MEAT 4
#define CAKE 5
#define CHOCOLATE_ICE_CREAM 6
#define VANILLA_ICE_CREAM 7
#define BEGIN_MEAL 100
#define END_MEAL 101

%}

%option noyywrap

%%

"<meal>"    {return BEGIN_MEAL;}
"</meal>"   {return END_MEAL;}

"broccoli"      {return VEGETABLE;}
"lettuce"       {return VEGETABLE;}
"tomato"        {return VEGETABLE;}
"cucumber"  {return VEGETABLE;}
"orange"        {return FRUIT;}
"apple"     {return FRUIT;}
"strawberry"    {return FRUIT;}
"watermelon"    {return FRUIT;}
"chicken"       {return MEAT;}
"beef"      {return MEAT;}
"bread"     {return BREAD;}
"cake"      {return CAKE}
"chocolate ice cream"   {return CHOCOLATE_ICE_CREAM ;}
"vanilla ice cream"     {return VANILLA_ICE_CREAM ;}

","     /* skip comma */
[\t ]+      /* skip white space */
\n         { line++; }
.   { fprintf (stderr, "line %d: unrecognized token %c\n",
                               line, yytext[0]);  
                exit(1);
            }


%%

.y文件:

%code {

#include <stdio.h>

extern int yylex (void);
void yyerror (const char *s);

struct diet
}

%code requires {
    struct diet {
        int veg_fruit, dessert, calories, isDesertFine, isVeggieFine;
    };
}
%union {
    struct diet _diet;
}

%token BEGIN_MEAL END_MEAL VEGETABLE FRUIT MEAT BREAD CAKE CHOCOLATE_ICE_CREAM VANILLA_ICE_CREAM 
%type <_diet> list_of_meals meal list_of_servings serving

%error-verbose

%%

day: list_of_meals{
                    if(($1.calories <= 18) && ($1.isDesertFine == 0) && ($1.isVeggieFine == 0))
                    printf ("everything is OK\n");
                    else if($1.calories <= 18 && $1.isDesertFine == 0)
                    printf ("Not enough veggies/fruits\n");
                    else if($1.calories <= 18 && $1.isVeggieFine == 0)
                    printf ("Too many desserts\n");
                    else if($1.isDesertFine == 0 && $1.isVeggieFine == 0)
                    printf ("Too many calories: total is $1.calories\n");
                    else if($1.calories <= 18){
                    printf ("Too many desserts\n");
                    printf ("Not enough veggies/fruits\n");
                    }
                    else if($1.isDesertFine == 0){
                    printf ("Too many calories: total is $1.calories\n");
                    printf ("Not enough veggies/fruits\n");
                    }
                    else if($1.isVeggieFine == 0){
                    printf ("Too many desserts\n");
                    printf ("Too many calories: total is $1.calories\n");
                    }
                    else{
                    printf ("Too many calories: total is $1.calories\n");
                    printf ("Too many desserts\n");
                    printf ("Not enough veggies/fruits\n");
                    }
                    };

list_of_meals: list_of_meals meal {$$.calories = $1.calories + $2.calories;
                                    $$.isDesertFine = $1.isDesertFine + $2.isDesertFine;
                                    $$.isVeggieFine = $1.isVeggieFine + $2.isVeggieFine;};

list_of_meals:  /*empty*/ {$$.calories = -1;
                                $$.veg_fruit = -1;
                                $$.dessert = -1;
                                $$.isVeggieFine = 1;
                                };
meal: BEGIN_MEAL list_of_servings END_MEAL {if($2.calories > 18)
                                            printf ("Meal : too many calories\n");
                                            if($2.veg_fruit < 2){
                                            printf ("Meal : not enough veggies/fruit\n");
                                            $$.isVeggieFine = 1;
                                            }else{ $$.isVeggieFine = 0;}
                                            if($2.dessert > 1){
                                            printf ("Meal : too many desserts\n");
                                            $$.isDesertFine = 1;
                                            }else{ $$.isDesertFine = 0;}

                                            $$.calories = $2.calories;
                                            };

list_of_servings: list_of_servings ',' serving {$$.calories = $1.calories + $3.calories;
                                                $$.veg_fruit = $1.veg_fruit + $3.veg_fruit;
                                                $$.dessert = $1.dessert + $3.dessert;};

list_of_servings: serving {$$.calories = $1.calories;
                            $$.veg_fruit = $1.veg_fruit;
                            $$.dessert = $1.dessert;};

serving:  VEGETABLE {$$.calories = 1; $$.veg_fruit = 1;}
        | FRUIT {$$.calories = 2; $$.veg_fruit = 1;}
        | MEAT {$$.calories = 3;}
        | BREAD {$$.calories = 4;}
        | CAKE{$$.calories = 5; $$.dessert = 1;}
        | CHOCOLATE_ICE_CREAM{$$.calories = 6; $$.dessert = 1;}
        | VANILLA_ICE_CREAM {$$.calories = 7; $$.dessert = 1;}
        ;

%%

#include <stdio.h>
#include <stdlib.h>

main (int argc, char **argv)
{
  extern FILE *yyin;
  if (argc != 2) {
     fprintf (stderr, "Usage: %s <input-file-name>\n", argv[0]);
     return 1;
  }
  yyin = fopen (argv [1], "r");
  if (yyin == NULL) {
       fprintf (stderr, "failed to open %s\n", argv[1]);
       return 2;
  }

  yyparse ();

  fclose (yyin);
  return 0;
}

void yyerror (const char *s)
{
  extern int line;
  fprintf (stderr, "line %d: %s\n", line, s);
}

谢谢!

1 个答案:

答案 0 :(得分:2)

问题是您的野牛文件的第一个%code部分中的C语法错误:

struct diet

缺少分号,并且在最终传递给C编译器时会产生各种不可预测的编译错误。

但是,声明是不必要的,应该简单地删除。

您的flex文件也存在一些问题:

  1. 不要这样做:

    #define VEGETABLE 1
    #define FRUIT 2
    ...
    

    正确的令牌定义位于bison创建的头文件中,您已将其包含在内。您提供的值不正确,将导致解析失败。

  2. 不要这样做:

    extern void exit(int);
    

    exit在标准标题stdlib.h中声明;你应该包括那个头文件而不是猜测它的内容:

    #include <stdlib.h> 
    #include <string.h> 
    #include "meals.tab.h"
    

    请注意,在包含您自己的标题(例如由野牛生成的标题)之前包含系统标题是常规的。

  3. 最后,我强烈建议您删除自己尝试跟踪line中的行号,而只是让flex执行此操作:

    %option yylineno
    

    将导致flex插入有效代码以维护变量yylineno中的当前行号。此外,它将正确维护行号,因为它了解所有极端情况。 (除非您使用input()直接从yyin读取来回避弯曲处理。)