Class: TaskJuggler::TextParser
- Includes:
- MessageHandler
- Defined in:
- lib/taskjuggler/TextParser.rb,
lib/taskjuggler/TextParser/Rule.rb,
lib/taskjuggler/TextParser/State.rb,
lib/taskjuggler/TextParser/Pattern.rb,
lib/taskjuggler/TextParser/Scanner.rb,
lib/taskjuggler/TextParser/TokenDoc.rb,
lib/taskjuggler/TextParser/MacroTable.rb,
lib/taskjuggler/TextParser/StackElement.rb,
lib/taskjuggler/TextParser/SourceFileInfo.rb
Overview
StackElement.rb – The TaskJuggler III Project Management Software
Copyright © 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
by Chris Schlaeger <[email protected]>
This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation.
Direct Known Subclasses
Defined Under Namespace
Classes: Macro, MacroTable, Pattern, Rule, Scanner, SourceFileInfo, StackElement, State, StateTransition, TextParserResultArray, TokenDoc
Instance Attribute Summary collapse
-
#rules ⇒ Object
readonly
Returns the value of attribute rules.
Instance Method Summary collapse
- #error(id, text, sfi = nil, data = nil) ⇒ Object
-
#initialize ⇒ TextParser
constructor
Create a new TextParser object.
-
#initRules ⇒ Object
Call all methods that start with ‘rule_’ to initialize the rules.
-
#limitTokenSet(tokenSet) ⇒ Object
Limit the allowed tokens of the scanner to the subset passed by the tokenSet Array.
-
#newRule(name) ⇒ Object
Add a new rule to the rule set.
-
#optional ⇒ Object
Identify the patterns of the most recently added rule as optional syntax elements.
-
#parse(ruleName) ⇒ Object
To parse the input this function needs to be called with the name of the rule to start with.
-
#pattern(tokens, func = nil) ⇒ Object
Add a new pattern to the most recently added rule.
-
#repeatable ⇒ Object
Identify the patterns of the most recently added rule as repeatable syntax elements.
-
#sourceFileInfo ⇒ Object
Return the SourceFileInfo of the TextScanner at the beginning of the currently processed TextParser::Rule.
-
#updateParserTables ⇒ Object
This function needs to be called whenever new rules or patterns have been added and before the next call to TextParser#parse.
- #warning(id, text, sfi = nil, data = nil) ⇒ Object
Methods included from MessageHandler
#critical, #debug, #fatal, #info
Constructor Details
#initialize ⇒ TextParser
Create a new TextParser object.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/taskjuggler/TextParser.rb', line 81 def initialize # This Hash will store the ruleset that the parser is operating on. @rules = { } # Array to hold the token types that the scanner can return. @variables = [] # An list of token types that are not allowed in the current context. # For performance reasons we use a hash with the token as key. The value # is irrelevant. @blockedVariables = {} # The currently processed rule. @cr = nil @states = {} # The stack used by the FSM. @stack = nil end |
Instance Attribute Details
#rules ⇒ Object (readonly)
Returns the value of attribute rules.
78 79 80 |
# File 'lib/taskjuggler/TextParser.rb', line 78 def rules @rules end |
Instance Method Details
#error(id, text, sfi = nil, data = nil) ⇒ Object
221 222 223 224 225 226 227 228 229 230 |
# File 'lib/taskjuggler/TextParser.rb', line 221 def error(id, text, sfi = nil, data = nil) sfi ||= sourceFileInfo if @scanner # The scanner has some more context information, so we pass the error # on to the TextScanner. @scanner.error(id, text, sfi, data) else error(id, text, sfi, data) end end |
#initRules ⇒ Object
Call all methods that start with ‘rule_’ to initialize the rules.
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/taskjuggler/TextParser.rb', line 113 def initRules methods.each do |m| if m[0, 5] == 'rule_' # Create a new rule with the suffix of the function name as name. newRule(m[5..-1]) # Call the function. send(m) end end end |
#limitTokenSet(tokenSet) ⇒ Object
Limit the allowed tokens of the scanner to the subset passed by the tokenSet Array.
100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/taskjuggler/TextParser.rb', line 100 def limitTokenSet(tokenSet) return unless tokenSet # Create a copy of all supported variables. blockedVariables = @variables.dup # Then delete all that are in the limited set. blockedVariables.delete_if { |v| tokenSet.include?(v) } # And convert the list into a Hash for faster lookups. @blockedVariables = {} blockedVariables.each { |v| @blockedVariables[v] = true } end |
#newRule(name) ⇒ Object
Add a new rule to the rule set. name must be a unique identifier. The function also sets the class variable @cr to the new rule. Subsequent calls to TextParser#pattern, TextParser#optional or TextParser#repeatable will then implicitly operate on the most recently added rule.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/taskjuggler/TextParser.rb', line 129 def newRule(name) # Use a symbol instead of a String. name = name.intern raise "Fatal Error: Rule #{name} already exists" if @rules.has_key?(name) if block_given? saveCr = @cr @rules[name] = @cr = TextParser::Rule.new(name) yield @cr = saveCr else @rules[name] = @cr = TextParser::Rule.new(name) end end |
#optional ⇒ Object
Identify the patterns of the most recently added rule as optional syntax elements.
161 162 163 |
# File 'lib/taskjuggler/TextParser.rb', line 161 def optional @cr.setOptional end |
#parse(ruleName) ⇒ Object
To parse the input this function needs to be called with the name of the rule to start with. It returns the result of the processing function of the top-level parser rule that was specified by ruleName. In case of an error, the result is false.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/taskjuggler/TextParser.rb', line 198 def parse(ruleName) @stack = [] @@expectedTokens = [] begin result = parseFSM(@rules[ruleName]) rescue TjException => msg if msg. && !msg..empty? critical('parse', msg.) end return false end result end |
#pattern(tokens, func = nil) ⇒ Object
Add a new pattern to the most recently added rule. tokens is an array of strings that specify the syntax elements of the pattern. Each token must start with an character that identifies the type of the token. The following types are supported.
-
! a reference to another rule
-
$ a variable token as delivered by the scanner
-
_ a literal token.
func is a Proc object that is called whenever the parser has completed the processing of this rule.
155 156 157 |
# File 'lib/taskjuggler/TextParser.rb', line 155 def pattern(tokens, func = nil) @cr.addPattern(TextParser::Pattern.new(tokens, func)) end |
#repeatable ⇒ Object
Identify the patterns of the most recently added rule as repeatable syntax elements.
167 168 169 |
# File 'lib/taskjuggler/TextParser.rb', line 167 def repeatable @cr.setRepeatable end |
#sourceFileInfo ⇒ Object
Return the SourceFileInfo of the TextScanner at the beginning of the currently processed TextParser::Rule. Or return nil if we don’t have a current position.
216 217 218 219 |
# File 'lib/taskjuggler/TextParser.rb', line 216 def sourceFileInfo return @scanner.sourceFileInfo if @stack.nil? || @stack.length <= 1 @stack.last.firstSourceFileInfo end |
#updateParserTables ⇒ Object
This function needs to be called whenever new rules or patterns have been added and before the next call to TextParser#parse. It’s perfectly ok to call this function from within a parse() call as long as the states that are currently on the stack have not been modified.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/taskjuggler/TextParser.rb', line 175 def updateParserTables saveFsmStack # Invalidate some cached data. @rules.each_value { |rule| rule.flushCache } @states = {} # Generate the parser states for all patterns of all rules. @rules.each_value do |rule| rule.generateStates(@rules).each do |s| @states[[ s.rule, s.pattern, s.index ]] = s end checkRule(rule) end # Compute the transitions between the generated states. @states.each_value do |state| state.addTransitions(@states, @rules) end restoreFsmStack end |
#warning(id, text, sfi = nil, data = nil) ⇒ Object
232 233 234 235 236 237 238 239 240 241 |
# File 'lib/taskjuggler/TextParser.rb', line 232 def warning(id, text, sfi = nil, data = nil) sfi ||= sourceFileInfo if @scanner # The scanner has some more context information, so we pass the # warning on to the TextScanner. @scanner.warning(id, text, sfi, data) else warning(id, text, sfi, data) end end |