Стог зубров
Это лексический анализатор, использующий Flex.
#include <iostream>
#include <cstdio>
#define YY_DECL extern "C" int yylex()
#include "conv.tab.h"
using namespace std;
%}
eq [ \t]*=
%%
[ \t] ;
(?:POINT|LINE) { yylval.ename = strdup(yytext); return ENAME; }
x{eq} { yylval.xval = atof(yytext);
return XVAL; }
y{eq} { yylval.yval = atof(yytext);
return YVAL; }
. ;
%%
И другой файл - файл грамматики зубров
%{
#include <iostream>
#include <cstdio>
#include <stdio.h>
using namespace std;
extern "C" int yylex ();
extern "C" int yyparse (void);
extern "C" FILE *yyin;
extern int line_no;
void yyerror(const char *s);
%}
%union{
float xval;
float yval;
char *ename;
}
%token <ename> ENAME
%token XVAL
%token YVAL
%%
converter:
converter ENAME { cout << "entity = " << $2 << endl; }
| converter XVAL {// x -> xval = $2;
cout << "x value = " << endl; }
| converter YVAL {// y -> yval = $2;
cout << "y value = " << endl; }
| ENAME { cout << "entity = " << $1 << endl; }
| XVAL { cout << "xvalue " << endl; }
| YVAL { cout << "yvalue " << endl; }
%%
main() {
FILE *myfile = fopen("conv.aj", "r");
if (!myfile) {
cout << "I can't open file" << endl;
return -1;
}
yyin = myfile;
do{
yydebug = 1;
yyparse();
} while (!feof(yyin));
yydebug = 2;
}
void yyerror(const char *s) {
cout << "Parser error! Message: " << s << endl;
exit(-1);
}
На самом деле, я хочу получить значения из файла. Я использовал Bison Debugger и узнал, что эти значения не могут быть добавлены в Bison Stack. Поэтому я хочу поместить эти значения в стек. Мой файл выглядит так: POINT x=38 y=47
1 ответ
Ничто в вашем лексическом анализаторе не соответствует числу, поэтому 38
а также 47
из входных данных оба будут обработаны вашим правилом по умолчанию (. ;
) что приведет к их игнорированию. В ваших правилах для XVAL
а также YVAL
, ты звонишь atoi
на yytext
, которые будут x=
(или же y=
); это явно не число и atoi
вероятно вернется 0
,
Мне непонятно, что вы подразумеваете под "этими значениями не в состоянии протолкнуть стек Bison", но я думаю, что эта проблема не имеет ничего общего с зубром или его стеком.
Кстати:
Нет необходимости иметь два разных члена в вашем семантическом типе для
xval
а такжеyval
, Тип являетсяunion
неstruct
таким образом, имея два члена одного типа (float
) является излишним.flex
не делает регулярные выражения. Так что нет смысла избегать захвата с(?:...)
; это просто затемняет вашу грамматику. Вы также можете использовать:POINT | LINE: {yylval.ename = strdup (yytext); возврат ENAME; }
С другой стороны, вам лучше определить два разных типа токенов, что позволит избежать необходимости
strdup
, (Вы, кажется, неfree
дублирующую строку, поэтомуstrdup
это также утечка памяти.) В качестве альтернативы, вы можете использовать перечисляемое значение в вашем семантическом типе:POINT { yylval.ename_enum=POINT; return ENAME; } LINE { yylval.ename_enum=LINE; return ENAME; }
. ;
это не очень хорошая идея, особенно во время разработки, потому что она скрывает ошибки (например, ту, которая у вас есть). Ты можешь использовать%option nodefault
избежатьflex
правило по умолчанию, а затем flex представит ошибку при обнаружении недопустимого символа.Если вы не используете действительно старые версии
bison
а такжеflex
, вы можете просто скомпилировать сгенерированный код какc++
, Там не должно быть необходимости использоватьextern "C"