/*
* Copyright (C) 2012-2013 Robin Haberkorn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef __EXPRESSIONS_H
#define __EXPRESSIONS_H
#include
#include "undo.h"
template
class ValueStack {
class UndoTokenPush : public UndoToken {
ValueStack *stack;
Type value;
int index;
public:
UndoTokenPush(ValueStack *_stack,
Type _value, int _index = 1)
: stack(_stack), value(_value), index(_index) {}
void
run(void)
{
stack->push(value, index);
}
};
class UndoTokenPop : public UndoToken {
ValueStack *stack;
int index;
public:
UndoTokenPop(ValueStack *_stack, int _index = 1)
: stack(_stack), index(_index) {}
void
run(void)
{
stack->pop(index);
}
};
int size;
Type *stack;
Type *top;
public:
ValueStack(int _size = 1024) : size(_size)
{
top = stack = new Type[size];
}
~ValueStack()
{
delete stack;
}
inline int
items(void)
{
return top - stack;
}
inline Type &
push(Type value, int index = 1)
{
for (int i = -index + 1; i; i++)
top[i+1] = top[i];
top++;
return peek(index) = value;
}
inline void
undo_push(Type value, int index = 1)
{
undo.push(new UndoTokenPush(this, value, index));
}
inline Type
pop(int index = 1)
{
Type v = peek(index);
top--;
while (--index)
top[-index] = top[-index + 1];
return v;
}
inline void
undo_pop(int index = 1)
{
undo.push(new UndoTokenPop(this, index));
}
inline Type &
peek(int index = 1)
{
return top[-index];
}
inline void
clear(void)
{
top = stack;
}
};
/*
* Arithmetic expression stacks
*/
extern class Expressions {
public:
/* reflects also operator precedence */
enum Operator {
OP_NIL = 0,
OP_POW, // ^*
OP_MUL, // *
OP_DIV, // /
OP_MOD, // ^/
OP_SUB, // -
OP_ADD, // +
OP_AND, // &
OP_OR, // #
// pseudo operators:
OP_NEW,
OP_BRACE,
OP_LOOP,
OP_NUMBER
};
private:
ValueStack numbers;
ValueStack operators;
public:
Expressions() : num_sign(1), radix(10) {}
gint num_sign;
void set_num_sign(gint sign);
gint radix;
void set_radix(gint r);
tecoInt push(tecoInt number);
inline tecoInt
peek_num(int index = 1)
{
return numbers.peek(index);
}
tecoInt pop_num(int index = 1);
tecoInt pop_num_calc(int index, tecoInt imply);
inline tecoInt
pop_num_calc(int index = 1)
{
return pop_num_calc(index, num_sign);
}
tecoInt add_digit(gchar digit);
Operator push(Operator op);
Operator push_calc(Operator op);
inline Operator
peek_op(int index = 1)
{
return operators.peek(index);
}
Operator pop_op(int index = 1);
void eval(bool pop_brace = false);
int args(void);
void discard_args(void);
int find_op(Operator op);
inline void
clear(void)
{
numbers.clear();
operators.clear();
}
const gchar *format(tecoInt number);
private:
void calc(void);
int first_op(void);
} expressions;
#endif