Доброго времени суток, господа знатоки.
Подскажите, пожалуйста, что я делаю не так.
Черпаю информацию о Bison на сайте openNET. Нашёл информацию, что
для того что по умолчанию все нетерминалы имеют тип int, мне нужно сменить тип на string.
Пытался менять с помощью #define YYSTYPE std::string, но bison говорит всё равно что тип не определён.
Ещё bison говорит что не знает какой тип у ‘;’,‘{’ и т.д., но если им приписать тип с помощью %type ‘;’, то он не воспринимает описанные мной действия.
Я добился всякими обходными действиями что бы работало, но выводит не то что нужно.
В файле 2.txt лежит просто a = 2 , обычная переменная и int, а в консоль пишется два раза а.
Bison
%{
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void yyerror(char const* msg);
extern FILE *yyin;
extern int yylineno;
extern int ch;
int yylex();
std::string outCode;
%}
%union{
std::string* stringVal;
}
%expect 3
%verbose
%token <stringVal> LTOE GTOE TILDEEQUAL DEQUAL DSLASH DLESS DGREATER DPOINT TPOINT
%token <stringVal> NOT NIL FALSE TRUE RETURN
%token <stringVal> OR AND WHILE REPEAT UNTIL IF THEN ELSE ELSEIF
%token <stringVal> FOR IN FUNCTION LOCAL DO END GOTO BREAK DCOLON
%token <stringVal> NAME ESCAPE STRING CHARSTRING COMMENT LINECOMMENT
%token <stringVal> INT HEX FLOAT
%type <stringVal> number var '.' '[' ']'
%left OR
%left AND
%left '<' '>' LTOE GTOE TILDEEQUAL DEQUAL
%left '|'
%left '~'
%left '&'
%left DLESS DGREATER
%right DPOINT
%left '+' '-'
%left '*' '/' '%' DSLASH
%left '#' NOT
%left UNARY
%right '^'
%start chunk
%%
chunk: block
;
block: statREP
| statREP retstat
;
stat: ';'
| varlist '=' explist
| functioncall
| COMMENT
| LINECOMMENT
| label
| BREAK
| GOTO NAME
| DO block END
| WHILE exp DO block END
| REPEAT block UNTIL exp
| IF exp THEN block elseifREP END
| IF exp THEN block elseifREP ELSE block END
| FOR NAME '=' exp ',' exp DO block END
| FOR NAME '=' exp ',' exp ',' exp DO block END
| FOR namelist IN explist DO block END
| FUNCTION funcname funcbody
| LOCAL FUNCTION NAME funcbody
| LOCAL attnamelist
| LOCAL attnamelist '=' explist
;
statREP: /*empty*/
| statREP stat
;
elseifREP: /*empty*/
| elseifREP ELSEIF exp THEN block
;
attnamelist: NAME attrib attnamelistREP
;
attnamelistREP: /*empty*/
| attnamelistREP ',' NAME attrib
;
attrib: /*empty*/
| '<' NAME '>'
;
retstat: RETURN
| RETURN explist
| RETURN ';'
| RETURN explist ';'
;
label: DCOLON NAME DCOLON
;
funcname: NAME nameREP
| NAME nameREP ':' NAME
;
nameREP: /*empty*/
| nameREP '.' NAME
;
varlist: var
|varlist ',' var
;
namelist: NAME
| namelist ',' NAME
;
explist: exp
| explist ',' exp
;
exp: NIL | FALSE | TRUE
| number
| string
| TPOINT
| functiondef
| prefixexp
| tableconstructor
| exp '^' exp
| NOT exp
| '#' exp
| '-' exp %prec UNARY
| '~' exp %prec UNARY
| exp '*' exp
| exp '/' exp
| exp '%' exp
| exp DSLASH exp
| exp '+' exp
| exp '-' exp
| exp DPOINT exp
| exp '<' exp
| exp '>' exp
| exp LTOE exp
| exp GTOE exp
| exp TILDEEQUAL exp
| exp DEQUAL exp
| exp AND exp
| exp OR exp
| exp '&' exp
| exp '|' exp
| exp '~' exp
| exp DLESS exp
| exp DGREATER exp
;
prefixexp_nf: var
| '(' exp ')'
;
prefixexp: prefixexp_nf
| functioncall
;
functionargs: args
| ':' NAME args
;
functioncall: prefixexp_nf functionargs
| functioncall functionargs
;
var
: NAME { $<stringVal>$ = $1;std::cout << *($$) << std::endl;}
| prefixexp '[' exp ']' { $<stringVal>$ = $<stringVal>1;}
| prefixexp '.' NAME { $<stringVal>$ = $<stringVal>1;}
;
args: '('/*empty*/')'
| '(' explist ')'
| tableconstructor
| string
;
functiondef: FUNCTION funcbody
;
funcbody: '('/*empty*/')' block END
| '(' parlist ')' block END
;
parlist: namelist
| namelist ',' TPOINT
| namelist TPOINT
;
tableconstructor: '{' '}'
| '{' fieldlist '}'
;
fieldlist: field fieldlistREP
| field fieldlistREP fieldsep
;
fieldlistREP: /*empty*/
| fieldlistREP fieldsep field
;
field: '[' exp ']' '=' exp
| NAME '=' exp
| exp
;
fieldsep: ',' | ';'
;
number
: INT { std::cout << *($1) << std::endl;}
| HEX
| FLOAT
;
string: STRING | CHARSTRING
;
%%
void yyerror(char const* msg) {}
int main() {
yyin = fopen("2.txt", "r");
yylineno = 1;
ch = 1;
if (yyparse() == 0) {
cout << "Success" << endl;
} else {
cout << "Syntax error" << endl;
}
std::ofstream fout;
fout.open("output code.txt");
fout << outCode;
fout.close();
return 0;
}
Flex
%option noyywrap yylineno
%{
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "lua.tab.h"
using namespace std;
void showError();
int ch;
%}
%%
[ \t\r\n]+ { /* игнорируем пробелы, табы и переносы строк */ }
"(" {return 40;}
")" {return 41;}
"[" {return 91;}
"]" {return 93;}
"{" {return 123;}
"}" {return 125;}
"<" {return 60;}
">" {return 62;}
"," {return 44;}
"." {return 46;}
"+" {return 43;}
"-" {return 45;}
"*" {return 42;}
"/" {return 47;}
"=" {return 61;}
":" {return 58;}
";" {return 59;}
"%" {return 37;}
"&" {return 38;}
"|" {return 124;}
"~" {return 126;}
"#" {return 35;}
"^" {return 94;}
["] {return 34;}
"'" {return 39;}
"\\" {return 92;}
"<=" {yylval.stringVal = new std::string(yytext, yyleng); return (LTOE);}
">=" {yylval.stringVal = new std::string(yytext, yyleng); return (GTOE);}
"~=" {yylval.stringVal = new std::string(yytext, yyleng); return (TILDEEQUAL);}
"==" {yylval.stringVal = new std::string(yytext, yyleng); return (DEQUAL);}
"//" {yylval.stringVal = new std::string(yytext, yyleng); return (DSLASH);}
"<<" {yylval.stringVal = new std::string(yytext, yyleng); return (DLESS);}
">>" {yylval.stringVal = new std::string(yytext, yyleng); return (DGREATER);}
".." {yylval.stringVal = new std::string(yytext, yyleng); return (DPOINT);}
"..." {yylval.stringVal = new std::string(yytext, yyleng); return (TPOINT);}
"not" {yylval.stringVal = new std::string(yytext, yyleng); return (NOT);}
"nil" {yylval.stringVal = new std::string(yytext, yyleng); return (NIL);}
"false" {yylval.stringVal = new std::string(yytext, yyleng); return (FALSE);}
"true" {yylval.stringVal = new std::string(yytext, yyleng); return (TRUE);}
"return" {yylval.stringVal = new std::string(yytext, yyleng); return (RETURN);}
"or" {yylval.stringVal = new std::string(yytext, yyleng); return (OR);}
"and" {yylval.stringVal = new std::string(yytext, yyleng); return (AND);}
"while" {yylval.stringVal = new std::string(yytext, yyleng); return (WHILE);}
"repeat" {yylval.stringVal = new std::string(yytext, yyleng); return (REPEAT);}
"until" {yylval.stringVal = new std::string(yytext, yyleng); return (UNTIL);}
"if" {yylval.stringVal = new std::string(yytext, yyleng); return (IF);}
"then" {yylval.stringVal = new std::string(yytext, yyleng); return (THEN);}
"else" {yylval.stringVal = new std::string(yytext, yyleng); return (ELSE);}
"elseif" {yylval.stringVal = new std::string(yytext, yyleng); return (ELSEIF);}
"for" {yylval.stringVal = new std::string(yytext, yyleng); return (FOR);}
"in" {yylval.stringVal = new std::string(yytext, yyleng); return (IN);}
"function" {yylval.stringVal = new std::string(yytext, yyleng); return (FUNCTION);}
"local" {yylval.stringVal = new std::string(yytext, yyleng); return (LOCAL);}
"do" {yylval.stringVal = new std::string(yytext, yyleng); return (DO);}
"end" {yylval.stringVal = new std::string(yytext, yyleng); return (END);}
"goto" {yylval.stringVal = new std::string(yytext, yyleng); return (GOTO);}
"break" {yylval.stringVal = new std::string(yytext, yyleng); return (BREAK);}
"::" {yylval.stringVal = new std::string(yytext, yyleng); return (DCOLON);}
[a-zA-Z_][a-zA-Z_0-9]* {yylval.stringVal = new std::string(yytext, yyleng); return (NAME);}
\"[ -~]*\" {yylval.stringVal = new std::string(yytext, yyleng); return (STRING);}
[0-9]+ {return (INT);}
0[xX][0-9a-fA-F]+ {return (HEX);}
([0-9]*\.[0-9]+|[0-9]+\.) {return (FLOAT);}
. {showError(); return 0;}
%%
void showError(){
printf("Other input\n");
}