Skip to content

Commit

Permalink
Lexer: Handle triple quoted raw strings (e.g. r"""abc""").
Browse files Browse the repository at this point in the history
--
MOS_MIGRATED_REVID=105956734
  • Loading branch information
laurentlb authored and hanwen committed Oct 21, 2015
1 parent 5d9b8a0 commit 4d7fae3
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 9 deletions.
19 changes: 13 additions & 6 deletions src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ private boolean skipTripleQuote(char quot) {
*
* @return the string-literal token.
*/
private Token escapedStringLiteral(char quot) {
private Token escapedStringLiteral(char quot, boolean isRaw) {
boolean inTriplequote = skipTripleQuote(quot);

int oldPos = pos - 1;
Expand All @@ -336,6 +336,14 @@ private Token escapedStringLiteral(char quot) {
error("unterminated string literal at eof", oldPos, pos);
return new Token(TokenKind.STRING, oldPos, pos, literal.toString());
}
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) {
Expand Down Expand Up @@ -428,7 +436,7 @@ private Token stringLiteral(char quot, boolean isRaw) {
// Don't even attempt to parse triple-quotes here.
if (skipTripleQuote(quot)) {
pos -= 2;
return escapedStringLiteral(quot);
return escapedStringLiteral(quot, isRaw);
}

// first quick optimistic scan for a simple non-escaped string
Expand All @@ -446,11 +454,10 @@ private Token stringLiteral(char quot, boolean isRaw) {
// skip the next character
pos++;
break;
} else {
// oops, hit an escape, need to start over & build a new string buffer
pos = oldPos + 1;
return escapedStringLiteral(quot);
}
// oops, hit an escape, need to start over & build a new string buffer
pos = oldPos + 1;
return escapedStringLiteral(quot, false);
case '\'':
case '"':
if (c == quot) {
Expand Down
30 changes: 27 additions & 3 deletions src/test/java/com/google/devtools/build/lib/syntax/LexerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,14 @@ public void testStringEscapes() throws Exception {
assertEquals("STRING(\\$$) NEWLINE EOF", values(tokens("'\\$$'")));
assertEquals("STRING(ab) NEWLINE EOF",
values(tokens("'a\\\nb'"))); // escape end of line
assertEquals("STRING(abcd) NEWLINE EOF",
values(tokens("\"ab\\ucd\"")));
assertEquals("/some/path.txt:1: escape sequence not implemented: \\u",
lastError.toString());
}

@Test
public void testRawString() throws Exception {
assertEquals("STRING(abcd) NEWLINE EOF",
values(tokens("r'abcd'")));
assertEquals("STRING(abcd) NEWLINE EOF",
Expand All @@ -261,9 +268,26 @@ public void testStringEscapes() throws Exception {
assertEquals("STRING(ab) IDENTIFIER(r) NEWLINE EOF",
values(tokens("r'ab'r")));

assertEquals("STRING(abcd) NEWLINE EOF",
values(tokens("\"ab\\ucd\"")));
assertEquals("/some/path.txt:1: escape sequence not implemented: \\u",
// Unterminated raw string
values(tokens("r'\\'")); // r'\'
assertEquals("/some/path.txt:1: unterminated string literal at eof",
lastError.toString());
}

@Test
public void testTripleRawString() throws Exception {
// r'''a\ncd'''
assertEquals("STRING(ab\\ncd) NEWLINE EOF",
values(tokens("r'''ab\\ncd'''")));
// r"""ab
// cd"""
assertEquals(
"STRING(ab\ncd) NEWLINE EOF",
values(tokens("\"\"\"ab\ncd\"\"\"")));

// Unterminated raw string
values(tokens("r'''\\'''")); // r'''\'''
assertEquals("/some/path.txt:1: unterminated string literal at eof",
lastError.toString());
}

Expand Down

0 comments on commit 4d7fae3

Please sign in to comment.