Browse Source

lolremez: shorter code in the expression parser.

undefined
Sam Hocevar 10 years ago
parent
commit
4e76c6e708
1 changed files with 58 additions and 99 deletions
  1. +58
    -99
      tools/lolremez/expression.h

+ 58
- 99
tools/lolremez/expression.h View File

@@ -13,7 +13,12 @@
#pragma once

//
// Parser tools for a simple calculator grammar with + - * /
// Powerful arithmetic expression parser/evaluator
//
// Usage:
// expression e;
// e.parse(" 2*x^3 + 3 * sin(x - atan(x))");
// auto y = e.eval("1.5");
//

#include "pegtl.hh"
@@ -85,114 +90,68 @@ struct expression
*/
lol::real eval(lol::real const &x) const
{
/* Use a stack */
lol::array<lol::real> stack;
lol::real tmp;

for (int i = 0; i < m_ops.Count(); ++i)
{
switch (m_ops[i].m1)
/* Rules that do not consume stack elements */
if (m_ops[i].m1 == op::x)
{
case op::plus:
break;
case op::minus:
stack.Push(-stack.Pop());
break;
case op::abs:
stack.Push(fabs(stack.Pop()));
break;
case op::sqrt:
stack.Push(sqrt(stack.Pop()));
break;
case op::cbrt:
stack.Push(cbrt(stack.Pop()));
break;
case op::exp:
stack.Push(exp(stack.Pop()));
break;
case op::exp2:
stack.Push(exp2(stack.Pop()));
break;
case op::log:
stack.Push(log(stack.Pop()));
break;
case op::log2:
stack.Push(log2(stack.Pop()));
break;
case op::log10:
stack.Push(log10(stack.Pop()));
break;
case op::sin:
stack.Push(sin(stack.Pop()));
break;
case op::cos:
stack.Push(cos(stack.Pop()));
break;
case op::tan:
stack.Push(tan(stack.Pop()));
break;
case op::asin:
stack.Push(asin(stack.Pop()));
break;
case op::acos:
stack.Push(acos(stack.Pop()));
break;
case op::atan:
stack.Push(atan(stack.Pop()));
break;
case op::sinh:
stack.Push(sinh(stack.Pop()));
break;
case op::cosh:
stack.Push(cosh(stack.Pop()));
break;
case op::tanh:
stack.Push(tanh(stack.Pop()));
break;
stack.push(x);
continue;
}
else if (m_ops[i].m1 == op::constant)
{
stack.push(m_constants[m_ops[i].m2]);
continue;
}

case op::add:
tmp = stack.Pop();
stack.Push(stack.Pop() + tmp);
break;
case op::sub:
tmp = stack.Pop();
stack.Push(stack.Pop() - tmp);
break;
case op::mul:
tmp = stack.Pop();
stack.Push(stack.Pop() * tmp);
break;
case op::div:
tmp = stack.Pop();
stack.Push(stack.Pop() / tmp);
break;
case op::atan2:
tmp = stack.Pop();
stack.Push(atan2(stack.Pop(), tmp));
break;
case op::pow:
tmp = stack.Pop();
stack.Push(pow(stack.Pop(), tmp));
break;
case op::min:
tmp = stack.Pop();
stack.Push(min(stack.Pop(), tmp));
break;
case op::max:
tmp = stack.Pop();
stack.Push(max(stack.Pop(), tmp));
break;
/* All other rules consume at least the head of the stack */
lol::real head = stack.pop();

case op::x:
stack.Push(x);
break;
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:
stack.Push(m_constants[m_ops[i].m2]);
/* Already handled above */
break;
}
}

return stack.Pop();
ASSERT(stack.count() == 1);
return stack.pop();
}

private:
@@ -205,8 +164,8 @@ private:
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()));
that->m_ops.push(op::constant, that->m_constants.Count());
that->m_constants.push(lol::real(ctx.c_str()));
}
};

@@ -216,7 +175,7 @@ private:
static void apply(std::string const &ctx, expression *that)
{
UNUSED(ctx);
that->m_ops.Push(OP, -1);
that->m_ops.push(OP, -1);
}
};



Loading…
Cancel
Save