Add new start rule ending with EOF token rather than appending EOF token to all user-specified start rules

This commit is contained in:
Josh Holtrop 2022-06-07 22:25:31 -04:00
parent 2837dfda6b
commit d6e5c4325d
2 changed files with 12 additions and 10 deletions

View File

@ -35,7 +35,7 @@ class Propane
pattern = name
end
unless name =~ /^[a-zA-Z_][a-zA-Z_0-9]*$/
raise Error.new("Invalid token name #{name}")
raise Error.new("Invalid token name #{name.inspect}")
end
@tokens << Token.new(name: name, pattern: pattern, id: @tokens.size, line_number: line_number)
elsif sliced = input.slice!(/\Adrop\s+(\S+)\n/)
@ -43,8 +43,12 @@ class Propane
@drop_tokens << Token.new(pattern: pattern, line_number: line_number)
elsif sliced = input.slice!(/\A(\S+)\s*->\s*(.*?)(?:;|<<\n(.*?)^>>\n)/m)
rule_name, components, code = $1, $2, $3
unless rule_name =~ /^[a-zA-Z_][a-zA-Z_0-9]*$/
raise Error.new("Invalid rule name #{name.inspect}")
end
components = components.strip.split(/\s+/)
@rules << Rule.new(rule_name, components, code, line_number, @rules.size)
# Reserve rule ID 0 for the "real" start rule.
@rules << Rule.new(rule_name, components, code, line_number, @rules.size + 1)
else
if input.size > 25
input = input.slice(0..20) + "..."

View File

@ -3,15 +3,13 @@ class Propane
class Parser
def initialize(start_rule_set)
@token_eof = Token.new(name: "$", id: TOKEN_EOF)
@eof_token = Token.new(name: "$", id: TOKEN_EOF)
start_rule = Rule.new("$$", [start_rule_set, @eof_token], nil, nil, 0)
@item_sets = []
@item_sets_set = {}
start_items = start_rule_set.rules.map do |rule|
rule.components << @token_eof
Item.new(rule, 0)
end
start_item = Item.new(start_rule, 0)
eval_item_sets = Set.new
eval_item_sets << ItemSet.new(start_items)
eval_item_sets << ItemSet.new([start_item])
while eval_item_sets.size > 0
this_eval_item_sets = eval_item_sets
@ -22,7 +20,7 @@ class Propane
@item_sets << item_set
@item_sets_set[item_set] = item_set
item_set.following_symbols.each do |following_symbol|
unless following_symbol == @token_eof
unless following_symbol == @eof_token
following_set = item_set.build_following_item_set(following_symbol)
eval_item_sets << following_set
end
@ -71,7 +69,7 @@ class Propane
def process_item_set(item_set)
item_set.following_symbols.each do |following_symbol|
unless following_symbol == @token_eof
unless following_symbol == @eof_token
following_set = @item_sets_set[item_set.build_following_item_set(following_symbol)]
item_set.following_item_set[following_symbol] = following_set
following_set.in_sets << item_set