aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-07 08:10:47 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-07 08:10:47 +0100
commit8a7d756c01d63761226725288caba0a1563389b0 (patch)
tree8c62cf1fab4e1c6ee7f9080769838b6e798756c9
parent2ed38e4d01d73d62b29a28d7540ca515f9ff3b09 (diff)
downloadsciteco-8a7d756c01d63761226725288caba0a1563389b0.tar.gz
expression stack fixes and some arithmetic commands
-rw-r--r--expressions.cpp6
-rw-r--r--expressions.h18
-rw-r--r--parser.cpp64
3 files changed, 75 insertions, 13 deletions
diff --git a/expressions.cpp b/expressions.cpp
index 1e48d3e..8c8fb0c 100644
--- a/expressions.cpp
+++ b/expressions.cpp
@@ -23,7 +23,7 @@ Expressions::set_radix(gint r)
gint64
Expressions::push(gint64 number)
{
- while (numbers.peek() == G_MAXINT64)
+ while (numbers.items() > 0 && numbers.peek() == G_MAXINT64)
pop_num();
push(OP_NUMBER);
@@ -87,8 +87,10 @@ Expressions::push(Expressions::Operator op)
Expressions::Operator
Expressions::push_calc(Expressions::Operator op)
{
+ int first = first_op();
+
/* calculate if op has lower precedence than op on stack */
- if (operators.peek(first_op()) <= op)
+ if (first && operators.peek(first) <= op)
calc();
return push(op);
diff --git a/expressions.h b/expressions.h
index 2ff9c1a..4a33632 100644
--- a/expressions.h
+++ b/expressions.h
@@ -26,7 +26,7 @@ public:
inline int
items(void)
{
- return (top - stack)/sizeof(Type);
+ return top - stack;
}
inline Type &
@@ -97,6 +97,7 @@ public:
* Arithmetic expression stacks
*/
extern class Expressions {
+public:
/* reflects also operator precedence */
enum Operator {
OP_NIL = 0,
@@ -114,20 +115,26 @@ extern class Expressions {
OP_NUMBER
};
+private:
ValueStack<gint64> numbers;
ValueStack<Operator> operators;
- gint num_sign;
- gint radix;
-
public:
Expressions() : num_sign(1), radix(10) {}
+ gint num_sign;
void set_num_sign(gint sign);
+
+ gint radix;
void set_radix(gint r);
gint64 push(gint64 number);
+ inline gint64
+ peek_num(int index = 1)
+ {
+ return numbers.peek(index);
+ }
gint64 pop_num(int index = 1);
gint64 pop_num_calc(int index, gint64 imply);
inline gint64
@@ -151,7 +158,8 @@ public:
inline int
first_op(void)
{
- return args() + 1;
+ int n = args() + 1;
+ return n > operators.items() ? 0 : n;
}
void discard_args(void);
diff --git a/parser.cpp b/parser.cpp
index bd31734..6c92bc2 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -3,6 +3,7 @@
#include "sciteco.h"
#include "undo.h"
+#include "expressions.h"
#include "parser.h"
gint macro_pc = 0;
@@ -76,20 +77,71 @@ State *
StateStart::custom(gchar chr)
{
#if 0
+ /*
+ * <CTRL/x> commands implemented in StateCtrlCmd
+ */
if (IS_CTL(chr))
return states.ctl.get_next_state(CTL_ECHO(chr));
#endif
+ /*
+ * arithmetics
+ */
+ if (g_ascii_isdigit(chr)) {
+ expressions.add_digit(chr);
+ return this;
+ }
+
switch (g_ascii_toupper(chr)) {
+ case '/':
+ expressions.push_calc(Expressions::OP_DIV);
+ break;
+ case '*':
+ expressions.push_calc(Expressions::OP_MUL);
+ break;
+ case '+':
+ expressions.push_calc(Expressions::OP_ADD);
+ break;
+ case '-':
+ if (!expressions.args() &&
+ expressions.peek_num() == G_MAXINT64)
+ expressions.set_num_sign(-expressions.num_sign);
+ else
+ expressions.push_calc(Expressions::OP_SUB);
+ break;
+ case '&':
+ expressions.push_calc(Expressions::OP_AND);
+ break;
+ case '#':
+ expressions.push_calc(Expressions::OP_OR);
+ break;
+ case '(':
+ if (expressions.num_sign < 0) {
+ expressions.push(-1);
+ expressions.push_calc(Expressions::OP_MUL);
+ }
+ expressions.push(Expressions::OP_BRACE);
+ break;
+ case ')':
+ expressions.eval(true);
+ break;
+ case ',':
+ expressions.eval();
+ expressions.push(G_MAXINT64);
+ break;
/*
* commands
*/
- case 'C':
- editor_msg(SCI_CHARRIGHT);
- undo.push_msg(SCI_CHARLEFT);
- break;
- default:
- return NULL;
+ case 'C':
+ editor_msg(SCI_CHARRIGHT);
+ undo.push_msg(SCI_CHARLEFT);
+ break;
+ case '=':
+ message_display(GTK_MESSAGE_OTHER, "%" G_GINT64_FORMAT,
+ expressions.pop_num_calc());
+ break;
+ default:
+ return NULL;
}
return this;