diff options
-rw-r--r-- | expressions.h | 5 | ||||
-rw-r--r-- | parser.cpp | 83 | ||||
-rw-r--r-- | parser.h | 9 |
3 files changed, 93 insertions, 4 deletions
diff --git a/expressions.h b/expressions.h index e456449..ef41b15 100644 --- a/expressions.h +++ b/expressions.h @@ -157,6 +157,11 @@ public: 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); @@ -15,10 +15,11 @@ gint macro_pc = 0; namespace States { - StateStart start; - StateControl control; - StateECommand ecommand; - StateInsert insert; + StateStart start; + StateControl control; + StateFlowCommand flowcommand; + StateECommand ecommand; + StateInsert insert; State *current = &start; } @@ -199,6 +200,7 @@ StateStart::StateStart() : State() transitions['!'] = &States::label; transitions['^'] = &States::control; + transitions['F'] = &States::flowcommand; transitions['E'] = &States::ecommand; transitions['I'] = &States::insert; transitions['Q'] = &States::getqreginteger; @@ -517,6 +519,79 @@ StateStart::custom(gchar chr) return this; } +StateFlowCommand::StateFlowCommand() : State() +{ + transitions['\0'] = this; +} + +State * +StateFlowCommand::custom(gchar chr) +{ + switch (chr) { + /* + * loop flow control + */ + case '<': + BEGIN_EXEC(&States::start); + /* FIXME: what if in brackets? */ + expressions.discard_args(); + if (expressions.peek_op() == Expressions::OP_LOOP) + /* repeat loop */ + macro_pc = expressions.peek_num(); + else + macro_pc = -1; + break; + + case '>': { + gint64 loop_pc, loop_cnt; + + BEGIN_EXEC(&States::start); + /* FIXME: what if in brackets? */ + expressions.discard_args(); + g_assert(expressions.pop_op() == Expressions::OP_LOOP); + loop_pc = expressions.pop_num(); + loop_cnt = expressions.pop_num(); + + if (loop_cnt != 1) { + /* repeat loop */ + macro_pc = loop_pc; + expressions.push(MAX(loop_cnt - 1, -1)); + expressions.push(loop_pc); + expressions.push(Expressions::OP_LOOP); + } else { + /* skip to end of loop */ + undo.push_var<Mode>(mode); + mode = MODE_PARSE_ONLY; + } + break; + } + + /* + * conditional flow control + */ + case '\'': + BEGIN_EXEC(&States::start); + /* skip to end of conditional */ + undo.push_var<Mode>(mode); + mode = MODE_PARSE_ONLY; + undo.push_var<bool>(skip_else); + skip_else = true; + break; + + case '|': + BEGIN_EXEC(&States::start); + /* skip to ELSE-part or end of conditional */ + undo.push_var<Mode>(mode); + mode = MODE_PARSE_ONLY; + break; + + default: + return NULL; + } + + return &States::start; +} + StateControl::StateControl() : State() { transitions['\0'] = this; @@ -96,6 +96,14 @@ private: State *custom(gchar chr); }; +class StateFlowCommand : public State { +public: + StateFlowCommand(); + +private: + State *custom(gchar chr); +}; + class StateECommand : public State { public: StateECommand(); @@ -116,6 +124,7 @@ extern gint macro_pc; namespace States { extern StateStart start; extern StateControl control; + extern StateFlowCommand flowcommand; extern StateECommand ecommand; extern StateInsert insert; |