diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-11-07 08:10:47 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-11-07 08:10:47 +0100 |
commit | 8a7d756c01d63761226725288caba0a1563389b0 (patch) | |
tree | 8c62cf1fab4e1c6ee7f9080769838b6e798756c9 | |
parent | 2ed38e4d01d73d62b29a28d7540ca515f9ff3b09 (diff) | |
download | sciteco-8a7d756c01d63761226725288caba0a1563389b0.tar.gz |
expression stack fixes and some arithmetic commands
-rw-r--r-- | expressions.cpp | 6 | ||||
-rw-r--r-- | expressions.h | 18 | ||||
-rw-r--r-- | parser.cpp | 64 |
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); @@ -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; |