[ create a new paste ] login | about

Link: http://codepad.org/AIXjWKjg    [ raw code | fork ]

k4st - C++, pasted on Jan 5:
/*
 * main.cpp
 *
 *  Created on: Dec 8, 2010
 *      Author: Peter Goodman
 *     Version: $Id: main.cpp 8 2011-01-04 05:20:54Z peter.goodman $
 *
 * Copyright 2011 Peter Goodman, all rights reserved.
 */

#include <cstring>
#include <cstdio>
#include <cmath>

#include "src/peg/PEG.hpp"

class CalcTraits {
public:
    typedef char token_type;
    typedef long 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;
    }
};

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 neg(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_and_add(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 sum { };
    class product { };
    class factor { };
    class number { };
    class digit { };
    class calc { };

    template <template<typename> class R>
    static void definition(void) throw() {

        R<calc>::add(V<sum,P>() << T<'\0'>()).action(identity);
        R<calc>::add(T<'\0'>()).action(nothing);

        R<sum>::add(V<sum,P>() << T<'+'>() << V<sum,P>()).action(add);
        R<sum>::add(V<sum,P>() << T<'-'>() << V<sum,P>()).action(sub);
        R<sum>::add(V<product,P>()).action(identity);

        R<product>::add(V<product,P>() << T<'*'>() << V<product,P>()).action(mul);
        R<product>::add(V<product,P>() << T<'/'>() << V<product,P>()).action(div);
        R<product>::add(V<factor,P>()).action(identity);

        R<factor>::add(V<factor,P>() << T<'^'>() >> V<factor,P>()).action(exp);
        R<factor>::add(T<'+'>() << V<factor,P>()).action(identity);
        R<factor>::add(T<'-'>() << V<factor,P>()).action(neg);
        R<factor>::add(T<'('>() << V<sum,P>() << T<')'>()).action(identity);
        R<factor>::add(V<number,P>()).action(identity);

        R<number>::add(V<number,P>() << V<digit,P>()).action(shift_and_add);
        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);
    }
};

/// read a line of input
void read_string(char *str, const int max_len) {
    char c;
    int end_char;
    memset(str, 0, sizeof(char) * max_len);
    if(NULL != fgets(str, max_len, stdin)) {
        end_char = strlen(str) - 1;
        if(end_char >= 0 && '\n' == str[end_char]) {
            str[end_char] = '\0';
            ungetc('\n', stdin);
        }
        do {
            c = getchar();
        } while(c != '\n' && c != EOF);
    }
}

int main(void) {

    typedef cp::peg::PEG<Calc> Calculator;

    Calculator::Program instructions(Calculator::compile());
    Calculator::Parser parser(instructions.load());

    char buffer[1024];
    CalcTraits::result_type result;

    for(; true; result = 0.0) {
        printf(">> ");
        read_string(buffer, 1023);

        if('\0' == buffer[0]) {
            break;
        }

        if(parser.run(buffer, strlen(buffer) + 1, &result)) {
            printf("%Lf\n", result);
        } else {
            printf("parse error.\n");
        }
    }

    return 0;
}


Create a new paste based on this one


Comments: