提交 30926012 编写于 作者: A Andrey Breslav

Support unicode escapes in chars and strings

上级 ff624892
......@@ -198,7 +198,7 @@ public class CheckerTestUtil {
opened.pop();
}
assert opened.isEmpty() : "Stack is not empty";
assert opened.isEmpty() : "Stack is not empty: " + opened;
}
else {
......
......@@ -165,29 +165,60 @@ public class CompileTimeConstantResolver {
return error;
}
// Strip the quotes
if (text.charAt(0) != '\'' || text.charAt(text.length() - 1) != '\'') {
return new ErrorValue("Incorret character constant");
return new ErrorValue("Incorrect character literal");
}
text = text.substring(1, text.length() - 1);
text = text.substring(1, text.length() - 1); // now there're no quotes
if (text.length() == 0) {
return new ErrorValue("Empty character literal");
} else if (text.length() == 1) {
if (text.charAt(0) == '\\') {
return new ErrorValue("Illegal escape: " + text);
} else {
return new ErrorValue("Empty character literal");
}
if (text.charAt(0) != '\\') {
// No escape
if (text.length() == 1) {
return new CharValue(text.charAt(0));
}
} else if (text.length() == 2 && text.charAt(0) == '\\') {
Character escaped = translateEscape(text.charAt(1));
if (escaped == null) {
return new ErrorValue("Illegal escape: " + text);
}
return new CharValue(escaped);
} else {
return new ErrorValue("Too many characters in character literal");
return new ErrorValue("Too many characters in a character literal" + text);
}
return escapedStringToCharValue(text);
}
@NotNull
public static CompileTimeConstant<?> escapedStringToCharValue(@NotNull String text) {
assert text.length() > 0 && text.charAt(0) == '\\' : "Only escaped sequences must be passed to this routine: " + text;
// Escape
String escape = text.substring(1); // strip the slash
switch (escape.length()) {
case 0:
// bare slash
return illegalEscape(text);
case 1:
// one-char escape
Character escaped = translateEscape(escape.charAt(0));
if (escaped == null) {
return illegalEscape(text);
}
return new CharValue(escaped);
case 5:
// unicode escape
if (escape.charAt(0) == 'u') {
try {
Integer intValue = Integer.valueOf(escape.substring(1), 16);
return new CharValue((char) intValue.intValue());
} catch (NumberFormatException e) {
// Will be reported below
}
}
break;
}
return illegalEscape(text);
}
private static ErrorValue illegalEscape(String text) {
return new ErrorValue("Illegal escape: " + text);
}
@Nullable
......
......@@ -840,18 +840,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override
public void visitEscapeStringTemplateEntry(JetEscapeStringTemplateEntry entry) {
// TODO : Check escape
String text = entry.getText();
assert text.length() == 2 && text.charAt(0) == '\\';
char escaped = text.charAt(1);
Character character = CompileTimeConstantResolver.translateEscape(escaped);
if (character == null) {
CompileTimeConstant<?> character = CompileTimeConstantResolver.escapedStringToCharValue(text);
if (character instanceof ErrorValue) {
context.trace.report(ILLEGAL_ESCAPE_SEQUENCE.on(entry));
value[0] = CompileTimeConstantResolver.OUT_OF_RANGE;
}
else {
builder.append(character);
builder.append(((CharValue) character).getValue());
}
}
});
......@@ -866,7 +863,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public JetType visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext data) {
return facade.getType(expression.getBaseExpression(), data);
}
@Override
public JetType visitJetElement(JetElement element, ExpressionTypingContext context) {
context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
......
......@@ -92,7 +92,7 @@ HEX_SIGNIFICAND={HEX_INTEGER_LITERAL}|0[Xx]{HEX_DIGIT}*\.{HEX_DIGIT}+
CHARACTER_LITERAL="'"([^\\\'\n]|{ESCAPE_SEQUENCE})*("'"|\\)?
// TODO: introduce symbols (e.g. 'foo) as another way to write string literals
STRING_LITERAL=\"([^\\\"\n]|{ESCAPE_SEQUENCE})*(\"|\\)?
ESCAPE_SEQUENCE=\\[^\n]
ESCAPE_SEQUENCE=\\(u{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}|[^\n])
// ANY_ESCAPE_SEQUENCE = \\[^]
THREE_QUO = (\"\"\")
......
......@@ -18,4 +18,5 @@ fun demo() {
"foo${bar + map { "foo" }}sdfsdf"
"foo${bar + map {
"foo$sdf${ buzz{}}" }}sdfsdf"
"a<!ILLEGAL_ESCAPE_SEQUENCE!>\u<!> <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>0 <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>00 <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>000 \u0000 \u0AaA <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>0AAz.length( ) + \u0022b"
}
\ No newline at end of file
......@@ -23,4 +23,16 @@ fun test() {
<!ERROR_COMPILE_TIME_VALUE!>'\123'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\ra'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\000'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\000'<!>
'\u0000'
'\u000a'
'\u000A'
<!ERROR_COMPILE_TIME_VALUE!>'\u'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\u0'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\u00'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\u000'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\u000z'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\\u000'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\'<!>
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册