expr.y (bison):
Код: Выделить всё
%{
#include <iostream>
#include <stdlib.h>
#include <string>
using std::string;
using std::cout;
//int yylex(){return getc(stdin);}
extern int yylex();
extern int yylineno;
void yyerror(char *s)
{
std::cerr << s << ", line " << yylineno << std::endl;
exit(1);
}
class tree_node //abstract
{
public:
virtual int eval()=0;
};
class value: public tree_node
{
int num;
public:
value(int n){num=n;}
value(string s)
{
const char* c=s.c_str();
num=atoi(c);
}
int eval(){return num;}
};
typedef int (*bin_func) (int, int);
class binary: public tree_node
{
tree_node* left,*right;
bin_func func;
public:
binary(tree_node* l,tree_node* r,bin_func f){left=l;right=r;func=f;}
int eval()
{
return func(left->eval(),right->eval());
}
};
int _add(int a,int b){return a+b;}
int _sub(int a,int b){return a-b;}
int _mul(int a,int b){return a*b;}
int _div(int a,int b){return a/b;}
bin_func get_f(char c){return c=='+'?_add:c=='-'?_sub:c=='*'?_mul:_div;}
typedef struct {
string str;
tree_node* node;
} YYSTYPE;
#define YYSTYPE YYSTYPE
%}
%token NUM
%type<str> NUM;
%type<node> EXPR TERM VAL;
%%
EVALUATE: EXPR '\n' {cout<<$1->eval()<<'\n';}
;
EXPR: TERM
| TERM '+' EXPR {$$=new binary($1,$3,get_f('+'));}
| TERM '-' EXPR {$$=new binary($1,$3,get_f('-'));}
;
TERM: VAL
| TERM '*' VAL {$$=new binary($1,$3,get_f('*'));}
| TERM '/' VAL {$$=new binary($1,$3,get_f('/'));}
;
VAL: NUM {$$=new value($1);}
;
%%
int main(){return yyparse();}(извиняюсь за деревья разбора, функции _add, _sub, _mul, _div - я в курсе что можно считать прямо во время разбора - у данного поделия в будущем появятся возможности, для которых дерево необходимо).
expr.lex (flex):
Код: Выделить всё
%{
#include <stdio.h>
#include <string>
#define YYSTYPE std::string
#include "expr.tab.h"
void yyerror(char* s);
%}
%option yylineno
%option noyywrap
%%
[0-9]+ {yylval=yytext;return NUM;}
[\+\-\*\/\n] return *yytext;
%%Инструкция как собрать:
bison -d expr.y
flex expr.lex
g++ lex.yy.c expr.tab.c
Что должно получится:
Программа читает выражения и вычисляет их по очереди. Выражения разделяются переводами строк.
Что получилось:
Программа успешно обрабатывает первое выражение, но на второе обязательно выдает ошибку. В чем причина?
PS. Еще раз извиняюсь за толстый код.
PPS. С bison и flex работаю впервые.