/*
* main.cpp
*
* Created on: Dec 8, 2010
* Author: Peter Goodman
* Version: $Id: main.cpp 6 2011-01-03 22:20:52Z peter.goodman $
*
* Copyright 2011 Peter Goodman, all rights reserved.
*/
#include <cstring>
#include <cmath>
#include "src/peg/PEG.hpp"
class CalcTraits {
public:
typedef char token_type;
typedef double result_type;
typedef char terminal_type;
static unsigned terminal_to_unsigned(terminal_type tt) {
return static_cast<unsigned>(tt);
}
static terminal_type token_to_terminal(const token_type *tok) {
return *tok;
}
};
template <template<typename> class R>
class Calc : public cp::peg::Grammar<CalcTraits> {
public:
static result_type add(result_type left, result_type right) throw() {
return left + right;
}
static result_type sub(result_type left, result_type right) throw() {
return left - right;
}
static result_type mul(result_type left, result_type right) throw() {
return left * right;
}
static result_type div(result_type left, result_type right) throw() {
return left / right;
}
static result_type negate(result_type x) throw() {
return -x;
}
static result_type exp(result_type left, result_type right) throw() {
return static_cast<result_type>(pow(left, right));
}
static result_type shift(result_type old, result_type digit) throw() {
return (old * 10.0) + digit;
}
static result_type char_to_number(const token_type cc) throw() {
return 0.0 + static_cast<result_type>(cc - '0');
}
class result { };
class factor { };
class number { };
class digit { };
class calc { };
static void definition(void) throw() {
R<calc>::add(V<result,P>() << T<'\0'>()).action(identity);
R<calc>::add(T<'\0'>()).action(nothing);
R<result>::add(V<result,P>() << T<'*'>() << V<result,P>()).action(mul);
R<result>::add(V<result,P>() << T<'/'>() << V<result,P>()).action(div);
R<result>::add(V<result,P>() << T<'+'>() << V<result,P>()).action(add);
R<result>::add(V<result,P>() << T<'-'>() << V<result,P>()).action(sub);
R<result>::add(V<factor,P>()).action(identity);
R<factor>::add(V<factor,P>() << T<'^'>() >> V<factor,P>()).action(exp);
R<factor>::add(V<number,P>()).action(identity);
R<factor>::add(T<'-'>() << V<result,P>()).action(negate);
R<factor>::add(T<'('>() << V<result,P>() << T<')'>()).action(identity);
R<factor>::add(V<number,P>()).action(identity);
R<number>::add(V<number,P>() << V<digit,P>()).action(shift);
R<number>::add(V<digit,P>()).action(identity);
R<digit>::add(T<'0',P>()).action(char_to_number);
R<digit>::add(T<'1',P>()).action(char_to_number);
R<digit>::add(T<'2',P>()).action(char_to_number);
R<digit>::add(T<'3',P>()).action(char_to_number);
R<digit>::add(T<'4',P>()).action(char_to_number);
R<digit>::add(T<'5',P>()).action(char_to_number);
R<digit>::add(T<'6',P>()).action(char_to_number);
R<digit>::add(T<'7',P>()).action(char_to_number);
R<digit>::add(T<'8',P>()).action(char_to_number);
R<digit>::add(T<'9',P>()).action(char_to_number);
}
};
int main(int argc, const char **argv) {
typedef cp::peg::PEG<Calc> Calculator;
Calculator::Program instructions(Calculator::compile());
Calculator::Parser parser(instructions.load());
if(1 < argc) {
const char *str(argv[1]);
instructions.print();
double result;
if(parser.run(str, strlen(str) + 1, &result)) {
printf("\nresult = %f\n", result);
}
}
return 0;
}