// // Lol Engine - Sandbox program // // Copyright © 2005-2015 Sam Hocevar // // This program is free software. It comes without any warranty, to // the extent permitted by applicable law. You can redistribute it // and/or modify it under the terms of the Do What the Fuck You Want // to Public License, Version 2, as published by the WTFPL Task Force. // See http://www.wtfpl.net/ for more details. // #if HAVE_CONFIG_H # include "config.h" #endif #include #include "pegtl.hh" namespace lol { namespace parser = pegtl; } #include "axe.h" namespace lol { using namespace axe; } using namespace lol; // // Parser tools for a simple calculator grammar with + - * / // struct calculator { void push(double d) { stack.Push(d); } void pop() { printf("%f\n", stack.Pop()); } void mul() { auto x = stack.Pop(); stack.Push(stack.Pop() * x); } void div() { auto x = stack.Pop(); stack.Push(stack.Pop() / x); } void add() { auto x = stack.Pop(); stack.Push(stack.Pop() + x); } void sub() { auto x = stack.Pop(); stack.Push(stack.Pop() - x); } array stack; }; static void parse_pegtl(std::string const &str); static void parse_axe(std::string const &str); int main() { std::string const str("42+2*(1-1+2+3-4*5)"); parse_axe(str); parse_pegtl(str); return EXIT_SUCCESS; } // // PegTL -- a PEG parser // namespace pegtl_parser { using namespace lol::parser; #define ACTION(name, code) \ struct name : action_base { \ static void apply(std::string const &ctx, calculator &c) { \ code \ } \ }; ACTION( do_number, c.push(atof(ctx.c_str())); ) ACTION( do_op, switch (ctx[0]) { case '*': c.mul(); break; case '/': c.div(); break; case '+': c.add(); break; case '-': c.sub(); break; } ) ACTION( do_success, c.pop(); ) #undef ACTION // number <- + struct number : ifapply, do_number> {}; // term <- number | "(" expr ")" struct term : sor, struct expr, one<')'>>> {}; // factor <- term ( "*" term | "/" term ) * struct factor : seq, term>, seq, term>>, do_op>>> {}; // expr <- factor ( "+" factor | "-" factor ) * struct expr : seq, factor>, seq, factor>>, do_op>>> {}; // stmt <- expr struct stmt : ifapply, do_success> {}; }; static void parse_pegtl(std::string const & str) { calculator c; pegtl::basic_parse_string(str, c); } // // AXE -- a recursive descent parser (needs right-recursion) // template static void parse_axe_helper(IT i1, IT i2) { calculator c; double d; #define ACTION(code) e_ref([&](...) { code }) r_rule number, term, factor, factor_tail, expr, expr_tail, stmt; // number ::= number = r_double(d) >> ACTION( c.push(d); ); // term ::= number | ( expr ) term = number | '(' & expr & ')'; // factor ::= term factor_tail // factor_tail ::= * term factor_tail // | / term factor_tail // | ɛ factor_tail = '*' & term >> ACTION( c.mul(); ) & factor_tail | '/' & term >> ACTION( c.div(); ) & factor_tail | r_empty(); factor = term & factor_tail; // expr ::= factor expr_tail // expr_tail ::= + factor expr_tail // | - factor expr_tail // | ɛ expr_tail = '+' & factor >> ACTION( c.add(); ) & expr_tail | '-' & factor >> ACTION( c.sub(); ) & expr_tail | r_empty(); expr = factor & expr_tail; // stmt ::= expr // | stmt = expr & r_end() >> ACTION( c.pop(); ) | r_fail([](...) { printf("malformed expression\n"); }); #undef ACTION // Evaluate expression stmt(i1, i2); } static void parse_axe(std::string const &str) { return parse_axe_helper(str.begin(), str.end()); }