%header { #include "grammar.hpp" } %source { typedef std::vector> vars_t; typedef std::pair, vars_t> rhs_t; static inline void free_string(std::string *v) { delete v; } static inline void free_symbol(solar::symbol_t *v) { delete v; } static inline void free_rule(solar::rule_t *v) { delete v; } static inline void free_rhs(rhs_t *v) { delete v; } } %type SYMBOL {std::string *} str %destructor SYMBOL free_string %type SYMBOL_UC {std::string *} str %destructor SYMBOL_UC free_string %type BLOCK {std::string *} str %destructor BLOCK free_string %type SQBLOCK {std::string *} str %destructor SQBLOCK free_string %type STRING {std::string *} str %destructor STRING free_string %type CHAR {char} c %type rule {solar::rule_t *} %destructor rule free_rule %type rhs {rhs_t *} %destructor rhs free_rhs %type action {std::string *} %destructor action free_string %type symbol {solar::symbol_t *} %destructor symbol free_symbol %type term {solar::symbol_t *} %destructor term free_symbol %type varname {std::string *} %destructor varname free_string %extra_arg {__attribute__((unused)) solar::grammar_t *} grammar grammar |=; grammar |= grammar directive; directive |= "%type" SYMBOL(nonterm) BLOCK(type) { grammar->nonterm_types.insert(std::make_pair(*nonterm, *type)); } directive |= "%type" term(term) BLOCK(type) varname(name) { grammar->term_types.insert(std::make_pair(*term, std::make_pair(*type, *name))); } directive |= "%destructor" symbol(sym) varname(name) { grammar->destructors.insert(std::make_pair(*sym, *name)); } directive |= "%source" BLOCK(block) { grammar->source_block = *block; } directive |= "%header" BLOCK(block) { grammar->header_block = *block; } directive |= "%extra_arg" BLOCK(type) varname(name) { grammar->extra_args.push_back(std::make_pair(*type, *name)); } directive |= rule(rule) { if (grammar->rules.empty()) { solar::item_t init(""); init.get_rhs().push_back(solar::symbol_t::make_nonterm(rule->item.get_lhs().c_str())); grammar->rules.emplace_back(solar::rule_t {std::move(init), vars_t(), std::string()}); } grammar->rules.push_back(*rule); } rule |= SYMBOL(lhs) "|=" rhs(rhs) action(action) [new solar::rule_t {solar::item_t(*lhs, rhs->first), rhs->second, *action}] rhs |= [new rhs_t()] rhs |= rhs(=rhs) symbol(sym) { rhs->first.push_back(*sym); rhs->second.emplace_back(); return rhs; } rhs |= rhs(=rhs) symbol(sym) '(' varname(var) ')' { rhs->first.push_back(*sym); rhs->second.emplace_back(*var, true); return rhs; } rhs |= rhs(=rhs) symbol(sym) '(' '=' varname(var) ')' { rhs->first.push_back(*sym); rhs->second.emplace_back(*var, false); return rhs; } rhs |= rhs(=rhs) STRING(str) { for (char c : *str) { rhs->first.push_back(solar::symbol_t::make_char(c)); rhs->second.emplace_back(); } return rhs; } action |= ';' [new std::string] action |= BLOCK(=v) [v] action |= SQBLOCK(v) [new std::string("return " + *v + ";")] symbol |= SYMBOL(v) [new solar::symbol_t(solar::symbol_t::make_nonterm(*v))] symbol |= term(=v) [v] term |= SYMBOL_UC(v) [new solar::symbol_t(solar::symbol_t::make_term(*v))] term |= CHAR(v) [new solar::symbol_t(solar::symbol_t::make_char(v))] varname |= SYMBOL_UC(=v) [v] varname |= SYMBOL(=v) [v]