У меня есть это домашнее задание, где я должен преобразовать некоторые входные данные в определенные выходные данные. Проблема, с которой я сталкиваюсь, заключается в том, что я могу преобразовать только первую строку в нужный мне вывод, другие строки возвращают ошибку «синтаксическая ошибка».
Кроме того, если я изменяю порядок строк, строки не преобразуются, поэтому работает только одна конкретная строка.
Это мой входной файл:
Ввод.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
Может ли кто-нибудь указать мне в правильном направлении или сказать мне, что не так с моим кодом?
Спасибо, и если мое объяснение было недостаточно хорошим, я постараюсь объяснить его лучше!!
Извините за это, я переведу.... Я добавил ту строку, которую вы сказали, и я получил этот вывод: syntax error, unexpected $undefined, expecting $end
Вместо перевода VIRGULA в COMMA рассмотрите возможность использования ',', который не требует перевода и намного понятнее.
А как насчет файла flex? Удалить запись ЗАПЯТАЯ или оставить ее?





Есть по крайней мере две разные проблемы, которые вызывают эти симптомы.
Ваша грамматика верхнего уровня принимает не более одного animal:
inicio: /*vazio*/
| animal
Таким образом, вход, содержащий более одной строки, не будет разрешен. Вам нужен верхний уровень, который принимает любое количество animals. (Кстати, современные версии bison позволяют писать %empty в правой части пустой продукции вместо того, чтобы (неправильно) использовать комментарий.
Порядок правил вашего сканера означает, что большинство слов, которые вы хотите распознать как 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 добьюсь ли я этого?
2. Я понял свою ошибку, исправлю и выложу результаты... Спасибо за ответ!!
У меня это работает! Все благодаря вам!! Спасибо за ответ :)
Пожалуйста, добавьте
%define parse.error verboseв начало вашего файла bison, чтобы улучшить сообщения об ошибках, а затем опубликуйте расширенное сообщение об ошибке синтаксиса, которое вы получите с этой опцией. Также рассмотрите возможность перевода имен токенов и нетерминалов на английский язык, чтобы облегчить понимание кода.