class TaskJuggler::TextParser::Rule

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.

Attributes

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

Public Class Methods

new(name) click to toggle source

Create a new syntax rule called name.

# 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

addPattern(pattern) click to toggle source

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

# File lib/taskjuggler/TextParser/Rule.rb, line 52
def addPattern(pattern)
  @patterns << pattern
end
addTransitionsToState(states, rules, stateStack, sourceState, loopBack) click to toggle source

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

# File lib/taskjuggler/TextParser/Rule.rb, line 100
def addTransitionsToState(states, rules, stateStack, sourceState,
                          loopBack)
  @patterns.each do |pattern|
    pattern.addTransitionsToState(states, rules, stateStack.dup,
                                  sourceState, self, 0, loopBack)
  end
end
dump() click to toggle source
# File lib/taskjuggler/TextParser/Rule.rb, line 182
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
flushCache() click to toggle 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
generateStates(rules) click to toggle source
# File lib/taskjuggler/TextParser/Rule.rb, line 86
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
include?(token) click to toggle source
# File lib/taskjuggler/TextParser/Rule.rb, line 56
def include?(token)
  @patterns.each { |p| return true if p[0][1] == token }
  false
end
optional?(rules) click to toggle source

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.

# File lib/taskjuggler/TextParser/Rule.rb, line 69
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
pattern(idx) click to toggle source

Return a reference the pattern of this Rule.

# File lib/taskjuggler/TextParser/Rule.rb, line 156
def pattern(idx)
  @patterns[idx]
end
setArg(idx, doc) click to toggle source

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

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

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).

# File lib/taskjuggler/TextParser/Rule.rb, line 118
def setDoc(keyword, doc)
  raise 'No pattern defined yet' if @patterns.empty?
  @patterns[-1].setDoc(keyword, doc)
end
setExample(file, tag) click to toggle source

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.

# File lib/taskjuggler/TextParser/Rule.rb, line 151
def setExample(file, tag)
  @patterns[-1].setExample(file, tag)
end
setLastSyntaxToken(idx) click to toggle source

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

# File lib/taskjuggler/TextParser/Rule.rb, line 131
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
setOptional() click to toggle source

Mark the rule as an optional element of the syntax.

# File lib/taskjuggler/TextParser/Rule.rb, line 62
def setOptional
  @optional = true
end
setRepeatable() click to toggle source

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

# File lib/taskjuggler/TextParser/Rule.rb, line 110
def setRepeatable
  @repeatable = true
end
setSeeAlso(also) click to toggle source

Add a reference to another rule for documentation purposes.

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

Specify the support level of the current pattern.

# File lib/taskjuggler/TextParser/Rule.rb, line 138
def setSupportLevel(level)
  raise 'No pattern defined yet' if @patterns.empty?
  @patterns[-1].setSupportLevel(level)
end
to_syntax(stack, docs, rules, skip) click to toggle source
# File lib/taskjuggler/TextParser/Rule.rb, line 160
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