Parser template implementation
This commit is contained in:
parent
a4cd31c011
commit
85d5142c60
|
@ -2,7 +2,9 @@
|
|||
#ifndef PARSODUS_PARSER_{{name}}_H
|
||||
#define PARSODUS_PARSER_{{name}}_H
|
||||
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <stack>
|
||||
|
||||
template <typename Value>
|
||||
class {{name}} {
|
||||
|
@ -48,15 +50,25 @@ class {{name}} {
|
|||
* Apply a reduction (a grammar rule in reverse)
|
||||
*/
|
||||
{{#rules}}
|
||||
{{#name}}virtual Value reduce_{{name}}(const std::deque<Token>& subparts) = 0;{{/name}}
|
||||
{{^name}}virtual Value reduce_{{index}}(const std::deque<Token>& subparts) = 0;{{/name}}
|
||||
{{#name}}virtual Token reduce_{{name}}(std::deque<Token> subparts) = 0;{{/name}}
|
||||
{{^name}}virtual Token reduce_{{index}}(std::deque<Token> subparts) = 0;{{/name}}
|
||||
{{/rules}}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#define TABLE {{name}}___Table___{{name}}
|
||||
#define REDUCE_COUNT {{name}}___Num_Reduces___{{name}}
|
||||
// Not a static member because the table should not be replicated for different instantiations of the parser
|
||||
extern const std::uint64_t {{name}}___Table[%(num_states)][%(num_symbols)];
|
||||
extern const std::uint64_t TABLE[%(num_states)][%(num_symbols)];
|
||||
extern const unsigned char REDUCE_COUNT[%(num_rules)];
|
||||
|
||||
enum Action {
|
||||
ERROR = 0,
|
||||
SHIFT = 1,
|
||||
REDUCE = 2,
|
||||
ACCEPT = 3
|
||||
};
|
||||
|
||||
|
||||
/***************************
|
||||
|
@ -64,7 +76,61 @@ extern const std::uint64_t {{name}}___Table[%(num_states)][%(num_symbols)];
|
|||
***************************/
|
||||
template <typename Value>
|
||||
Value {{name}}::parse() {
|
||||
//TODO
|
||||
std::stack<Token> valueStack;
|
||||
std::stack<std::uint64_t> stateStack;
|
||||
|
||||
stateStack.push(0);
|
||||
Token tok = lex();
|
||||
|
||||
while (true) {
|
||||
std::uint64_t act = TABLE[stateStack.top()][tok.symbol];
|
||||
|
||||
switch (act & 0x3) {
|
||||
case ERROR:
|
||||
//TODO: error handling
|
||||
assert(false);
|
||||
break;
|
||||
case SHIFT:
|
||||
valueStack.emplace(std::move(tok));
|
||||
stateStack.push(act >> 2);
|
||||
tok = lex();
|
||||
break;
|
||||
case REDUCE:
|
||||
{
|
||||
std::uint64_t rule = act >> 2;
|
||||
std::deque<Token> dq;
|
||||
for (decltype(RECUDE_COUNT[rule]) i = 0; i < REDUCE_COUNT[rule]; i++) {
|
||||
dq.emplace_front(std::move(valueStack.top()));
|
||||
valueStack.pop();
|
||||
stateStack.pop();
|
||||
}
|
||||
|
||||
switch (rule) {
|
||||
{{#rules}}
|
||||
case {{index}}:
|
||||
{{#name}}valueStack.emplace(reduce_{{name}}(std::move(dq))){{/name}}
|
||||
{{^name}}valueStack.emplace(reduce{{index}}(std::move(dq))){{/name}}
|
||||
break;
|
||||
{{/rules}}
|
||||
default:
|
||||
assert(false); //There should be no such rule
|
||||
break;
|
||||
}
|
||||
|
||||
stateStack.push(TABLE[stateStack.top()][valueStack.top().symbol] >> 2);
|
||||
}
|
||||
break;
|
||||
case ACCEPT:
|
||||
assert(stateStack.size() == 2);
|
||||
assert(valueStack.size() == 1);
|
||||
return valueStack.top().value;
|
||||
default:
|
||||
//IMPOSSIBLE
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef REDUCE_COUNT
|
||||
#undef TABLE
|
||||
|
||||
#endif /* PARSODUS_PARSER_{{name}}_H */
|
||||
|
|
Loading…
Reference in New Issue