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.



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

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.



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

def doc
  @doc
end

#keywordObject (readonly)

Returns the value of attribute keyword.



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

def keyword
  @keyword
end

#nameObject (readonly)

Returns the value of attribute name.



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

def name
  @name
end

#optionalObject (readonly)

Returns the value of attribute optional.



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

def optional
  @optional
end

#patternsObject (readonly)

Returns the value of attribute patterns.



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

def patterns
  @patterns
end

#repeatableObject (readonly)

Returns the value of attribute repeatable.



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

def repeatable
  @repeatable
end

Instance Method Details

#addPattern(pattern) ⇒ Object

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



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

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.



101
102
103
104
105
106
107
# File 'lib/taskjuggler/TextParser/Rule.rb', line 101

def addTransitionsToState(states, rules, stateStack, sourceState,
                          loopBack)
  @patterns.each do |pattern|
    pattern.addTransitionsToState(states, rules, stateStack.dup,
                                  sourceState, self, 0, loopBack)
  end
end

#dumpObject



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/taskjuggler/TextParser/Rule.rb', line 183

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



44
45
46
47
48
49
# File 'lib/taskjuggler/TextParser/Rule.rb', line 44

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



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/taskjuggler/TextParser/Rule.rb', line 87

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)


57
58
59
60
# File 'lib/taskjuggler/TextParser/Rule.rb', line 57

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)


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/taskjuggler/TextParser/Rule.rb', line 70

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.



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

def pattern(idx)
  @patterns[idx]
end

#setArg(idx, doc) ⇒ Object

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



125
126
127
128
# File 'lib/taskjuggler/TextParser/Rule.rb', line 125

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



119
120
121
122
# File 'lib/taskjuggler/TextParser/Rule.rb', line 119

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.



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

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.



132
133
134
135
136
# File 'lib/taskjuggler/TextParser/Rule.rb', line 132

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.



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

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.



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

def setRepeatable
  @repeatable = true
end

#setSeeAlso(also) ⇒ Object

Add a reference to another rule for documentation purposes.



145
146
147
148
# File 'lib/taskjuggler/TextParser/Rule.rb', line 145

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.



139
140
141
142
# File 'lib/taskjuggler/TextParser/Rule.rb', line 139

def setSupportLevel(level)
  raise 'No pattern defined yet' if @patterns.empty?
  @patterns[-1].setSupportLevel(level)
end

#to_syntax(stack, docs, rules, skip) ⇒ Object



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/taskjuggler/TextParser/Rule.rb', line 161

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