   stringToken: ->
     switch @chunk.charAt 0
       when "'"
-        return false unless string = @match SIMPLESTR
-        @token 'STRING', string.replace MULTILINER, '\\\n'
+        return false unless match = SIMPLESTR.exec @chunk
+        @token 'STRING', (string = match[0]).replace MULTILINER, '\\\n'
       when '"'
         return false unless string = @balancedToken ['"', '"'], ['#{', '}']
         @interpolateString string.replace MULTILINER, '\\\n'

  prev: (index) ->
    @tokens[@tokens.length - (index or 1)]

  # Attempt to match a string against the current chunk, returning the indexed
  # match if successful, and `false` otherwise.
  match: (regex, index) ->
    if m = @chunk.match regex then m[index or 0] else false

  # Are we in the midst of an unfinished expression?
  unfinished: ->
    (prev  = @prev 2 ) and prev[0] isnt '.' and

    @outdebt = 0            # The under-outdentation at the current level.
    @indents = []           # The stack of all current indentation levels.
    @tokens  = []           # Stream of parsed tokens in the form ['TYPE', value, line]
    # At every position, run through this list of attempted matches,
    # short-circuiting if any of them succeed. Their order determines precedence:
    # `@literalToken` is the fallback catch-all.
    while (@chunk = code[@i..])
      @identifierToken() or
      @commentToken()    or
      @whitespaceToken() or
      @lineToken()       or
      @heredocToken()    or
      @stringToken()     or
      @numberToken()     or
      @regexToken()      or
      @jsToken()         or
      @literalToken()
    @closeIndentation()
    return @tokens if o.rewrite is off
    (new Rewriter).rewrite @tokens

  # Tokenizers
  # ----------
