diff options
| author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-02-14 00:55:04 +0100 |
|---|---|---|
| committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-02-14 05:21:03 +0100 |
| commit | 9cd71e16b30e2f0061a6d74421a5357333721a70 (patch) | |
| tree | bb362c1ffed48fe9af5ca0cf70c38caacfca2e45 /src/qregisters.cpp | |
| parent | 91ae87c7ab0c26a387eb42243e50baf0ded30250 (diff) | |
micro state machine for Q-Register specifications: allow long Q-Reg names
syntax is as follows: ["."]("#" CHR1 CHR2 | "{" STRING_BUILDING "}" | CHR1)
* the short one/two char names are turned upper case, while no
case folding is performed on verbose names
Diffstat (limited to 'src/qregisters.cpp')
| -rw-r--r-- | src/qregisters.cpp | 93 |
1 files changed, 78 insertions, 15 deletions
diff --git a/src/qregisters.cpp b/src/qregisters.cpp index 6eea64f..7fb5b27 100644 --- a/src/qregisters.cpp +++ b/src/qregisters.cpp @@ -357,11 +357,85 @@ QRegisters::hook(Hook type) globals["0"]->execute(); } +void +QRegSpecMachine::reset(void) +{ + MicroStateMachine::reset(); + string_machine.reset(); + undo.push_var(is_local) = false; + undo.push_var(nesting) = 0; + undo.push_str(name); + g_free(name); + name = NULL; +} + +QRegister * +QRegSpecMachine::input(gchar chr) throw (State::Error) +{ + QRegister *reg; + gchar *insert; + + if (state) + goto *state; + + /* NULL state */ + switch (chr) { + case '.': undo.push_var(is_local) = true; break; + case '#': set(&&StateFirstChar); break; + case '{': set(&&StateString); break; + default: + undo.push_str(name) = g_strdup(CHR2STR(g_ascii_toupper(chr))); + goto done; + } + + return NULL; + +StateFirstChar: + undo.push_str(name) = (gchar *)g_malloc(3); + name[0] = g_ascii_toupper(chr); + set(&&StateSecondChar); + return NULL; + +StateSecondChar: + name[1] = g_ascii_toupper(chr); + name[2] = '\0'; + goto done; + +StateString: + switch (chr) { + case '{': + undo.push_var(nesting)++; + break; + case '}': + if (!nesting) + goto done; + undo.push_var(nesting)--; + break; + } + + insert = string_machine.input(chr); + if (!insert) + return NULL; + + undo.push_str(name); + String::append(name, insert); + g_free(insert); + return NULL; + +done: + reg = is_local ? (*QRegisters::locals)[name] + : QRegisters::globals[name]; + if (!reg) + throw State::InvalidQRegError(name, is_local); + + return reg; +} + /* * Command states */ -StateExpectQReg::StateExpectQReg() : State(), got_local(false) +StateExpectQReg::StateExpectQReg() : State() { transitions['\0'] = this; } @@ -369,22 +443,11 @@ StateExpectQReg::StateExpectQReg() : State(), got_local(false) State * StateExpectQReg::custom(gchar chr) throw (Error, ReplaceCmdline) { - QRegister *reg; + QRegister *reg = machine.input(chr); - if (chr == '.') { - undo.push_var(got_local) = true; - return this; - } - chr = g_ascii_toupper(chr); - - if (got_local) { - undo.push_var(got_local) = false; - reg = (*QRegisters::locals)[chr]; - } else { - reg = QRegisters::globals[chr]; - } if (!reg) - throw InvalidQRegError(chr, got_local); + return this; + machine.reset(); return got_register(*reg); } |
