code: private void _string() throws
        IOException,
        CssException
    {
  
      if (debug)
      {
        checkState(QUOTES.matches((char) reader.curChar));
      }
  
      /*
         * Note: resulting token excludes start+end quotes
         */
  
      builder.type = Type.STRING;
      int quoteType = reader.curChar;
  
      // in strings, we let escapes in general pass through
      while (true)
      {
        CssReader.Mark mark = reader.mark();
        int ch = reader.next();
        if (ch == -1)
        {
          builder.error(SCANNER_PREMATURE_EOF, reader);
          reader.unread(ch, mark);
          break;
        }
        else if (ch == '\n' || ch == '\r' || ch == '\f')
        {
          builder.error(SCANNER_ILLEGAL_CHAR, reader, "NEWLINE",
              Type.STRING.name());
          reader.forward(TERMINATOR);
          break;
        }
        else if (ch == '\\')
        {
          int[] peek = reader.peek(2);
          int nl = isNewLine(peek);
          if (nl > 0)
          {
            // in strings, ignore backslash followed by a literal
            // newline
            reader.forward(nl);
            continue;
          }
  
        }
        else if (ch == quoteType && reader.prevChar != '\\')
        {
          break;
        }
  
        builder.append(ch);
      }
  
      if (debug && builder.errors.size() == 0)
      {
        checkState(QUOTES.matches((char) reader.curChar));
      }
    }
docs: string1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\"
  string2 \'([^\n\r\f\\']|\\{nl}|{escape})*\'