この文法を使用して、式を作成できます。
exp:
/* empty */
| non_empty_exp { print_exp(); }
;
non_empty_exp:
mult_div_exp
| add_sub_exp
;
mult_div_exp:
primary_exp
| mult_div_exp '*' primary_exp { push_node('*'); }
| mult_div_exp '/' primary_exp { push_node('/'); }
;
add_sub_exp:
non_empty_exp '+' mult_div_exp { push_node('+'); }
| non_empty_exp '-' mult_div_exp { push_node('-'); }
;
primary_exp:
| '(' non_empty_exp ')'
| NUMBER { push_term($1); }
;
そして、あなたのレクサーのために以下。
[ \t]+ {}
[0-9]+ { yylval.number = atoi(yytext); return NUMBER; }
[()] { return *yytext; }
[*/+-] { return *yytext; }
式は、次のルーチンを使用して、進行中に作成されます。
std::list<Exp *> exps;
/* push a term onto expression stack */
void push_term (int n) {
Term *t = new Term;
t->n_ = n;
exps.push_front(t);
}
/* push a node onto expression stack, top two in stack are its children */
void push_node (char op) {
Node *n = new Node;
n->operation_ = op;
n->roperator_ = exps.front();
exps.pop_front();
n->loperator_ = exps.front();
exps.pop_front();
exps.push_front(n);
}
/*
* there is only one expression left on the stack, the one that was parsed
*/
void print_exp () {
Exp *e = exps.front();
exps.pop_front();
print_exp(e);
delete e;
}
次のルーチンは、式ツリーをきれいに出力できます。
static void
print_exp (Exp *e, std::string ws = "", std::string prefix = "") {
Term *t = dynamic_cast<Term *>(e);
if (t) { std::cout << ws << prefix << t->n_ << std::endl; }
else {
Node *n = dynamic_cast<Node *>(e);
std::cout << ws << prefix << "'" << n->operation_ << "'" << std::endl;
if (prefix.size()) {
ws += (prefix[1] == '|' ? " |" : " ");
ws += " ";
}
print_exp(n->loperator_, ws, " |- ");
print_exp(n->roperator_, ws, " `- ");
}
}