Я пытаюсь реализовать калькулятор гибкости / зубра, который может выполнять арифметические операции с плавающей запятой. Мой гибкий код выглядит так
%{
#include "calc.tab.h"
#include <stdlib.h>
void yyerror(char *s);
%}
digit [0-9]
integer {digit}+
real ({digit}+[.]{digit}*)|({digit}*[.]{digit}+)
exp ({integer}|{real})[eE]-?{integer}
%%
({integer}|{real}|{exp}) { yylval = atof(yytext); return NUMBER; }
[-+*/\n] { return *yytext; }
[ \t\v\f\r] { }
. { yyerror("Unknown Character"); }
%%
int yywrap(void)
{
return 1;
}
И мой код бизона выглядит так
%{
#include <stdio.h>
typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED
void yyerror(char *s);
extern char *yytext;
extern int yylineno;
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%%
program: program expr '\n' { printf("%g\n", $2); }
| program '\n'
|
;
expr: expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| NUMBER { $$ = $1; }
;
%%
void yyerror(char *s)
{
fprintf(stderr, "error: %s at %s, line %d\n", s, yytext, yylineno);
}
int main(int argc, char *argv[])
{
yyparse();
return 0;
}
Это не дает правильного результата. Хотя лексический анализатор интерпретирует строки как двойные и правильно сохраняет их в переменной yylval
, когда синтаксический анализатор складывает числа, он выдает только 0.0000
. Однако, если я объявляю yylval
как объединение с помощью директивы %union
, состоящей только из одной переменной double lf_val;
, и сохраняю вывод atof
в этом поле yylval
в лексере, а также объявить %token <lf_val> NUMBER
и %type <lf_val> expr
в синтаксическом анализаторе, все вроде работает.
Но почему не работает простой метод typedef
ing YYSTYPE
? Я также пробовал #define YYSTYPE double
. Это тоже не сработало.
1 ответ
Что касается %code
, в документации Bison говорится:
%code requires [...] is the best place to override Bison's default YYSTYPE
and YYLTYPE definitions.
Так что просто добавьте в верхнюю часть файла bison следующее:
%code requires
{
#define YYSTYPE double
}
Вы также захотите удалить эти две строки:
typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED
Обратите внимание, что YYSTYPE_IS_DECLARED, насколько мне известно, нигде не задокументирован и, таким образом, предназначен только для внутреннего использования Bison.
Если вы не знакомы с использованием директив Bison %code
по сравнению с простыми прологами %{
, вы можете найти этот раздел документации интересно прочитать.
Похожие вопросы
Новые вопросы
bison
Бизон - это генератор парсера GNU. Он генерирует парсеры LALR, но также может генерировать парсеры GLR для грамматик, которые не являются LALR. Он имеет режим совместимости со своим старым предшественником Yacc (еще один компилятор компилятора).
#define
внутри директивы%code requires { }
генерирует определение YYSTYPE в файле.h
, который был включен лексером. Таким образом, лексический анализатор выполнял запись в целочисленную переменную, а синтаксический анализатор читал из двойной!