         @token 'OUTDENT', dent
     @outdebt -= moveOut if dent
     @token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR' or noNewlines
-    true
+    this
 
   # Matches and consumes non-meaningful whitespace. Tag the previous token
   # as being "spaced", because there are some cases where it makes a difference.
   whitespaceToken: ->
-    return false unless (match = WHITESPACE.exec @chunk) or nline = @chunk.substring(0, 1) is '\n'
+    return 0 unless (match = WHITESPACE.exec @chunk) or
+                    (nline = @chunk.charAt(0) is '\n')
     prev = last @tokens
     prev[if match then 'spaced' else 'newLine'] = true if prev
-    @i += match[0].length if match
-    !!match
+    if match then match[0].length else 0
 
   # Generate a newline token. Consecutive newlines get merged together.
-  newlineToken: (newlines) ->
+  newlineToken: ->
     @token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR'
-    true
+    this
 
   # Use a `\` at a line-ending to suppress the newline.
   # The slash is removed here once its job is done.
   suppressNewlines: ->
     @tokens.pop() if @value() is '\\'
-    true
+    this
 
   # We treat all other single characters as a token. Eg.: `( ) , . !`
   # Multi-character operators are also literal tokens, so that Jison can assign

    else
      @token 'STRING', @makeString doc, quote, yes
    @line += count heredoc, '\n'
    @i += heredoc.length
    true

  # Matches and consumes comments.
  commentToken: ->
    return false unless match = @chunk.match COMMENT
    [comment, here] = match
    @line += count comment, '\n'
    @i += comment.length
    if here
      @token 'HERECOMMENT', @sanitizeHeredoc here,
        herecomment: true, indent: Array(@indent + 1).join(' ')
      @token 'TERMINATOR', '\n'
    true

  # Matches JavaScript interpolated directly into the source via backticks.
  jsToken: ->
    return false unless @chunk.charAt(0) is '`' and match = JSTOKEN.exec @chunk
    @token 'JS', (script = match[0]).slice 1, -1
    @i += script.length
    true

  # Matches regular expression literals. Lexing regular expressions is difficult
  # to distinguish from division, so we borrow some basic heuristics from
  # JavaScript and Ruby.
  regexToken: ->
    return false if @chunk.charAt(0) isnt '/'
    return @heregexToken match if match = HEREGEX.exec @chunk
    return false if @tag() in NOT_REGEX
    return false unless match = REGEX.exec @chunk
    [regex] = match
    @token 'REGEX', if regex is '//' then '/(?:)/' else regex
    @i += regex.length
    true

  # Matches experimental, multiline and extended regular expression literals.
  heregexToken: (match) ->
    [heregex, body, flags] = match
    @i += heregex.length
    if 0 > body.indexOf '#{'
      re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/')
      @token 'REGEX', "/#{ re or '(?:)' }/#{flags}"
      return true
    @token 'IDENTIFIER', 'RegExp'
    @tokens.push ['CALL_START', '(']
    tokens = []

        tag = 'BOOL'
    @token tag, id
    @token ':', ':' if colon
    input.length

  # Matches numbers, including decimals, hex, and exponential notation.
  # Be careful not to interfere with ranges-in-progress.
  numberToken: ->
    return 0 unless match = NUMBER.exec @chunk
    number = match[0]
    return 0 if @tag() is '.' and number.charAt(0) is '.'
    @token 'NUMBER', number
    number.length

  # Matches strings, including multi-line strings. Ensures that quotation marks
  # are balanced within the string's contents, and within nested interpolations.
  stringToken: ->
    switch @chunk.charAt 0
      when "'"
        return 0 unless match = SIMPLESTR.exec @chunk
        @token 'STRING', (string = match[0]).replace MULTILINER, '\\\n'
      when '"'
        return 0 unless string = @balancedString @chunk, [['"', '"'], ['#{', '}']]
        if 0 < string.indexOf '#{', 1
          @interpolateString string.slice 1, -1
        else
          @token 'STRING', @escapeLines string
      else
        return 0
    @line += count string, '\n'
    string.length

  # Matches heredocs, adjusting indentation to the correct level, as heredocs
  # preserve whitespace, but ignore indentation to the left.
  heredocToken: ->
    return 0 unless match = HEREDOC.exec @chunk
    heredoc = match[0]
    quote = heredoc.charAt 0
    doc = @sanitizeHeredoc match[2], {quote, indent: null}
