|
- //
- // Lol Engine - Sandbox program
- //
- // Copyright © 2005-2015 Sam Hocevar <sam@hocevar.net>
- //
- // 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 <lol/engine.h>
-
- #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<double> 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<name> { \
- 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 <- <digit> +
- struct number : ifapply<plus<digit>, do_number> {};
-
- // term <- number | "(" expr ")"
- struct term : sor<number,
- seq<one<'('>, struct expr, one<')'>>> {};
-
- // factor <- term ( "*" term | "/" term ) *
- struct factor : seq<term,
- star<ifapply<sor<seq<one<'*'>, term>,
- seq<one<'/'>, term>>, do_op>>> {};
-
- // expr <- factor ( "+" factor | "-" factor ) *
- struct expr : seq<factor,
- star<ifapply<sor<seq<one<'+'>, factor>,
- seq<one<'-'>, factor>>, do_op>>> {};
-
- // stmt <- expr <end>
- struct stmt : ifapply<seq<expr, eof>, do_success> {};
- };
-
- static void parse_pegtl(std::string const & str)
- {
- calculator c;
- pegtl::basic_parse_string<pegtl_parser::stmt>(str, c);
- }
-
- //
- // AXE -- a recursive descent parser (needs right-recursion)
- //
-
- template<typename IT>
- static void parse_axe_helper(IT i1, IT i2)
- {
- calculator c;
- double d;
-
- #define ACTION(code) e_ref([&](...) { code })
-
- r_rule<IT> number, term, factor, factor_tail, expr, expr_tail, stmt;
-
- // number ::= <double>
- 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 <end>
- // | <fail>
- 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());
- }
|