Сделайте простой калькулятор, используя flex и bison - PullRequest
2 голосов
/ 10 января 2020

Я пытаюсь сделать очень простой калькулятор с генераторами flex и bison. Это просто работает на целых числах. Я правильно скомпилировал файл lexer без ошибок; но когда я компилирую файл парсера, он показывает мне несколько предупреждений:

  • предупреждение: 1 нетерминал бесполезен в грамматике
  • предупреждение: 2 правила бесполезны в грамматике
  • 21.1-4: предупреждение: нетерминал, бесполезен в грамматике: строка
  • 21.9-1: предупреждение: правило бесполезно в грамматике: строка: NWL
  • 22.9-55: предупреждение: 1 нетерминал бесполезен в грамматика: Exp NWL

Создает выходной файл после отображения этих предупреждений.
Я скомпилировал выходные файлы с помощью gcc; он сделал файл .exe .
Когда я запускаю файл .exe и пытаюсь вычислить, он показывает мне эту ошибку:

  • синтаксическая ошибка

Пожалуйста, помогите мне.

Мои коды:
файл лексера

%option noyywrap
%{
#define YYSTYPE double
#include <stdio.h>
#include "x.tab.h"
%}
DIG         [0-9]
%%
{DIG}+      { yylval = atoi(yytext); return NUM; }
"+"                             { return PLS; }
"-"                             { return MNS; }
"*"                             { return MUL; }
"/"                             { return DIV; }
"\n"                                { return NWL; }
"("                             { return LFT; }
")"                             { return RIT; }
%%

файл парсера

%{
#include <stdio.h>
#define YYSTYPE double
int yyerror (char const *s);
extern int yylex (void);
%}
%token  PLS MNS
%token  MUL DIV
%token  NWL
%token  NUM
%token  LFT RIT
%left   PLS MNS
%left   MUL DIV
%%
Exp:    NUM             { $$ = $1; };
Exp:    Exp PLS Exp     { $$ = $1 + $3; };
Exp:    Exp MNS Exp     { $$ = $1 - $3; };
Exp:    Exp MUL Exp     { $$ = $1 * $3; };
Exp:    Exp DIV Exp     { $$ = $1 / $3; };
Exp:    LFT Exp RIT     { $$ = $2; };
Line:   NWL;
Line:   Exp NWL         { printf("%f\n", $1); };
;
%%
int yyerror(char const *s) {
  printf("%s\n", s);
}
int main(){
    int ret = yyparse();
    if (ret){
    fprintf(stderr, "%d error found.\n",ret);
    }
    return 0;
}

1 Ответ

3 голосов
/ 10 января 2020

Начальным символом вашей грамматики является Exp, а не Line. Либо сначала поместите правило Line, либо используйте объявление %start Line. Объявление %start должно go перед %%, в том же разделе, что и объявления %token.

Это должно привести вас к тому, что ваша программа сможет обработать первую строку, такую ​​как 3 + 4; -)

Если вы хотите, чтобы он обрабатывал несколько строк, вы должны добавить еще одно правило - пример фиксированного раздела грамматики вашего *.y файла, где Seq (последовательность строк) является начальный символ:

Seq:    /* empty */
|       Seq Line
Exp:    NUM             { $$ = $1; };
Exp:    Exp PLS Exp     { $$ = $1 + $3; };
Exp:    Exp MNS Exp     { $$ = $1 - $3; };
Exp:    Exp MUL Exp     { $$ = $1 * $3; };
Exp:    Exp DIV Exp     { $$ = $1 / $3; };
Exp:    LFT Exp RIT     { $$ = $2; };
Line:   NWL
Line:   Exp NWL         { printf("%f\n", $1); };
...