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 */