class TaskJuggler::TextParser::Scanner::StreamHandle

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.

Attributes

fileName[R]
macroStack[R]

Public Class Methods

new(log, textScanner) click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 53
def initialize(log, textScanner)
  @log = log
  @textScanner = textScanner
  @fileName = nil
  @stream = nil
  @line = nil
  @endPos = 1
  @scanner = nil
  @wrapped = false
  @macroStack = []
  @nextMacroEnd = nil
end

Public Instance Methods

cleanupMacroStack() click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 123
def cleanupMacroStack
  if @nextMacroEnd
    pos = @scanner.pos
    while @nextMacroEnd && @nextMacroEnd < pos
      @macroStack.pop
      @nextMacroEnd = @macroStack.empty? ? nil : @macroStack.last.endPos
    end
  end
end
close() click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 70
def close
  @stream = nil
end
dirname() click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 141
def dirname
  @fileName ? File.dirname(@fileName) : ''
end
eof?() click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 137
def eof?
  @stream.eof? && @scanner.eos?
end
error(id, message) click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 66
def error(id, message)
  @textScanner.error(id, message)
end
injectMacro(macro, args, text, callLength) click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 90
def injectMacro(macro, args, text, callLength)
  injectText(text, callLength)

  # Simple detection for recursive macro calls.
  return false if @macroStack.length > 20

  @macroStack << MacroStackEntry.new(macro, args, text, @nextMacroEnd)
  true
end
injectText(text, callLength) click to toggle source

Inject the String text into the input stream at the current cursor position.

# File lib/taskjuggler/TextParser/Scanner.rb, line 76
def injectText(text, callLength)
  # 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.string = @line
  @scanner.pos = preCall.bytesize
end
line() click to toggle source

Return the already processed part of the current line.

# File lib/taskjuggler/TextParser/Scanner.rb, line 156
def line
  return '' unless @line

  (@scanner.pre_match || '') + (@scanner.matched || '')
end
lineNo() click to toggle source

Return the number of the currently processed line.

# File lib/taskjuggler/TextParser/Scanner.rb, line 146
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
peek(n) click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 133
def peek(n)
  @scanner ? @scanner.peek(n) : nil
end
readyNextLine() click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 100
def readyNextLine
  # 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 false
    end
    @scanner = StringScanner.new(@line)
    @wrapped = @line[-1] == ?\n
  end

  true
end
scan(re) click to toggle source
# File lib/taskjuggler/TextParser/Scanner.rb, line 119
def scan(re)
  @scanner.scan(re)
end