Калькулятор в lex и yacc - PullRequest
       43

Калькулятор в lex и yacc

0 голосов
/ 12 апреля 2020

Я пытаюсь создать калькулятор, используя lex и ya cc. Однако я не могу понять, как я могу дать приоритет оператора этой программе? Я не мог найти информацию об этом. Какой код мне нужно добавить в мой проект для правильного расчета?

Ya cc Файл:

%{
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int yylex();
void yyerror(const char *s);
%}
%token INTEGER

%left  '*'  '/'
%left  '+'  '-'

%%
program:
       program line | line

line:
    expr ';' { printf("%d\n",$1); } ; | '\n'

expr:
    expr '+' term { $$ = $1 + $3; } 
    | expr '-' term { $$ = $1 - $3; }
    | expr '*' term { $$ = $1 * $3; } 
    | expr '/' term { $$ = $1 / $3; } 
    | expr '%' term { $$ = $1 % $3; }
    | expr '^' term { $$ = $1 ; }
    | term { $$ = $1; }

term:
    INTEGER { $$ = $1; }
%%
void yyerror(const char *s) { fprintf(stderr,"%s\n",s); return ; }
int main(void) { /*yydebug=1;*/ yyparse(); return 0; }

Файл Lex:

%{
#include <stdlib.h>
#include <stdio.h>
void yyerror(char*);
extern int yylval;
#include "calc.tab.h" 
#include<time.h>
%}

%%

[ \t]+ ; //skip whitespace
[0-9]+ {yylval = atoi(yytext); return INTEGER;}

[-+*/%^] {return *yytext;}
\n {return *yytext;}
; {return *yytext;}
. {char msg[25]; sprintf(msg,"%s <%s>","invalid character",yytext); yyerror(msg);}

1 Ответ

1 голос
/ 12 апреля 2020
%left  '*'  '/'
%left  '+'  '-'

Объявления приоритетов указываются в порядке от самого низкого приоритета до самого высокого. Таким образом, в приведенном выше коде вы задаете * и / самый низкий уровень приоритета, а + и - - самый высокий. Это противоположный порядок того, что вы хотите, так что вам нужно изменить порядок этих двух строк. Вы также захотите добавить операторы % и ^, которые в настоящее время являются частью вашей грамматики, но не являются вашими аннотациями предшествования.

С этими изменениями вы теперь указали приоритет, который вы хочу, но пока не вступит в силу. Почему бы нет? Потому что аннотации предшествования используются для разрешения неоднозначностей, но ваша грамматика на самом деле не является двусмысленной.

То, как вы написали грамматику, только левый операнд всех операторов равен expr, а правый операнд - term, есть только один способ получить выражение, подобное 2+4*2, а именно: 2+4 из expr и 2 из термина (поскольку получение 4*2 из term было бы невозможно, поскольку term может соответствовать только один номер). Таким образом, ваша грамматика рассматривает все операторы как левоассоциативные и имеющие одинаковый приоритет, и ваши аннотации предшествования вообще не рассматриваются.

Для того, чтобы аннотации предшествования были рассмотрены, вам придется изменить свою грамматику , так что оба операнда операторов равны expr (например, expr '+' expr вместо expr '+' term). Таким образом, такое выражение, как 2+4*2, может быть получено путем получения 2+4 из expr в качестве левого операнда и 2 из expr в качестве правого операнда или 2 в качестве левого и 4*2 как право, и эта неоднозначность будет решена с использованием ваших предыдущих аннотаций.

...