Skip to content

Commit 86b85b1

Browse files
committed
Implement verbatim string literals (still need tests)
Fixes google#246
1 parent f75d474 commit 86b85b1

File tree

6 files changed

+54
-2
lines changed

6 files changed

+54
-2
lines changed

core/ast.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ struct LiteralNumber : public AST {
473473
/** Represents JSON strings. */
474474
struct LiteralString : public AST {
475475
String value;
476-
enum TokenKind { SINGLE, DOUBLE, BLOCK };
476+
enum TokenKind { SINGLE, DOUBLE, BLOCK, VERBATIM_SINGLE, VERBATIM_DOUBLE };
477477
TokenKind tokenKind;
478478
std::string blockIndent; // Only contains ' ' and '\t'.
479479
std::string blockTermIndent; // Only contains ' ' and '\t'.

core/desugarer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,9 @@ class Desugarer {
609609
// Nothing to do.
610610

611611
} else if (auto *ast = dynamic_cast<LiteralString*>(ast_)) {
612-
if (ast->tokenKind != LiteralString::BLOCK) {
612+
if ((ast->tokenKind != LiteralString::BLOCK) &&
613+
(ast->tokenKind != LiteralString::VERBATIM_DOUBLE) &&
614+
(ast->tokenKind != LiteralString::VERBATIM_SINGLE)) {
613615
ast->value = jsonnet_string_unescape(ast->location, ast->value);
614616
}
615617
ast->tokenKind = LiteralString::DOUBLE;

core/formatter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,14 @@ class Unparser {
463463
}
464464
}
465465
o << ast->blockTermIndent << "|||";
466+
} else if (ast->tokenKind == LiteralString::VERBATIM_DOUBLE) {
467+
o << "@\"";
468+
o << encode_utf8(ast->value);
469+
o << "\"";
470+
} else if (ast->tokenKind == LiteralString::VERBATIM_SINGLE) {
471+
o << "@'";
472+
o << encode_utf8(ast->value);
473+
o << "'";
466474
}
467475

468476
} else if (dynamic_cast<const LiteralNull*>(ast_)) {

core/lexer.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,39 @@ Tokens jsonnet_lex(const std::string &filename, const char *input)
507507
}
508508
break;
509509

510+
// Verbatim string literals.
511+
case '@': {
512+
c++;
513+
if (*c != '"' && *c != '\'') {
514+
std::stringstream ss;
515+
ss << "Couldn't lex verbatim string, junk after '@': " << *c;
516+
throw StaticError(filename, begin, ss.str());
517+
}
518+
const char quot = *c;
519+
c++; // Advance beyond the opening quote.
520+
for (; ; ++c) {
521+
if (*c == '\0') {
522+
throw StaticError(filename, begin, "Unterminated verbatim string");
523+
}
524+
if (*c == quot) {
525+
if (*(c+1) == quot) {
526+
data += *c;
527+
++c;
528+
} else {
529+
break;
530+
}
531+
}
532+
data += *c;
533+
}
534+
c++; // Advance beyond the closing quote.
535+
if (quot == '"') {
536+
kind = Token::VERBATIM_STRING_DOUBLE;
537+
} else {
538+
kind = Token::VERBATIM_STRING_SINGLE;
539+
}
540+
}
541+
break;
542+
510543
// Keywords
511544
default:
512545
if (is_identifier_first(*c)) {

core/lexer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ struct Token {
102102
STRING_DOUBLE,
103103
STRING_SINGLE,
104104
STRING_BLOCK,
105+
VERBATIM_STRING_SINGLE,
106+
VERBATIM_STRING_DOUBLE,
105107

106108
// Keywords
107109
ASSERT,

core/parser.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,13 @@ class Parser {
634634
return alloc->make<LiteralString>(
635635
span(tok), tok.fodder, tok.data32(), LiteralString::BLOCK,
636636
tok.stringBlockIndent, tok.stringBlockTermIndent);
637+
case Token::VERBATIM_STRING_SINGLE:
638+
return alloc->make<LiteralString>(
639+
span(tok), tok.fodder, tok.data32(), LiteralString::VERBATIM_SINGLE, "", "");
640+
case Token::VERBATIM_STRING_DOUBLE:
641+
return alloc->make<LiteralString>(
642+
span(tok), tok.fodder, tok.data32(), LiteralString::VERBATIM_DOUBLE, "", "");
643+
637644

638645
case Token::FALSE:
639646
return alloc->make<LiteralBoolean>(span(tok), tok.fodder, false);

0 commit comments

Comments
 (0)