Handle shifting states after reducing
This commit is contained in:
parent
84c4a16ce6
commit
f2cc5b112e
@ -2,6 +2,9 @@
|
|||||||
module <%= @grammar.modulename %>;
|
module <%= @grammar.modulename %>;
|
||||||
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
class <%= @classname %>
|
class <%= @classname %>
|
||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
@ -16,7 +19,7 @@ class <%= @classname %>
|
|||||||
_TOKEN_NONE = <%= TOKEN_NONE %>,
|
_TOKEN_NONE = <%= TOKEN_NONE %>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static immutable string TokenNames[] = [
|
static immutable string token_names[] = [
|
||||||
<% @grammar.tokens.each_with_index do |token, index| %>
|
<% @grammar.tokens.each_with_index do |token, index| %>
|
||||||
"<%= token.name %>",
|
"<%= token.name %>",
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -303,7 +306,7 @@ class <%= @classname %>
|
|||||||
m_lexer = new Lexer(input, input_length);
|
m_lexer = new Lexer(input, input_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse()
|
bool parse()
|
||||||
{
|
{
|
||||||
Lexer.LexedToken lexed_token;
|
Lexer.LexedToken lexed_token;
|
||||||
uint token = _TOKEN_NONE;
|
uint token = _TOKEN_NONE;
|
||||||
@ -331,7 +334,7 @@ class <%= @classname %>
|
|||||||
if (token == _TOKEN_EOF)
|
if (token == _TOKEN_EOF)
|
||||||
{
|
{
|
||||||
/* Successful parse. */
|
/* Successful parse. */
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
states ~= shift_state;
|
states ~= shift_state;
|
||||||
token = _TOKEN_NONE;
|
token = _TOKEN_NONE;
|
||||||
@ -347,18 +350,39 @@ class <%= @classname %>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Error, unexpected token. */
|
/* Error, unexpected token. */
|
||||||
return;
|
write("Unexpected token ");
|
||||||
|
if (token == _TOKEN_EOF)
|
||||||
|
{
|
||||||
|
writeln("{EOF}");
|
||||||
|
}
|
||||||
|
else if (token < _TOKEN_COUNT)
|
||||||
|
{
|
||||||
|
writeln(token_names[token]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeln("{other}");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint check_shift(uint state, uint token)
|
private uint check_shift(uint state, uint symbol)
|
||||||
{
|
{
|
||||||
uint start = states[state].shift_table_index;
|
uint start = states[state].shift_table_index;
|
||||||
uint end = start + states[state].n_shift_entries;
|
uint end = start + states[state].n_shift_entries;
|
||||||
for (uint i = start; i < end; i++)
|
for (uint i = start; i < end; i++)
|
||||||
{
|
{
|
||||||
if (shifts[i].symbol == token)
|
if (shifts[i].symbol == symbol)
|
||||||
{
|
{
|
||||||
|
if (symbol < _TOKEN_COUNT)
|
||||||
|
{
|
||||||
|
writeln("Shifting ", token_names[symbol]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeln("Shifting rule set ", symbol);
|
||||||
|
}
|
||||||
return shifts[i].state;
|
return shifts[i].state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,6 +398,7 @@ class <%= @classname %>
|
|||||||
if ((reduces[i].token == token) ||
|
if ((reduces[i].token == token) ||
|
||||||
(reduces[i].token == _TOKEN_NONE))
|
(reduces[i].token == _TOKEN_NONE))
|
||||||
{
|
{
|
||||||
|
writeln("Reducing rule ", reduces[i].rule, ", rule set ", reduces[i].rule_set);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,7 @@ class Propane
|
|||||||
state_table = []
|
state_table = []
|
||||||
reduce_table = []
|
reduce_table = []
|
||||||
@item_sets.each do |item_set|
|
@item_sets.each do |item_set|
|
||||||
shift_entries = item_set.following_symbols.select do |following_symbol|
|
shift_entries = item_set.following_symbols.map do |following_symbol|
|
||||||
following_symbol.is_a?(Token)
|
|
||||||
end.map do |following_symbol|
|
|
||||||
state_id =
|
state_id =
|
||||||
if following_symbol == @eof_token
|
if following_symbol == @eof_token
|
||||||
0
|
0
|
||||||
|
@ -74,10 +74,13 @@ EOF
|
|||||||
write_grammar <<EOF
|
write_grammar <<EOF
|
||||||
token a
|
token a
|
||||||
token b
|
token b
|
||||||
|
drop \\s+
|
||||||
Start -> a R1;
|
Start -> a R1;
|
||||||
Start -> b R1;
|
Start -> b R1;
|
||||||
R1 -> b;
|
R1 -> b;
|
||||||
EOF
|
EOF
|
||||||
build_parser
|
build_parser
|
||||||
|
compile("spec/test_d_lexer2.d")
|
||||||
|
run
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
22
spec/test_d_lexer2.d
Normal file
22
spec/test_d_lexer2.d
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import testparser;
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
string input = "a";
|
||||||
|
auto parser = new Testparser.Parser(cast(const(ubyte) *)input.ptr, input.length);
|
||||||
|
assert(parser.parse() == false);
|
||||||
|
|
||||||
|
input = "a b";
|
||||||
|
parser = new Testparser.Parser(cast(const(ubyte) *)input.ptr, input.length);
|
||||||
|
assert(parser.parse() == true);
|
||||||
|
|
||||||
|
input = "bb";
|
||||||
|
parser = new Testparser.Parser(cast(const(ubyte) *)input.ptr, input.length);
|
||||||
|
assert(parser.parse() == true);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user