summaryrefslogtreecommitdiff
path: root/libadhocutil/lexer.cpp
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-10-14 01:58:19 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2016-10-14 01:58:19 +0100
commit7567f3f24c17dde282a09235a9c43bfc979d17c4 (patch)
treefc5043b6059001c0512376406467f6ece743c353 /libadhocutil/lexer.cpp
parentMigrate file utils from gentoobrowse-api (diff)
downloadlibadhocutil-7567f3f24c17dde282a09235a9c43bfc979d17c4.tar.bz2
libadhocutil-7567f3f24c17dde282a09235a9c43bfc979d17c4.tar.xz
libadhocutil-7567f3f24c17dde282a09235a9c43bfc979d17c4.zip
Migrate extensible lexer from gentoobrowse-api
Diffstat (limited to 'libadhocutil/lexer.cpp')
-rw-r--r--libadhocutil/lexer.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/libadhocutil/lexer.cpp b/libadhocutil/lexer.cpp
new file mode 100644
index 0000000..95e079b
--- /dev/null
+++ b/libadhocutil/lexer.cpp
@@ -0,0 +1,78 @@
+#include "lexer.h"
+
+namespace AdHoc {
+ const Lexer::State Lexer::InitialState = "";
+
+ Lexer::Lexer()
+ {
+ }
+
+ Lexer::Lexer(const Rules & r) : rules(r)
+ {
+ }
+
+ void
+ Lexer::extract(const gchar * string, size_t length) const
+ {
+ ExecuteState es;
+ while (es.position < length) {
+ const Rule * selected = nullptr;
+ for (const auto & r : rules) {
+ const auto & s = boost::get<0>(r);
+ if (s.find(es.getState()) == s.end()) {
+ continue;
+ }
+ const auto & p = boost::get<1>(r);
+ if (p->matches(string, length, es.position)) {
+ selected = &r;
+ break;
+ }
+ }
+ if (!selected) {
+ throw std::runtime_error(std::string("Unexpected input in state (" + es.getState() + ") at ") + (string + es.position));
+ }
+ es.pattern = boost::get<1>(*selected);
+ const auto & h = boost::get<2>(*selected);
+ h(&es);
+ es.position += es.pattern->matchedLength();
+ }
+
+ }
+
+ Lexer::ExecuteState::ExecuteState() :
+ position(0)
+ {
+ stateStack.push_back(InitialState);
+ }
+
+ void
+ Lexer::ExecuteState::setState(const State & s)
+ {
+ stateStack.back() = s;
+ }
+
+ void
+ Lexer::ExecuteState::pushState(const State & s)
+ {
+ stateStack.push_back(s);
+ }
+
+ void
+ Lexer::ExecuteState::popState()
+ {
+ stateStack.pop_back();
+ }
+
+ const Lexer::State &
+ Lexer::ExecuteState::getState() const
+ {
+ return stateStack.back();
+ }
+
+ size_t
+ Lexer::ExecuteState::depth() const
+ {
+ return stateStack.size();
+ }
+}
+