StringLiteral.ceylon
import ceylon.ast.core {
StringLiteral
}
import com.redhat.ceylon.compiler.typechecker.tree {
Tree {
JStringLiteral=StringLiteral
}
}
import com.redhat.ceylon.compiler.typechecker.parser {
CeylonLexer {
astring_literal=\iASTRING_LITERAL,
averbatim_string=\iAVERBATIM_STRING,
string_literal=\iSTRING_LITERAL,
verbatim_string_literal=\iVERBATIM_STRING
}
}
import org.antlr.runtime {
CommonToken
}
"""Strips quotes and leading indentation from a string literal.
For example,
"Hello,
World"
is turned into
Hello,
World"""
String stripStringLiteral(CommonToken token, Boolean isVerbatim) {
// value isVerbatim = token.type == verbatim_string_literal || token.type == averbatim_string;
value quoteLength = isVerbatim then 3 else 1;
Integer toStrip = token.charPositionInLine + quoteLength;
StringBuilder ret = StringBuilder();
value text = token.text[quoteLength .. token.text.size - (quoteLength + 1)];
value lines = text.lines;
if (exists firstLine = lines.first) {
ret.append(firstLine);
for (line in lines.rest) {
ret.appendNewline();
value parts = line.slice(toStrip);
"Multiline string content should align with start of string"
assert (parts[0].every(Character.whitespace));
ret.append(parts[1]);
}
}
return ret.string;
}
"Converts a RedHat AST [[StringLiteral|JStringLiteral]] to a `ceylon.ast` [[StringLiteral]]."
throws (`class AssertionError`, "If the token type is neither `STRING_LITERAL` nor `VERBATIM_STRING`
nor `ASTRING_LITERAL` nor `AVERBATIM_STRING`.")
shared StringLiteral stringLiteralToCeylon(JStringLiteral stringLiteral) {
assert (is CommonToken token = stringLiteral.mainToken);
if (token.type == verbatim_string_literal || token.type == averbatim_string) {
// verbatim
return StringLiteral(stripStringLiteral(token, true), true);
} else if (token.type == string_literal || token.type == astring_literal) {
// regular
return StringLiteral(stripStringLiteral(token, false), false);
} else {
throw AssertionError("Unknown token type ``stringLiteral.mainToken.type``");
}
}
"Converts a RedHat AST [[StringLiteral|JStringLiteral]] with annotation token type
(`ASTRING_LITERAL` or `AVERBATIM_STRING`) to a `ceylon.ast` [[StringLiteral]]."
throws (`class AssertionError`, "If the token type is neither `ASTRING_LITERAL` nor `AVERBATIM_STRING`.")
shared StringLiteral aStringLiteralToCeylon(JStringLiteral stringLiteral) {
assert (is CommonToken token = stringLiteral.mainToken);
if (token.type == averbatim_string) {
// verbatim
return StringLiteral(stripStringLiteral(token, true), true);
} else if (token.type == astring_literal) {
// regular
return StringLiteral(stripStringLiteral(token, false), false);
} else {
throw AssertionError("Unknown token type ``stringLiteral.mainToken.type``");
}
}
"Compiles the given [[code]] for a String Literal
into a [[StringLiteral]] using the Ceylon compiler
(more specifically, the rule for a `stringLiteral`)."
shared StringLiteral? compileStringLiteral(String code) {
if (exists jStringLiteral = createParser(code).stringLiteral()) {
return stringLiteralToCeylon(jStringLiteral);
} else {
return null;
}
}