lib/antelope/generation/constructor.rb in antelope-0.2.0 vs lib/antelope/generation/constructor.rb in antelope-0.2.2

- old
+ new

@@ -1,126 +1,126 @@ -# encoding: utf-8 - -require "set" -require "antelope/generation/constructor/nullable" -require "antelope/generation/constructor/first" -require "antelope/generation/constructor/follow" - -module Antelope - module Generation - - # Constructs the lookahead sets for all of the rules in the - # grammar. - class Constructor - - include Nullable - include First - include Follow - - # The grammar. - # - # @return [Ace::Grammar] - attr_reader :grammar - - # The augmented productions generated by the constructor. - # - # @return [Set<Ace::Production>] - attr_reader :productions - - # Initialize. - # - # @param grammar [Ace::Grammar] the grammar. - def initialize(grammar) - @productions = Set.new - @grammar = grammar - super() - end - - # Performs the construction. First, it goes through every state - # and augments the state. It then goes through every rule and - # augments it. - # - # @return [void] - # @see #augment_state - # @see #augment_rule - def call - grammar.states.each do |state| - augment_state(state) - end.each do |state| - augment_rules(state) - end - end - - # Augments the given state. On every rule within that state - # that has a position of zero, it follows the rule throughout - # the DFA until the end; it marks every nonterminal it - # encounters with the transitions it took on that nonterminal. - # - # @param state [Recognizer::State] the state to augment. - # @return [void] - def augment_state(state) - state.rules.select { |x| x.position.zero? }.each do |rule| - production = rule.production.clone - production.items = [] - - current_state = state - old_state = state - - production.label.from = state - production.label.to = state.transitions[rule.left.name] - - rule.right.each_with_index do |part, pos| - transition = current_state.transitions[part.name] - new_item = part.dup - - if part.nonterminal? - new_item.from = current_state - new_item.to = transition - end - - production.items << new_item - - old_state = current_state - current_state = transition - end - - productions << production - end - end - - # Augments every final rule. For every rule in the current - # state that has a position of zero, it follows the rule through - # the DFA until the ending state; it then modifies the ending - # state's lookahead set to be the FOLLOW set of the nonterminal - # it reduces to. - # - # @param state [Recognizer::State] - # @return [void] - # @see Follow#follow - def augment_rules(state) - state.rules.select { |x| x.position.zero? }.each do |rule| - current_state = state - - label = rule.left.dup - label.from = state - label.to = state.transitions[label.name] - - rule.right.each do |part| - transition = current_state.transitions[part.name] - current_state = transition - end - - final = current_state.rule_for(rule) - - final.lookahead = Set.new unless final.lookahead - final.lookahead.merge follow(label) - end - end - - private - - def incorrect_argument!(arg, *types) - raise ArgumentError, "Expected one of #{types.join(", ")}, got #{arg.class}" - end - end - end -end +# encoding: utf-8 + +require "set" +require "antelope/generation/constructor/nullable" +require "antelope/generation/constructor/first" +require "antelope/generation/constructor/follow" + +module Antelope + module Generation + + # Constructs the lookahead sets for all of the rules in the + # grammar. + class Constructor + + include Nullable + include First + include Follow + + # The grammar. + # + # @return [Ace::Grammar] + attr_reader :grammar + + # The augmented productions generated by the constructor. + # + # @return [Set<Ace::Production>] + attr_reader :productions + + # Initialize. + # + # @param grammar [Ace::Grammar] the grammar. + def initialize(grammar) + @productions = Set.new + @grammar = grammar + super() + end + + # Performs the construction. First, it goes through every state + # and augments the state. It then goes through every rule and + # augments it. + # + # @return [void] + # @see #augment_state + # @see #augment_rule + def call + grammar.states.each do |state| + augment_state(state) + end.each do |state| + augment_rules(state) + end + end + + # Augments the given state. On every rule within that state + # that has a position of zero, it follows the rule throughout + # the DFA until the end; it marks every nonterminal it + # encounters with the transitions it took on that nonterminal. + # + # @param state [Recognizer::State] the state to augment. + # @return [void] + def augment_state(state) + state.rules.select { |x| x.position.zero? }.each do |rule| + production = rule.production.clone + production.items = [] + + current_state = state + old_state = state + + production.label.from = state + production.label.to = state.transitions[rule.left.name] + + rule.right.each_with_index do |part, pos| + transition = current_state.transitions[part.name] + new_item = part.dup + + if part.nonterminal? + new_item.from = current_state + new_item.to = transition + end + + production.items << new_item + + old_state = current_state + current_state = transition + end + + productions << production + end + end + + # Augments every final rule. For every rule in the current + # state that has a position of zero, it follows the rule through + # the DFA until the ending state; it then modifies the ending + # state's lookahead set to be the FOLLOW set of the nonterminal + # it reduces to. + # + # @param state [Recognizer::State] + # @return [void] + # @see Follow#follow + def augment_rules(state) + state.rules.select { |x| x.position.zero? }.each do |rule| + current_state = state + + label = rule.left.dup + label.from = state + label.to = state.transitions[label.name] + + rule.right.each do |part| + transition = current_state.transitions[part.name] + current_state = transition + end + + final = current_state.rule_for(rule) + + final.lookahead = Set.new unless final.lookahead + final.lookahead.merge follow(label) + end + end + + private + + def incorrect_argument!(arg, *types) + raise ArgumentError, "Expected one of #{types.join(", ")}, got #{arg.class}" + end + end + end +end