| Class | TaskJuggler::TextParser::Scanner::StreamHandle |
| In: |
lib/taskjuggler/TextParser/Scanner.rb
|
| Parent: | Object |
This class is used to handle the low-level input operations. It knows whether it deals with a text buffer or a file and abstracts this to the Scanner. For each nested file the scanner puts an StreamHandle on the stack while the file is scanned. With this stack the scanner can resume the processing of the enclosing file once the included files has been completely processed.
| fileName | [R] | |
| macroStack | [R] |
# File lib/taskjuggler/TextParser/Scanner.rb, line 55 def initialize(log, textScanner) @log = log @textScanner = textScanner @fileName = nil @stream = nil @line = nil @endPos = 1 @scanner = nil @mrxScanner = nil @wrapped = false @macroStack = [] @nextMacroEnd = nil end
# File lib/taskjuggler/TextParser/Scanner.rb, line 178 def dirname @fileName ? File.dirname(@fileName) : '' end
# File lib/taskjuggler/TextParser/Scanner.rb, line 69 def error(id, message) @textScanner.error(id, message) end
# File lib/taskjuggler/TextParser/Scanner.rb, line 98 def injectMacro(macro, args, text, callLength) # We add 3 chars more for the ${}. injectText(text, callLength) # Simple detection for recursive macro calls. return false if @macroStack.length > 20 @macroStack << MacroStackEntry.new(macro, args, text, @nextMacroEnd) true end
Inject the String text into the input stream at the current cursor position.
# File lib/taskjuggler/TextParser/Scanner.rb, line 79 def injectText(text, callLength) if @scanner.is_a?(MRXScanner) @scanner.scan(@line) @scanner.seek(preCall.bytesize) else # Remove the macro call from the end of the already parsed input. preCall = @scanner.pre_match[0..-(callLength + 1)] # Store the end position of the inserted macro in bytes. @nextMacroEnd = preCall.bytesize + text.bytesize # Compose the new @line from the cleaned input, the injected text and # the remainer of the old @line. @line = preCall + text + @scanner.post_match # Start the StringScanner again at the first character of the injected # text. @scanner = StringScanner.new(@line) @scanner.pos = preCall.bytesize end end
Return the number of the currently processed line.
# File lib/taskjuggler/TextParser/Scanner.rb, line 183 def lineNo # The IO object counts the lines for us by counting the gets() calls. currentLine = @stream && @scanner ? @stream.lineno : 1 # If we've just read the LF, we have to add 1. The LF can only be the # last character of the line. currentLine += 1 if @wrapped && @line && @scanner && @scanner.eos? currentLine end
# File lib/taskjuggler/TextParser/Scanner.rb, line 109 def mrxscan(mode) # We read the file line by line with gets(). If we don't have a line # yet or we've reached the end of a line, we get the next one. if @scanner.nil? || @scanner.eos? if (@line = @stream.gets) # Update activity meter about every 1024 lines. @log.activity if (@stream.lineno & 0x3FF) == 0 else # We've reached the end of the current file. @scanner = nil # Return special EOF symbol. return :scannerEOF end @scanner = @textScanner.mrxs @scanner.read(@line) @wrapped = @line[-1] == ?\n end return nil if (token = @scanner.scan(nil, nil, mode)).nil? #puts "#{re.to_s[0..20]}: [#{token}]" if @nextMacroEnd pos = @scanner.pos while @nextMacroEnd && @nextMacroEnd < pos @macroStack.pop @nextMacroEnd = @macroStack.empty? ? nil : @macroStack.last.endPos end end token end
# File lib/taskjuggler/TextParser/Scanner.rb, line 170 def peek(n) @scanner ? @scanner.peek(n) : nil end
# File lib/taskjuggler/TextParser/Scanner.rb, line 140 def scan(re) # We read the file line by line with gets(). If we don't have a line # yet or we've reached the end of a line, we get the next one. if @scanner.nil? || @scanner.eos? if (@line = @stream.gets) # Update activity meter about every 1024 lines. @log.activity if (@stream.lineno & 0x3FF) == 0 else # We've reached the end of the current file. @scanner = nil # Return special EOF symbol. return :scannerEOF end @scanner = StringScanner.new(@line) @wrapped = @line[-1] == ?\n end return nil if (token = @scanner.scan(re)).nil? #puts "#{re.to_s[0..20]}: [#{token}]" if @nextMacroEnd pos = @scanner.pos while @nextMacroEnd && @nextMacroEnd < pos @macroStack.pop @nextMacroEnd = @macroStack.empty? ? nil : @macroStack.last.endPos end end token end