Class: TaskJuggler::TextParser::Rule

Inherits:
Object
  • Object
show all
Defined in:
lib/taskjuggler/TextParser/Rule.rb

Overview

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.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Rule

Create a new syntax rule called name.



33
34
35
36
37
38
39
40
41
# File 'lib/taskjuggler/TextParser/Rule.rb', line 33

def initialize(name)
  @name = name
  @patterns = []
  @repeatable = false
  @optional = false
  @keyword = nil

  flushCache
end

Instance Attribute Details

#docObject (readonly)

Returns the value of attribute doc.



30
31
32
# File 'lib/taskjuggler/TextParser/Rule.rb', line 30

def doc
  @doc
end

#keywordObject (readonly)

Returns the value of attribute keyword.



30
31
32
# File 'lib/taskjuggler/TextParser/Rule.rb', line 30

def keyword
  @keyword
end

#nameObject (readonly)

Returns the value of attribute name.



30
31
32
# File 'lib/taskjuggler/TextParser/Rule.rb', line 30

def name
  @name
end

#optionalObject (readonly)

Returns the value of attribute optional.



30
31
32
# File 'lib/taskjuggler/TextParser/Rule.rb', line 30

def optional
  @optional
end

#patternsObject (readonly)

Returns the value of attribute patterns.



30
31
32
# File 'lib/taskjuggler/TextParser/Rule.rb', line 30

def patterns
  @patterns
end

#repeatableObject (readonly)

Returns the value of attribute repeatable.



30
31
32
# File 'lib/taskjuggler/TextParser/Rule.rb', line 30

def repeatable
  @repeatable
end

Instance Method Details

#addPattern(pattern) ⇒ Object

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



52
53
54
# File 'lib/taskjuggler/TextParser/Rule.rb', line 52

def addPattern(pattern)
  @patterns << pattern
end

#addTransitionsToState(states, rules, stateStack, sourceState, loopBack) ⇒ Object

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



100
101
102
103
104
105
106
# 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

#dumpObject



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# 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

#flushCacheObject



43
44
45
46
47
48
# 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) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
# 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) ⇒ Boolean

Returns:

  • (Boolean)


56
57
58
59
# 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) ⇒ Boolean

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.

Returns:

  • (Boolean)


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 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) ⇒ Object

Return a reference the pattern of this Rule.



156
157
158
# File 'lib/taskjuggler/TextParser/Rule.rb', line 156

def pattern(idx)
  @patterns[idx]
end

#setArg(idx, doc) ⇒ Object

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



124
125
126
127
# 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) ⇒ Object

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



118
119
120
121
# 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) ⇒ Object

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.



151
152
153
# File 'lib/taskjuggler/TextParser/Rule.rb', line 151

def setExample(file, tag)
  @patterns[-1].setExample(file, tag)
end

#setLastSyntaxToken(idx) ⇒ Object

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



131
132
133
134
135
# 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

#setOptionalObject

Mark the rule as an optional element of the syntax.



62
63
64
# File 'lib/taskjuggler/TextParser/Rule.rb', line 62

def setOptional
  @optional = true
end

#setRepeatableObject

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



110
111
112
# File 'lib/taskjuggler/TextParser/Rule.rb', line 110

def setRepeatable
  @repeatable = true
end

#setSeeAlso(also) ⇒ Object

Add a reference to another rule for documentation purposes.



144
145
146
147
# 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) ⇒ Object

Specify the support level of the current pattern.



138
139
140
141
# 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) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# 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