private void escapedStringLiteral()

in base/src/com/google/idea/blaze/base/lang/buildfile/lexer/BuildLexerBase.java [279:400]


  private void escapedStringLiteral(char quot, boolean isRaw) {
    int oldPos = isRaw ? pos - 2 : pos - 1;
    boolean inTripleQuote = skipTripleQuote(quot);

    // more expensive second choice that expands escaped into a buffer
    StringBuilder literal = new StringBuilder();
    while (pos < buffer.length) {
      char c = buffer[pos];
      pos++;
      switch (c) {
        case '\n':
          if (inTripleQuote) {
            literal.append(c);
            break;
          } else {
            error("unterminated string literal at eol", oldPos, pos);
            addToken(TokenKind.STRING, oldPos, pos - 1, literal.toString());
            newline();
            return;
          }
        case '\\':
          if (pos == buffer.length) {
            error("unterminated string literal at eof", oldPos, pos);
            addToken(TokenKind.STRING, oldPos, pos - 1, literal.toString());
            return;
          }
          if (isRaw) {
            // Insert \ and the following character.
            // As in Python, it means that a raw string can never end with a single \.
            literal.append('\\');
            literal.append(buffer[pos]);
            pos++;
            break;
          }
          c = buffer[pos];
          pos++;
          switch (c) {
            case '\n':
              // ignore end of line character
              break;
            case 'n':
              literal.append('\n');
              break;
            case 'r':
              literal.append('\r');
              break;
            case 't':
              literal.append('\t');
              break;
            case '\\':
              literal.append('\\');
              break;
            case '\'':
              literal.append('\'');
              break;
            case '"':
              literal.append('"');
              break;
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
              { // octal escape
                int octal = c - '0';
                if (pos < buffer.length) {
                  c = buffer[pos];
                  if (c >= '0' && c <= '7') {
                    pos++;
                    octal = (octal << 3) | (c - '0');
                    if (pos < buffer.length) {
                      c = buffer[pos];
                      if (c >= '0' && c <= '7') {
                        pos++;
                        octal = (octal << 3) | (c - '0');
                      }
                    }
                  }
                }
                literal.append((char) (octal & 0xff));
                break;
              }
            case 'a':
            case 'b':
            case 'f':
            case 'N':
            case 'u':
            case 'U':
            case 'v':
            case 'x':
              // exists in Python but not implemented in Blaze => error
              error("escape sequence not implemented: \\" + c, oldPos, pos);
              break;
            default:
              // unknown char escape => "\literal"
              literal.append('\\');
              literal.append(c);
              break;
          }
          break;
        case '\'':
        case '"':
          if (c != quot || (inTripleQuote && !skipTripleQuote(quot))) {
            // Non-matching quote, treat it like a regular char.
            literal.append(c);
          } else {
            // Matching close-delimiter, all done.
            addToken(TokenKind.STRING, oldPos, pos, literal.toString());
            return;
          }
          break;
        default:
          literal.append(c);
          break;
      }
    }
    error("unterminated string literal at eof", oldPos, pos);
    addToken(TokenKind.STRING, oldPos, pos, literal.toString());
  }