Class TaskJuggler::TextParser::State
In: lib/taskjuggler/TextParser/State.rb
Parent: Object

This State objects describes a state of the TextParser FSM. A State captures the position in the syntax description that the parser is currently at. A position is defined by the Rule, the Pattern and the index of the current token of that Pattern. An index of 0 means, we‘ve just read the 1st token of the pattern. States which have no Pattern describe the start of rule. The parser has not yet identified the first token, so it doesn‘t know the Pattern yet.

The actual data of a State is the list of possible StateTransitions to other states and a boolean flag that specifies if Reduce operations are valid for this State or not. The transitions are hashed by the token that would trigger this transition.

Methods

Attributes

index  [R] 
noReduce  [RW] 
pattern  [R] 
rule  [R] 
transitions  [R] 

Public Class methods

[Source]

# File lib/taskjuggler/TextParser/State.rb, line 85
    def initialize(rule, pattern = nil, index = 0)
      @rule = rule
      @pattern = pattern
      @index = index
      # Starting states are always reduceable. Other states may or may not be
      # reduceable. For now, we assume they are not.
      @noReduce = !pattern.nil?

      @transitions = {}
    end

Public Instance methods

This method adds the actual StateTransition to this State.

[Source]

# File lib/taskjuggler/TextParser/State.rb, line 111
    def addTransition(token, nextState, stateStack, loopBack)
      tr = StateTransition.new(token, nextState, stateStack, loopBack)
      if @transitions.include?(tr.tokenType)
        raise "Ambiguous transition for #{tr.tokenType} in \n#{self}\n" +
              "The following transition both match:\n" +
              "  #{tr}\n  #{@transitions[tr.tokenType]}"
      end
      @transitions[tr.tokenType] = tr
    end

Complete the StateTransition list. We can only call this function after all State objects for the syntax have been created. So we can‘t make this part of the constructor.

[Source]

# File lib/taskjuggler/TextParser/State.rb, line 99
    def addTransitions(states, rules)
      if @pattern
        # This is an normal state node.
        @pattern.addTransitionsToState(states, rules, [], self,
                                       @rule, @index + 1, false)
      else
        # This is a start node.
        @rule.addTransitionsToState(states, rules, [], self, false)
      end
    end

Return a comma separated list of token strings that would trigger transitions for this State.

[Source]

# File lib/taskjuggler/TextParser/State.rb, line 136
    def expectedTokens
      tokens = []
      @transitions.each_key do |t|
        tokens << "#{t.is_a?(String) ? "'#{t}'" : ":#{t}"}"
      end
      tokens
    end

Convert the State data into a human readable form. Used for debugging only.

[Source]

# File lib/taskjuggler/TextParser/State.rb, line 146
    def to_s(short = false)
      if short
        if @pattern
          str = "#{rule.name} " +
                "#{rule.patterns.index(@pattern)} #{@index}"
        else
          str = "#{rule.name} (Starting Node)"
        end
      else
        if @pattern
          str = "=== State: #{rule.name} " +
                "#{rule.patterns.index(@pattern)} #{@index}" +
                " #{@noReduce ? '' : '(R)'}" +
                " #{'=' * 40}\nPattern: #{@pattern}\n"
        else
          str = "=== State: #{rule.name} (Starting Node) #{'=' * 30}\n"
        end

        @transitions.each do |type, target|
          targetStr = target ? target.to_s : "<EOF>"
          str += "  #{type.is_a?(String) ? "'#{type}'" : ":#{type}"}" +
                 " => #{targetStr}\n"
        end
        str += "#{'=' * 76}\n"
      end
      str
    end

Find the transition that matches token.

[Source]

# File lib/taskjuggler/TextParser/State.rb, line 122
    def transition(token)
      if token[0] == :ID
        # The scanner cannot differentiate between IDs and literals that look
        # like IDs. So we look for literals first and then for IDs.
        @transitions[token[1]] || @transitions[:ID]
      elsif token[0] == :LITERAL
        @transitions[token[1]]
      else
        @transitions[token[0]]
      end
    end

[Validate]