diff --git a/build/msbuild/lol.vars.props b/build/msbuild/lol.vars.props index d47c4ee3..e5e376de 100644 --- a/build/msbuild/lol.vars.props +++ b/build/msbuild/lol.vars.props @@ -5,7 +5,7 @@ $(SolutionDir)\..\external - $(ExternalDir)\pegtl-0.32 + $(ExternalDir)\pegtl-1.3.1 $(PegtlDir)\include diff --git a/configure.ac b/configure.ac index b486ab08..76b35f3f 100644 --- a/configure.ac +++ b/configure.ac @@ -296,7 +296,7 @@ fi dnl Use pegtl? Yes, always if true; then - LOL_CFLAGS="$LOL_CFLAGS -I\$(top_srcdir)/external/pegtl-0.32/include" + LOL_CFLAGS="$LOL_CFLAGS -I\$(top_srcdir)/external/pegtl-1.3.1/include" fi diff --git a/src/gpu/shader.cpp b/src/gpu/shader.cpp index 8b01d330..cc7144f5 100644 --- a/src/gpu/shader.cpp +++ b/src/gpu/shader.cpp @@ -117,42 +117,22 @@ using namespace pegtl; struct lolfx_parser { -public: - lolfx_parser(String const &code) - : m_section("header") - { - basic_parse_string(std::string(code.C()), this); - } - public: String m_section; map m_programs; private: - struct do_title : action_base - { - static void apply(std::string const &ctx, lolfx_parser *that) - { - that->m_section = ctx.c_str(); - } - }; - - struct do_code : action_base - { - static void apply(std::string const &ctx, lolfx_parser *that) - { - that->m_programs[that->m_section] = ctx.c_str(); - } - }; - // title <- '[' (!']')+ ']' .{eol} + struct do_title + : plus> {}; + struct title : seq, - ifapply>, do_title>, + do_title, one<']'>, until> {}; - // FIXME: I’m using this rule because the ifapply<> above also + // FIXME: I’m using this rule because the do_title above also // gets triggered when using at<> which is non-consuming. struct title_ignore : seq, @@ -166,7 +146,7 @@ private: // code_section < code_line{&(title / eof)} struct code_section - : ifapply>, code_line>, do_code> {}; + : until>, code_line> {}; // shader < title code_section struct shader @@ -179,6 +159,35 @@ private: // lolfx < header code_section* struct lolfx : seq> {}; + + // default action: nothing + template + struct action : nothing {}; + +public: + lolfx_parser(String const &code) + : m_section("header") + { + pegtl::parse(code.C(), "shader", this); + } +}; + +template<> +struct lolfx_parser::action +{ + static void apply(input const &in, lolfx_parser *that) + { + that->m_section = in.string().c_str(); + } +}; + +template<> +struct lolfx_parser::action +{ + static void apply(input const &in, lolfx_parser *that) + { + that->m_programs[that->m_section] = in.string().c_str(); + } }; /* diff --git a/tools/lolremez/expression.h b/tools/lolremez/expression.h index 5198880a..fac9782d 100644 --- a/tools/lolremez/expression.h +++ b/tools/lolremez/expression.h @@ -28,7 +28,7 @@ namespace grammar using namespace pegtl; -enum class op : uint8_t +enum class id : uint8_t { /* Variables and constants */ x, @@ -46,45 +46,8 @@ enum class op : uint8_t min, max, }; -// Map operation enums to pegl::string<> rules -template struct r_call_string {}; - -template<> struct r_call_string : string<'a','b','s'> {}; -template<> struct r_call_string : string<'s','q','r','t'> {}; -template<> struct r_call_string : string<'c','b','r','t'> {}; -template<> struct r_call_string : string<'e','x','p'> {}; -template<> struct r_call_string : string<'e','x','p','2'> {}; -template<> struct r_call_string : string<'l','o','g'> {}; -template<> struct r_call_string : string<'l','o','g','2'> {}; -template<> struct r_call_string : string<'l','o','g','1','0'> {}; -template<> struct r_call_string : string<'s','i','n'> {}; -template<> struct r_call_string : string<'c','o','s'> {}; -template<> struct r_call_string : string<'t','a','n'> {}; -template<> struct r_call_string : string<'a','s','i','n'> {}; -template<> struct r_call_string : string<'a','c','o','s'> {}; -template<> struct r_call_string : string<'a','t','a','n'> {}; -template<> struct r_call_string : string<'s','i','n','h'> {}; -template<> struct r_call_string : string<'c','o','s','h'> {}; -template<> struct r_call_string : string<'t','a','n','h'> {}; - -template<> struct r_call_string : string<'a','t','a','n','2'> {}; -template<> struct r_call_string : string<'p','o','w'> {}; -template<> struct r_call_string : string<'m','i','n'> {}; -template<> struct r_call_string : string<'m','a','x'> {}; - struct expression { - /* - * Parse arithmetic expression in x, e.g. 2*x+3 - */ - void parse(std::string const &str) - { - m_ops.empty(); - m_constants.empty(); - - basic_parse_string(str, this); - } - /* * Evaluate expression at x */ @@ -96,12 +59,12 @@ struct expression for (int i = 0; i < m_ops.count(); ++i) { /* Rules that do not consume stack elements */ - if (m_ops[i].m1 == op::x) + if (m_ops[i].m1 == id::x) { stack.push(x); continue; } - else if (m_ops[i].m1 == op::constant) + else if (m_ops[i].m1 == id::constant) { stack.push(m_constants[m_ops[i].m2]); continue; @@ -112,39 +75,39 @@ struct expression switch (m_ops[i].m1) { - case op::plus: stack.push(head); break; - case op::minus: stack.push(-head); break; - - case op::abs: stack.push(fabs(head)); break; - case op::sqrt: stack.push(sqrt(head)); break; - case op::cbrt: stack.push(cbrt(head)); break; - case op::exp: stack.push(exp(head)); break; - case op::exp2: stack.push(exp2(head)); break; - case op::log: stack.push(log(head)); break; - case op::log2: stack.push(log2(head)); break; - case op::log10: stack.push(log10(head)); break; - case op::sin: stack.push(sin(head)); break; - case op::cos: stack.push(cos(head)); break; - case op::tan: stack.push(tan(head)); break; - case op::asin: stack.push(asin(head)); break; - case op::acos: stack.push(acos(head)); break; - case op::atan: stack.push(atan(head)); break; - case op::sinh: stack.push(sinh(head)); break; - case op::cosh: stack.push(cosh(head)); break; - case op::tanh: stack.push(tanh(head)); break; - - case op::add: stack.push(stack.pop() + head); break; - case op::sub: stack.push(stack.pop() - head); break; - case op::mul: stack.push(stack.pop() * head); break; - case op::div: stack.push(stack.pop() / head); break; - - case op::atan2: stack.push(atan2(stack.pop(), head)); break; - case op::pow: stack.push(pow(stack.pop(), head)); break; - case op::min: stack.push(min(stack.pop(), head)); break; - case op::max: stack.push(max(stack.pop(), head)); break; - - case op::x: - case op::constant: + case id::plus: stack.push(head); break; + case id::minus: stack.push(-head); break; + + case id::abs: stack.push(fabs(head)); break; + case id::sqrt: stack.push(sqrt(head)); break; + case id::cbrt: stack.push(cbrt(head)); break; + case id::exp: stack.push(exp(head)); break; + case id::exp2: stack.push(exp2(head)); break; + case id::log: stack.push(log(head)); break; + case id::log2: stack.push(log2(head)); break; + case id::log10: stack.push(log10(head)); break; + case id::sin: stack.push(sin(head)); break; + case id::cos: stack.push(cos(head)); break; + case id::tan: stack.push(tan(head)); break; + case id::asin: stack.push(asin(head)); break; + case id::acos: stack.push(acos(head)); break; + case id::atan: stack.push(atan(head)); break; + case id::sinh: stack.push(sinh(head)); break; + case id::cosh: stack.push(cosh(head)); break; + case id::tanh: stack.push(tanh(head)); break; + + case id::add: stack.push(stack.pop() + head); break; + case id::sub: stack.push(stack.pop() - head); break; + case id::mul: stack.push(stack.pop() * head); break; + case id::div: stack.push(stack.pop() / head); break; + + case id::atan2: stack.push(atan2(stack.pop(), head)); break; + case id::pow: stack.push(pow(stack.pop(), head)); break; + case id::min: stack.push(min(stack.pop(), head)); break; + case id::max: stack.push(max(stack.pop(), head)); break; + + case id::x: + case id::constant: /* Already handled above */ break; } @@ -155,101 +118,70 @@ struct expression } private: - lol::array m_ops; + lol::array m_ops; lol::array m_constants; private: - struct do_constant : action_base - { - static void apply(std::string const &ctx, expression *that) - { - /* FIXME: check if the constant is already in the list */ - that->m_ops.push(op::constant, that->m_constants.count()); - that->m_constants.push(lol::real(ctx.c_str())); - } - }; - - template - struct do_op : action_base> - { - static void apply(std::string const &ctx, expression *that) - { - UNUSED(ctx); - that->m_ops.push(OP, -1); - } - }; - struct r_expr; // r_ <- * struct _ : star {}; - // r_call_unary <- "(" r_expr ")" - template - struct r_call_unary : ifapply, - _, - one<'('>, - _, - r_expr, - _, - one<')'>>, - do_op> {}; - - // r_call_binary <- "(" r_expr "," r_expr ")" - template - struct r_call_binary : ifapply, - _, - one<'('>, - _, - r_expr, - _, - one<','>, - _, - r_expr, - _, - one<')'>>, - do_op> {}; - // r_constant <- + ( "." * ) ? ( [eE] [+-] ? + ) ? - struct r_constant : ifapply, - opt, - star>>, - opt, - opt>, - plus>>>, - do_constant> {}; + struct r_constant : seq, + opt, + star>>, + opt, + opt>, + plus>>> {}; // r_var <- "x" - struct r_var : ifapply, do_op> {}; - - // r_call <- r_call_unary / r_call_binary - struct r_call : sor, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_unary, - r_call_binary, - r_call_binary, - r_call_binary, - r_call_binary> {}; + struct r_var : pegtl_string_t("x") {}; + + // r_binary_call <- "(" r_expr "," r_expr ")" + struct r_binary_fun : sor {}; + + struct r_binary_call : seq, + _, r_expr, + _, one<','>, + _, r_expr, + _, one<')'>> {}; + + // r_unary_call <- "(" r_expr ")" + struct r_unary_fun : sor {}; + + struct r_unary_call : seq, + _, r_expr, + _, one<')'>> {}; + + // r_call <- r_binary_call / r_unary_call + struct r_call : sor {}; // r_parentheses <- "(" r_expr ")" struct r_parentheses : seq, - _, - r_expr, - _, + pad, one<')'>> {}; // r_terminal <- r_call / r_var / r_constant / r_parentheses @@ -259,16 +191,16 @@ private: r_parentheses> {}; // r_signed <- "-" r_signed / "+" r_signed / r_terminal - struct r_signed : sor, _, r_signed>, - do_op>, + struct r_signed; + struct r_minus : seq, _, r_signed> {}; + struct r_signed : sor, _, r_signed>, r_terminal> {}; // r_exponent <- ( "^" / "**" ) r_signed - struct r_exponent : ifapply, string<'*', '*'>>, - _, - r_signed>, do_op> {}; + struct r_exponent : seq, + string<'*', '*'>>, space>, + r_signed> {}; // r_factor <- r_signed ( r_exponent ) * struct r_factor : seq, _, r_factor>, do_op> {}; - struct r_div : ifapply, _, r_factor>, do_op> {}; + struct r_mul : seq<_, one<'*'>, _, r_factor> {}; + struct r_div : seq<_, one<'/'>, _, r_factor> {}; struct r_term : seq>> {}; // r_add <- "+" r_term // r_sub <- "-" r_term // r_expr <- r_term ( r_add / r_sub ) * - struct r_add : ifapply, _, r_term>, do_op> {}; - struct r_sub : ifapply, _, r_term>, do_op> {}; + struct r_add : seq<_, one<'+'>, _, r_term> {}; + struct r_sub : seq<_, one<'-'>, _, r_term> {}; struct r_expr : seq>> {}; // r_stmt <- r_expr - struct r_stmt : seq<_, r_expr, _, pegtl::eof> {}; + struct r_stmt : must, pegtl::eof> {}; + + // + // Default actions + // + + template + struct action : nothing {}; + + template + struct generic_action + { + static void apply(input const &in, expression *that) + { + UNUSED(in); + that->m_ops.push(OP, -1); + } + }; + +public: + /* + * Parse arithmetic expression in x, e.g. 2*x+3 + */ + void parse(std::string const &str) + { + m_ops.empty(); + m_constants.empty(); + + pegtl::parse(str, "expression", this); + } +}; + +// +// Rule specialisations for simple operators +// + +template<> struct expression::action : generic_action {}; +template<> struct expression::action : generic_action {}; +template<> struct expression::action : generic_action {}; +template<> struct expression::action : generic_action {}; +template<> struct expression::action : generic_action {}; +template<> struct expression::action : generic_action {}; +template<> struct expression::action : generic_action {}; + +// +// Rule specialisations for unary and binary function calls +// + +template<> +struct expression::action +{ + static void apply(input const &in, expression *that) + { + struct { id id; char const *name; } lut[] = + { + { id::atan2, "atan2" }, + { id::pow, "pow" }, + { id::min, "min" }, + { id::max, "max" }, + }; + + for (auto pair : lut) + { + if (strncmp(in.string().c_str(), pair.name, strlen(pair.name)) != 0) + continue; + + that->m_ops.push(pair.id, -1); + return; + } + } +}; + +template<> +struct expression::action +{ + static void apply(input const &in, expression *that) + { + struct { id id; char const *name; } lut[] = + { + { id::abs, "abs" }, + { id::sqrt, "sqrt" }, + { id::cbrt, "cbrt" }, + { id::exp2, "exp2" }, + { id::exp, "exp" }, + { id::log10, "log10" }, + { id::log2, "log2" }, + { id::log, "log" }, + { id::sinh, "sinh" }, + { id::cosh, "cosh" }, + { id::tanh, "tanh" }, + { id::sin, "sin" }, + { id::cos, "cos" }, + { id::tan, "tan" }, + { id::asin, "asin" }, + { id::acos, "acos" }, + { id::atan, "atan" }, + }; + + for (auto pair : lut) + { + if (strncmp(in.string().c_str(), pair.name, strlen(pair.name)) != 0) + continue; + + that->m_ops.push(pair.id, -1); + return; + } + } +}; + +template<> +struct expression::action +{ + static void apply(input const &in, expression *that) + { + /* FIXME: check if the constant is already in the list */ + that->m_ops.push(id::constant, that->m_constants.count()); + that->m_constants.push(lol::real(in.string().c_str())); + } }; } /* namespace grammar */