summaryrefslogtreecommitdiff
path: root/libadhocutil/lexer.cpp
blob: 6d16a46eb6fb6e70034794734a3578155fff9a4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include "lexer.h"
#include "compileTimeFormatter.h"

namespace AdHoc {
	const Lexer::State Lexer::InitialState = "";

	Lexer::Lexer() = default;

	Lexer::Lexer(Rules r) : rules(std::move(r)) { }

	AdHocFormatter(UnexpectedInputState, "Unexpected input in state (%?) at %?");
	void
	Lexer::extract(const gchar * string, size_t length) const
	{
		ExecuteState es;
		while (es.pos < length) {
			const Rule * selected = nullptr;
			for (const auto & r : rules) {
				const auto & s = std::get<0>(r);
				if (s.find(es.getState()) == s.end()) {
					continue;
				}
				const auto & p = std::get<1>(r);
				if (p->matches(string, length, es.pos)) {
					selected = &r;
					break;
				}
			}
			if (!selected) {
				throw std::runtime_error(UnexpectedInputState::get(es.getState(), string + es.pos));
			}
			es.pat = std::get<1>(*selected);
			const auto & h = std::get<2>(*selected);
			h(&es);
			es.pos += es.pat->matchedLength();
		}
	}

	Lexer::ExecuteState::ExecuteState()
	{
		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();
	}

	size_t
	Lexer::ExecuteState::position() const
	{
		return pos;
	}

	Lexer::PatternPtr
	Lexer::ExecuteState::pattern() const
	{
		return pat;
	}
}