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 32
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 51
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 99
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 181
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 42
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 85
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 55
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 68
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 155
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 123
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 117
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 150
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 130
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 61
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 109
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 143
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 137
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 159
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