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

The TextParserRule holds the basic elment of the syntax description. Each rule has a name and a set of patterns. The parser uses these rules to parse the input files. The first token of a pattern must resolve to a terminal token. The resolution can run transitively over a set of rules. The first tokens of each pattern of a rule must resolve to a terminal symbol and all terminals must be unique in the scope that they appear in. The parser uses this first token to select the next pattern it uses for the syntactical analysis. A rule can be marked as repeatable and/or optional. In this case the syntax element described by the rule may occur 0 or multiple times in the parsed file.

Methods

Attributes

doc  [R] 
keyword  [R] 
name  [R] 
optional  [R] 
patterns  [R] 
repeatable  [R] 

Public Class methods

Create a new syntax rule called name.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 33
    def initialize(name)
      @name = name
      @patterns = []
      @repeatable = false
      @optional = false
      @keyword = nil

      flushCache
    end

Public Instance methods

Add a new pattern to the Rule. It should be of type TextParser::Pattern.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 52
    def addPattern(pattern)
      @patterns << pattern
    end

Return a Hash of all state transitions caused by the 1st token of each pattern of this rule.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 95
    def addTransitionsToState(states, rules, stateStack, sourceState,
                              loopBack)
      @patterns.each do |pattern|
        pattern.addTransitionsToState(states, rules, stateStack.dup,
                                      sourceState, self, 0, loopBack)
      end
    end

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 177
    def dump
      puts "Rule: #{name} #{@optional ? "[optional]" : ""} " +
           "#{@repeatable ? "[repeatable]" : ""}"
      @patterns.length.times do |i|
        puts "  Pattern: \"#{@patterns[i]}\""
        unless @transitions[i]
          puts "No transitions for this pattern!"
          next
        end

        @transitions[i].each do |key, rule|
          if key[0] == ?_
            token = "\"" + key.slice(1, key.length - 1) + "\""
          else
            token = key.slice(1, key.length - 1)
          end
          puts "    #{token} -> #{rule.name}"
        end
      end
      puts
    end

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 43
    def flushCache
      # A rule is considered to describe optional tokens in case the @optional
      # flag is set or all of the patterns reference optional rules again.
      # This variable caches the transitively determined optional value.
      @transitiveOptional = nil
    end

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 81
    def generateStates(rules)
      # First, add an entry State for this rule. Entry states are never
      # reached by normal state transitions. They are only used as (re-)start
      # states.
      states = [ State.new(self) ]

      @patterns.each do |pattern|
        states += pattern.generateStates(self, rules)
      end
      states
    end

Return true if the rule describes optional elements. The evaluation recursively descends into the pattern if necessary and stores the result to be reused for later calls.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 64
    def optional?(rules)
      # If we have a cached result, use this.
      return @transitiveOptional if @transitiveOptional

      # If the rule is marked optional, then it is optional.
      if @optional
        return @transitiveOptional = true
      end

      # If all patterns describe optional content, then this rule is optional
      # as well.
      @transitiveOptional = true
      @patterns.each do |pat|
        return @transitiveOptional = false unless pat.optional?(rules)
      end
    end

Return a reference the pattern of this Rule.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 151
    def pattern(idx)
      @patterns[idx]
    end

Add a description for a pattern element of the last added pattern.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 119
    def setArg(idx, doc)
      raise 'No pattern defined yet' if @patterns.empty?
      @patterns[-1].setArg(idx, doc)
    end

Add a description for the syntax elements of this Rule. doc is a RichText and keyword is a unique name of this Rule. To avoid ambiguouties, an optional scope can be appended, separated by a dot (E.g. name.scope).

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 113
    def setDoc(keyword, doc)
      raise 'No pattern defined yet' if @patterns.empty?
      @patterns[-1].setDoc(keyword, doc)
    end

Add a reference to a code example. file is the name of the file. tag is a tag within the file that specifies a part of this file.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 146
    def setExample(file, tag)
      @patterns[-1].setExample(file, tag)
    end

Specify the index idx of the last token to be used for the syntax documentation. All subsequent tokens will be ignored.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 126
    def setLastSyntaxToken(idx)
      raise 'No pattern defined yet' if @patterns.empty?
      raise 'Token index too large' if idx >= @patterns[-1].tokens.length
      @patterns[-1].setLastSyntaxToken(idx)
    end

Mark the rule as an optional element of the syntax.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 57
    def setOptional
      @optional = true
    end

Mark the syntax element described by this Rule as a repeatable element that can occur once or more times in sequence.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 105
    def setRepeatable
      @repeatable = true
    end

Add a reference to another rule for documentation purposes.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 139
    def setSeeAlso(also)
      raise 'No pattern defined yet' if @patterns.empty?
      @patterns[-1].setSeeAlso(also)
    end

Specify the support level of the current pattern.

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 133
    def setSupportLevel(level)
      raise 'No pattern defined yet' if @patterns.empty?
      @patterns[-1].setSupportLevel(level)
    end

[Source]

# File lib/taskjuggler/TextParser/Rule.rb, line 155
    def to_syntax(stack, docs, rules, skip)
      str = ''
      str << '[' if @optional || @repeatable
      str << '(' if @patterns.length > 1
      first = true
      pStr = ''
      @patterns.each do |pat|
        if first
          first = false
        else
          pStr << ' | '
        end
        pStr << pat.to_syntax_r(stack, docs, rules, skip)
      end
      return '' if pStr == ''
      str << pStr
      str << '...' if @repeatable
      str << ')' if @patterns.length > 1
      str << ']' if @optional || @repeatable
      str
    end

[Validate]