Always compute lookahead tokens for reduce rules
Even if they won't be needed for the generated parser, they'll be useful to detect shift/reduce conflicts.
This commit is contained in:
parent
7f3eb8f315
commit
69cc8fa67d
@ -62,13 +62,12 @@ class Propane
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
reduce_entries =
|
reduce_entries =
|
||||||
case ra = item_set.reduce_actions
|
if rule = item_set.reduce_rule
|
||||||
when Rule
|
[{token_id: @grammar.invalid_token_id, rule_id: rule.id, rule: rule,
|
||||||
[{token_id: @grammar.invalid_token_id, rule_id: ra.id, rule: ra,
|
rule_set_id: rule.rule_set.id, n_states: rule.components.size,
|
||||||
rule_set_id: ra.rule_set.id, n_states: ra.components.size,
|
propagate_optional_target: rule.optional? && rule.components.size == 1}]
|
||||||
propagate_optional_target: ra.optional? && ra.components.size == 1}]
|
elsif reduce_actions = item_set.reduce_actions
|
||||||
when Hash
|
reduce_actions.map do |token, rule|
|
||||||
ra.map do |token, rule|
|
|
||||||
{token_id: token.id, rule_id: rule.id, rule: rule,
|
{token_id: token.id, rule_id: rule.id, rule: rule,
|
||||||
rule_set_id: rule.rule_set.id, n_states: rule.components.size,
|
rule_set_id: rule.rule_set.id, n_states: rule.components.size,
|
||||||
propagate_optional_target: rule.optional? && rule.components.size == 1}
|
propagate_optional_target: rule.optional? && rule.components.size == 1}
|
||||||
@ -111,10 +110,8 @@ class Propane
|
|||||||
# @param item_set [ItemSet]
|
# @param item_set [ItemSet]
|
||||||
# ItemSet (parser state)
|
# ItemSet (parser state)
|
||||||
#
|
#
|
||||||
# @return [nil, Rule, Hash]
|
# @return [nil, Hash]
|
||||||
# If no reduce actions are possible for the given item set, nil.
|
# If no reduce actions are possible for the given item set, nil.
|
||||||
# If only one reduce action is possible for the given item set, the Rule
|
|
||||||
# to reduce.
|
|
||||||
# Otherwise, a mapping of lookahead Tokens to the Rules to reduce.
|
# Otherwise, a mapping of lookahead Tokens to the Rules to reduce.
|
||||||
def build_reduce_actions_for_item_set(item_set)
|
def build_reduce_actions_for_item_set(item_set)
|
||||||
# To build the reduce actions, we start by looking at any
|
# To build the reduce actions, we start by looking at any
|
||||||
@ -123,15 +120,15 @@ class Propane
|
|||||||
# reduction in the current ItemSet.
|
# reduction in the current ItemSet.
|
||||||
reduce_rules = Set.new(item_set.items.select(&:complete?).map(&:rule))
|
reduce_rules = Set.new(item_set.items.select(&:complete?).map(&:rule))
|
||||||
|
|
||||||
# If there are no rules to reduce for this ItemSet, we're done here.
|
if reduce_rules.size == 1
|
||||||
return nil if reduce_rules.size == 0
|
item_set.reduce_rule = reduce_rules.first
|
||||||
|
end
|
||||||
|
|
||||||
# If there is exactly one rule to reduce for this ItemSet, then do not
|
if reduce_rules.size == 0
|
||||||
# figure out the lookaheads; just reduce it.
|
nil
|
||||||
return reduce_rules.first if reduce_rules.size == 1
|
else
|
||||||
|
build_lookahead_reduce_actions_for_item_set(item_set)
|
||||||
# Otherwise, we have more than one possible rule to reduce.
|
end
|
||||||
build_lookahead_reduce_actions_for_item_set(item_set)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Build the reduce actions for a single item set (parser state).
|
# Build the reduce actions for a single item set (parser state).
|
||||||
@ -305,10 +302,9 @@ class Propane
|
|||||||
end
|
end
|
||||||
@log.puts
|
@log.puts
|
||||||
@log.puts " Reduce actions:"
|
@log.puts " Reduce actions:"
|
||||||
case item_set.reduce_actions
|
if item_set.reduce_rule
|
||||||
when Rule
|
@log.puts " * => rule #{item_set.reduce_rule.id}, rule set #{@rule_sets[item_set.reduce_rule.name].id} (#{item_set.reduce_rule.name})"
|
||||||
@log.puts " * => rule #{item_set.reduce_actions.id}, rule set #{@rule_sets[item_set.reduce_actions.name].id} (#{item_set.reduce_actions.name})"
|
elsif item_set.reduce_actions
|
||||||
when Hash
|
|
||||||
item_set.reduce_actions.each do |token, rule|
|
item_set.reduce_actions.each do |token, rule|
|
||||||
@log.puts " lookahead #{token.name} => #{rule.name} (#{rule.id}), rule set ##{rule.rule_set.id}"
|
@log.puts " lookahead #{token.name} => #{rule.name} (#{rule.id}), rule set ##{rule.rule_set.id}"
|
||||||
end
|
end
|
||||||
|
@ -21,8 +21,13 @@ class Propane
|
|||||||
# ItemSets leading to this item set.
|
# ItemSets leading to this item set.
|
||||||
attr_reader :in_sets
|
attr_reader :in_sets
|
||||||
|
|
||||||
# @return [nil, Rule, Hash]
|
# @return [nil, Rule]
|
||||||
# Reduce actions, mapping lookahead tokens to rules.
|
# Rule to reduce if there is only one possibility.
|
||||||
|
attr_accessor :reduce_rule
|
||||||
|
|
||||||
|
# @return [nil, Hash]
|
||||||
|
# Reduce actions, mapping lookahead tokens to rules, if there is
|
||||||
|
# more than one rule that could be reduced.
|
||||||
attr_accessor :reduce_actions
|
attr_accessor :reduce_actions
|
||||||
|
|
||||||
# @return [Set<Token>]
|
# @return [Set<Token>]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user