class RLTK::Parser::ParseStack::State
The State
class is used to represent sets of items and actions to be used during parsing.
Attributes
@return [Hash{Symbol => Array<Action>}] Maps lookahead symbols to actions
@return [Integer] State’s ID.
@return [Array<CFG::Item>] Item objects that comprise this state
Public Class Methods
Instantiate a new State
object.
@param [Array<Symbol>] tokens Tokens that represent this state @param [Array<CFG::Item>] items Items that make up this state
# File lib/rltk/parser.rb, line 1487 def initialize(tokens, items = []) @id = nil @items = items @actions = tokens.inject(Hash.new) { |h, t| h[t] = Array.new; h } end
Public Instance Methods
Compare one State
to another. Two States are equal if they have the same items or, if the items have been cleaned, if the States have the same ID.
@param [State] other Another State
to compare to
@return [Boolean]
# File lib/rltk/parser.rb, line 1500 def ==(other) if self.items and other.items then self.items == other.items else self.id == other.id end end
Add a Reduce
action to the state.
@param [Production] production Production used to perform the reduction
@return [void]
# File lib/rltk/parser.rb, line 1509 def add_reduction(production) action = Reduce.new(production) # Reduce actions are not allowed for the ERROR terminal. @actions.each { |k, v| if CFG::is_terminal?(k) and k != :ERROR then v << action end } end
@param [CFG::Item] item Item to add to this state.
# File lib/rltk/parser.rb, line 1517 def append(item) if item.is_a?(CFG::Item) and not @items.include?(item) then @items << item end end
Clean this State
by removing the list of {CFG::Item} objects.
@return [void]
# File lib/rltk/parser.rb, line 1525 def clean @items = nil end
Close this state using productions.
@param [Array<CFG::Production>] productions Productions used to close this state.
@return [vod]
# File lib/rltk/parser.rb, line 1534 def close(productions) self.each do |item| if (next_symbol = item.next_symbol) and CFG::is_nonterminal?(next_symbol) productions[next_symbol].each { |p| self << p.to_item } end end end
Checks to see if there is a conflict in this state, given a input of sym. Returns :SR if a shift/reduce conflict is detected and :RR if a reduce/reduce conflict is detected. If no conflict is detected nil is returned.
@param [Symbol] sym Symbol to check for conflicts on.
@return [:SR, :RR, nil]
# File lib/rltk/parser.rb, line 1550 def conflict_on?(sym) reductions = 0 shifts = 0 @actions[sym].each do |action| if action.is_a?(Reduce) reductions += 1 elsif action.is_a?(Shift) shifts += 1 end end if shifts == 1 and reductions > 0 :SR elsif reductions > 1 :RR else nil end end
Iterate over the state’s items.
@return [void]
# File lib/rltk/parser.rb, line 1577 def each current_item = 0 while current_item < @items.count yield @items.at(current_item) current_item += 1 end end
Specify an Action
to perform when the input token is symbol.
@param [Symbol] symbol Symbol to add action for. @param [Action] action Action
for symbol.
@return [void]
# File lib/rltk/parser.rb, line 1591 def on(symbol, action) if @actions.key?(symbol) @actions[symbol] << action else raise ParserConstructionException, "Attempting to set action for token (#{symbol}) not seen in grammar definition." end end
Returns that actions that should be taken when the input token is symbol.
@param [Symbol] symbol Symbol we want the actions for.
@return [Array<Action>] Actions that should be taken.
# File lib/rltk/parser.rb, line 1605 def on?(symbol) @actions[symbol].clone end