Skip to content

Commit

Permalink
Character literals
Browse files Browse the repository at this point in the history
  • Loading branch information
johnno1962 committed Oct 8, 2018
1 parent 72c5367 commit ef0a3ee
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 1 deletion.
6 changes: 6 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Expand Up @@ -114,6 +114,12 @@ ERROR(lex_unprintable_ascii_character,none,
"unprintable ASCII character found in source file", ())
ERROR(lex_invalid_utf8,none,
"invalid UTF-8 found in source file", ())
ERROR(lex_character_empty,none,
"empty character literal", ())
ERROR(lex_character_invalid_escape,none,
"invalid escape in character literal", ())
ERROR(lex_character_not_codepoint,none,
"character not expressible as a single codepoint", ())
ERROR(lex_single_quote_string,none,
"single-quoted string literal found, use '\"'", ())
ERROR(lex_invalid_curly_quote,none,
Expand Down
2 changes: 2 additions & 0 deletions include/swift/Parse/Lexer.h
Expand Up @@ -480,6 +480,8 @@ class Lexer {
void operator=(const SILBodyRAII&) = delete;
};

uint32_t lexCharacterLiteral(const char *&CurPtr);

private:
/// Nul character meaning kind.
enum class NulCharacterKind {
Expand Down
41 changes: 40 additions & 1 deletion lib/Parse/Lexer.cpp
Expand Up @@ -2424,14 +2424,53 @@ void Lexer::lexImpl() {
return lexNumber();

case '"':
case '\'':
return lexStringLiteral();

case '\'': {
const char *TokStart = CurPtr-1;
uint32_t CodePoint = lexCharacterLiteral(CurPtr);
return formToken(CodePoint == ~0U ? tok::unknown :
tok::integer_literal, TokStart);
}

case '`':
return lexEscapedIdentifier();
}
}

uint32_t Lexer::lexCharacterLiteral(const char *&CurPtr) {
uint32_t CodePoint = ~0;
if (*CurPtr == '\'')
diagnose(CurPtr, diag::lex_character_empty);
else if (*CurPtr == '\\') {
switch (*++CurPtr) {
case 't': CodePoint = '\t'; break;
case 'r': CodePoint = '\r'; break;
case 'n': CodePoint = '\n'; break;
case '\\': CodePoint = '\\'; break;
case '\'': ++CurPtr; CodePoint = '\''; break;
default:
diagnose(CurPtr, diag::lex_character_invalid_escape);
}
}
else {
CodePoint = swift::validateUTF8CharacterAndAdvance(CurPtr, BufferEnd);

if (CodePoint == ~0U)
diagnose(CurPtr, diag::lex_invalid_utf8);
}

if (CodePoint != ~0U && *CurPtr != '\'') {
diagnose(CurPtr, diag::lex_character_not_codepoint);
CodePoint = ~0U;
}

while (*CurPtr && *CurPtr != '\n' && *CurPtr++ != '\'');
return CodePoint;
}



Token Lexer::getTokenAtLocation(const SourceManager &SM, SourceLoc Loc) {
// Don't try to do anything with an invalid location.
if (!Loc.isValid())
Expand Down
7 changes: 7 additions & 0 deletions lib/Parse/ParseExpr.cpp
Expand Up @@ -1441,6 +1441,13 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
switch (Tok.getKind()) {
case tok::integer_literal: {
StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
if (Text[0] == '\'') {
const char *CurPtr = Tok.getText().begin() + 1;
uint32_t CodePoint = L->lexCharacterLiteral(CurPtr);
std::string Integer = std::to_string(CodePoint);
char *IntegerBuff = (char *)Context.Allocate(Integer.size() + 1, 1 );
Text = StringRef(strcpy(IntegerBuff, Integer.c_str()), Integer.size());
}
SourceLoc Loc = consumeToken(tok::integer_literal);
ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr);
return makeParserResult(new (Context)
Expand Down
6 changes: 6 additions & 0 deletions stdlib/public/core/Character.swift
Expand Up @@ -497,3 +497,9 @@ extension Character: Hashable {
hasher.combine(String(self))
}
}

extension Character : ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) {
self.init(Unicode.Scalar(_value: UInt32(value)))
}
}
6 changes: 6 additions & 0 deletions stdlib/public/core/UnicodeScalar.swift
Expand Up @@ -44,6 +44,12 @@ extension Unicode {
}
}

extension Unicode.Scalar : ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) {
self.init(_value: UInt32(value))
}
}

extension Unicode.Scalar :
_ExpressibleByBuiltinUnicodeScalarLiteral,
ExpressibleByUnicodeScalarLiteral {
Expand Down

0 comments on commit ef0a3ee

Please sign in to comment.