Browse Source

Port all parsers to PEGTL 1.3.1.

There might be issues with lolremez but at first sight it seems to work.
undefined
Sam Hocevar 8 years ago
parent
commit
6a6ecc66e9
4 changed files with 251 additions and 193 deletions
  1. +1
    -1
      build/msbuild/lol.vars.props
  2. +1
    -1
      configure.ac
  3. +35
    -26
      src/gpu/shader.cpp
  4. +214
    -165
      tools/lolremez/expression.h

+ 1
- 1
build/msbuild/lol.vars.props View File

@@ -5,7 +5,7 @@
<ExternalDir>$(SolutionDir)\..\external</ExternalDir>

<!-- PEGTL -->
<PegtlDir>$(ExternalDir)\pegtl-0.32</PegtlDir>
<PegtlDir>$(ExternalDir)\pegtl-1.3.1</PegtlDir>
<PegtlIncludes>$(PegtlDir)\include</PegtlIncludes>

<!-- imgui -->


+ 1
- 1
configure.ac View File

@@ -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




+ 35
- 26
src/gpu/shader.cpp View File

@@ -117,42 +117,22 @@ using namespace pegtl;

struct lolfx_parser
{
public:
lolfx_parser(String const &code)
: m_section("header")
{
basic_parse_string<struct lolfx>(std::string(code.C()), this);
}

public:
String m_section;
map<String, String> m_programs;

private:
struct do_title : action_base<do_title>
{
static void apply(std::string const &ctx, lolfx_parser *that)
{
that->m_section = ctx.c_str();
}
};

struct do_code : action_base<do_code>
{
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<not_one<']'>> {};

struct title
: seq<one<'['>,
ifapply<plus<not_one<']'>>, do_title>,
do_title,
one<']'>,
until<eol, any>> {};

// 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<one<'['>,
@@ -166,7 +146,7 @@ private:

// code_section < code_line{&(title / eof)}
struct code_section
: ifapply<until<at<sor<title_ignore, pegtl::eof>>, code_line>, do_code> {};
: until<at<sor<title_ignore, pegtl::eof>>, code_line> {};

// shader < title code_section
struct shader
@@ -179,6 +159,35 @@ private:
// lolfx < header code_section*
struct lolfx
: seq<header, star<shader>> {};

// default action: nothing
template<typename RULE>
struct action : nothing<RULE> {};

public:
lolfx_parser(String const &code)
: m_section("header")
{
pegtl::parse<lolfx, action>(code.C(), "shader", this);
}
};

template<>
struct lolfx_parser::action<lolfx_parser::do_title>
{
static void apply(input const &in, lolfx_parser *that)
{
that->m_section = in.string().c_str();
}
};

template<>
struct lolfx_parser::action<lolfx_parser::code_section>
{
static void apply(input const &in, lolfx_parser *that)
{
that->m_programs[that->m_section] = in.string().c_str();
}
};

/*


+ 214
- 165
tools/lolremez/expression.h View File

@@ -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<op OP> struct r_call_string {};

template<> struct r_call_string<op::abs> : string<'a','b','s'> {};
template<> struct r_call_string<op::sqrt> : string<'s','q','r','t'> {};
template<> struct r_call_string<op::cbrt> : string<'c','b','r','t'> {};
template<> struct r_call_string<op::exp> : string<'e','x','p'> {};
template<> struct r_call_string<op::exp2> : string<'e','x','p','2'> {};
template<> struct r_call_string<op::log> : string<'l','o','g'> {};
template<> struct r_call_string<op::log2> : string<'l','o','g','2'> {};
template<> struct r_call_string<op::log10> : string<'l','o','g','1','0'> {};
template<> struct r_call_string<op::sin> : string<'s','i','n'> {};
template<> struct r_call_string<op::cos> : string<'c','o','s'> {};
template<> struct r_call_string<op::tan> : string<'t','a','n'> {};
template<> struct r_call_string<op::asin> : string<'a','s','i','n'> {};
template<> struct r_call_string<op::acos> : string<'a','c','o','s'> {};
template<> struct r_call_string<op::atan> : string<'a','t','a','n'> {};
template<> struct r_call_string<op::sinh> : string<'s','i','n','h'> {};
template<> struct r_call_string<op::cosh> : string<'c','o','s','h'> {};
template<> struct r_call_string<op::tanh> : string<'t','a','n','h'> {};

template<> struct r_call_string<op::atan2> : string<'a','t','a','n','2'> {};
template<> struct r_call_string<op::pow> : string<'p','o','w'> {};
template<> struct r_call_string<op::min> : string<'m','i','n'> {};
template<> struct r_call_string<op::max> : 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<r_stmt>(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<op, int> m_ops;
lol::array<id, int> m_ops;
lol::array<lol::real> m_constants;

private:
struct do_constant : action_base<do_constant>
{
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<op OP>
struct do_op : action_base<do_op<OP>>
{
static void apply(std::string const &ctx, expression *that)
{
UNUSED(ctx);
that->m_ops.push(OP, -1);
}
};

struct r_expr;

// r_ <- <blank> *
struct _ : star<space> {};

// r_call_unary <- <unary_op> "(" r_expr ")"
template<op OP>
struct r_call_unary : ifapply<seq<r_call_string<OP>,
_,
one<'('>,
_,
r_expr,
_,
one<')'>>,
do_op<OP>> {};

// r_call_binary <- <binary_op> "(" r_expr "," r_expr ")"
template<op OP>
struct r_call_binary : ifapply<seq<r_call_string<OP>,
_,
one<'('>,
_,
r_expr,
_,
one<','>,
_,
r_expr,
_,
one<')'>>,
do_op<OP>> {};

// r_constant <- <digit> + ( "." <digit> * ) ? ( [eE] [+-] ? <digit> + ) ?
struct r_constant : ifapply<seq<plus<digit>,
opt<seq<one<'.'>,
star<digit>>>,
opt<seq<one<'e', 'E'>,
opt<one<'+', '-'>>,
plus<digit>>>>,
do_constant> {};
struct r_constant : seq<plus<digit>,
opt<seq<one<'.'>,
star<digit>>>,
opt<seq<one<'e', 'E'>,
opt<one<'+', '-'>>,
plus<digit>>>> {};

// r_var <- "x"
struct r_var : ifapply<one<'x'>, do_op<op::x>> {};

// r_call <- r_call_unary / r_call_binary
struct r_call : sor<r_call_unary<op::abs>,
r_call_unary<op::sqrt>,
r_call_unary<op::cbrt>,
r_call_unary<op::exp>,
r_call_unary<op::exp2>,
r_call_unary<op::log>,
r_call_unary<op::log2>,
r_call_unary<op::log10>,
r_call_unary<op::sin>,
r_call_unary<op::cos>,
r_call_unary<op::tan>,
r_call_unary<op::asin>,
r_call_unary<op::acos>,
r_call_unary<op::atan>,
r_call_unary<op::sinh>,
r_call_unary<op::cosh>,
r_call_unary<op::tanh>,
r_call_binary<op::atan2>,
r_call_binary<op::pow>,
r_call_binary<op::min>,
r_call_binary<op::max>> {};
struct r_var : pegtl_string_t("x") {};

// r_binary_call <- <r_binary_fun> "(" r_expr "," r_expr ")"
struct r_binary_fun : sor<pegtl_string_t("atan2"),
pegtl_string_t("pow"),
pegtl_string_t("min"),
pegtl_string_t("max")> {};

struct r_binary_call : seq<r_binary_fun,
_, one<'('>,
_, r_expr,
_, one<','>,
_, r_expr,
_, one<')'>> {};

// r_unary_call <- <r_unary_fun> "(" r_expr ")"
struct r_unary_fun : sor<pegtl_string_t("abs"),
pegtl_string_t("sqrt"),
pegtl_string_t("cbrt"),
pegtl_string_t("exp"),
pegtl_string_t("exp2"),
pegtl_string_t("log"),
pegtl_string_t("log2"),
pegtl_string_t("log10"),
pegtl_string_t("sin"),
pegtl_string_t("cos"),
pegtl_string_t("tan"),
pegtl_string_t("asin"),
pegtl_string_t("acos"),
pegtl_string_t("atan"),
pegtl_string_t("sinh"),
pegtl_string_t("cosh"),
pegtl_string_t("tanh")> {};

struct r_unary_call : seq<r_unary_fun,
_, one<'('>,
_, r_expr,
_, one<')'>> {};

// r_call <- r_binary_call / r_unary_call
struct r_call : sor<r_binary_call,
r_unary_call> {};

// r_parentheses <- "(" r_expr ")"
struct r_parentheses : seq<one<'('>,
_,
r_expr,
_,
pad<r_expr, space>,
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<ifapply<seq<one<'-'>, _, r_signed>,
do_op<op::minus>>,
struct r_signed;
struct r_minus : seq<one<'-'>, _, r_signed> {};
struct r_signed : sor<r_minus,
seq<one<'+'>, _, r_signed>,
r_terminal> {};

// r_exponent <- ( "^" / "**" ) r_signed
struct r_exponent : ifapply<seq<_,
sor<one<'^'>, string<'*', '*'>>,
_,
r_signed>, do_op<op::pow>> {};
struct r_exponent : seq<pad<sor<one<'^'>,
string<'*', '*'>>, space>,
r_signed> {};

// r_factor <- r_signed ( r_exponent ) *
struct r_factor : seq<r_signed,
@@ -277,21 +209,138 @@ private:
// r_mul <- "*" r_factor
// r_div <- "/" r_factor
// r_term <- r_factor ( r_mul / r_div ) *
struct r_mul : ifapply<seq<_, one<'*'>, _, r_factor>, do_op<op::mul>> {};
struct r_div : ifapply<seq<_, one<'/'>, _, r_factor>, do_op<op::div>> {};
struct r_mul : seq<_, one<'*'>, _, r_factor> {};
struct r_div : seq<_, one<'/'>, _, r_factor> {};
struct r_term : seq<r_factor,
star<sor<r_mul, r_div>>> {};

// r_add <- "+" r_term
// r_sub <- "-" r_term
// r_expr <- r_term ( r_add / r_sub ) *
struct r_add : ifapply<seq<_, one<'+'>, _, r_term>, do_op<op::add>> {};
struct r_sub : ifapply<seq<_, one<'-'>, _, r_term>, do_op<op::sub>> {};
struct r_add : seq<_, one<'+'>, _, r_term> {};
struct r_sub : seq<_, one<'-'>, _, r_term> {};
struct r_expr : seq<r_term,
star<sor<r_add, r_sub>>> {};

// r_stmt <- r_expr <end>
struct r_stmt : seq<_, r_expr, _, pegtl::eof> {};
struct r_stmt : must<pad<r_expr, space>, pegtl::eof> {};

//
// Default actions
//

template<typename R>
struct action : nothing<R> {};

template<id OP>
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<r_stmt, action>(str, "expression", this);
}
};

//
// Rule specialisations for simple operators
//

template<> struct expression::action<expression::r_var> : generic_action<id::x> {};
template<> struct expression::action<expression::r_exponent> : generic_action<id::pow> {};
template<> struct expression::action<expression::r_mul> : generic_action<id::mul> {};
template<> struct expression::action<expression::r_div> : generic_action<id::div> {};
template<> struct expression::action<expression::r_add> : generic_action<id::add> {};
template<> struct expression::action<expression::r_sub> : generic_action<id::sub> {};
template<> struct expression::action<expression::r_minus> : generic_action<id::minus> {};

//
// Rule specialisations for unary and binary function calls
//

template<>
struct expression::action<expression::r_binary_call>
{
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<expression::r_unary_call>
{
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<expression::r_constant>
{
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 */


Loading…
Cancel
Save