Почему мой bison/flex не работает должным образом?

У меня есть это домашнее задание, где я должен преобразовать некоторые входные данные в определенные выходные данные. Проблема, с которой я сталкиваюсь, заключается в том, что я могу преобразовать только первую строку в нужный мне вывод, другие строки возвращают ошибку «синтаксическая ошибка».

Кроме того, если я изменяю порядок строк, строки не преобразуются, поэтому работает только одна конкретная строка.

Это мой входной файл:

Ввод.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

Это мой код:

файл.у

%{
    #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);
}

файл.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, чтобы улучшить сообщения об ошибках, а затем опубликуйте расширенное сообщение об ошибке синтаксиса, которое вы получите с этой опцией. Также рассмотрите возможность перевода имен токенов и нетерминалов на английский язык, чтобы облегчить понимание кода.

sepp2k 07.04.2019 18:59

Извините за это, я переведу.... Я добавил ту строку, которую вы сказали, и я получил этот вывод: syntax error, unexpected $undefined, expecting $end

H. Soares 07.04.2019 19:30

Вместо перевода VIRGULA в COMMA рассмотрите возможность использования ',', который не требует перевода и намного понятнее.

rici 07.04.2019 19:50

А как насчет файла flex? Удалить запись ЗАПЯТАЯ или оставить ее?

H. Soares 07.04.2019 20:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
240
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть по крайней мере две разные проблемы, которые вызывают эти симптомы.

  1. Ваша грамматика верхнего уровня принимает не более одного animal:

    inicio: /*vazio*/
        | animal
    

    Таким образом, вход, содержащий более одной строки, не будет разрешен. Вам нужен верхний уровень, который принимает любое количество animals. (Кстати, современные версии bison позволяют писать %empty в правой части пустой продукции вместо того, чтобы (неправильно) использовать комментарий.

  2. Порядок правил вашего сканера означает, что большинство слов, которые вы хотите распознать как VACINA, вместо этого будут распознаны как NOME. Напомним, что когда два шаблона соответствуют одному и тому же токену, первый в файле выиграет. Итак, с этими правилами:

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

    Токены вроде Tosse, которые могут соответствовать любому правилу, будут считаться соответствующими первому правилу. Только V8 и Anti-Rabatical, которые не соответствуют [A-Z][a-z]*, подпадают под второе правило. Таким образом, ваша первая строка ввода не вызывает эту проблему, но все остальные.

Вам, вероятно, следует обрабатывать символы новой строки синтаксически, если только вы не разрешаете разбивать записи о лечении на несколько строк. И имейте в виду, что многие версии (f)lex не допускают пустых действий, как в ваших последних двух правилах flex. Это может привести к лексическим ошибкам.

И наконец

<<EOF>> return 0;

не нужно. Вот как сканер обрабатывает конец файла по умолчанию. <<EOF>> правила часто выкручиваются или повторяются, и их следует использовать только в случае крайней необходимости (и с большой осторожностью).

1. Если я это сделаю begining: | begining '\n' animal добьюсь ли я этого?

H. Soares 07.04.2019 20:23

2. Я понял свою ошибку, исправлю и выложу результаты... Спасибо за ответ!!

H. Soares 07.04.2019 20:24

У меня это работает! Все благодаря вам!! Спасибо за ответ :)

H. Soares 07.04.2019 20:48

Другие вопросы по теме