//===--- LiteralSupport.cpp - Code to parse and process literals ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the NumericLiteralParser, CharLiteralParser, and
// StringLiteralParser interfaces.
//
//===----------------------------------------------------------------------===//
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
/// HexDigitValue - Return the value of the specified hex digit, or -1 if it's
/// not valid.
static int HexDigitValue(char C) {
if (C >= '0' && C <= '9') return C-'0';
if (C >= 'a' && C <= 'f') return C-'a'+10;
if (C >= 'A' && C <= 'F') return C-'A'+10;
return -1;
}
static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target) {
switch (kind) {
default: assert(0 && "Unknown token type!");
case tok::char_constant:
case tok::string_literal:
case tok::utf8_string_literal:
return Target.getCharWidth();
case tok::wide_char_constant:
case tok::wide_string_literal:
return Target.getWCharWidth();
case tok::utf16_char_constant:
case tok::utf16_string_literal:
return Target.getChar16Width();
case tok::utf32_char_constant:
case tok::utf32_string_literal:
return Target.getChar32Width();
}
}
/// ProcessCharEscape - Parse a standard C escape sequence, which can occur in
/// either a character or a string literal.
static unsigned ProcessCharEscape(const char *&ThisTokBuf,
const char *ThisTokEnd, bool &HadError,
FullSourceLoc Loc, unsigned CharWidth,
Diagnostic *Diags) {
// Skip the '\' char.
++ThisTokBuf;
// We know that this character can't be off the end of the buffer, because
// that would have been \", which would not have been the end of string.
unsigned ResultChar = *ThisTokBuf++;
switch (ResultChar) {
// These map to themselves.
case '\\': case '\'': case '"': case '?': break;
// These have fixed mappings.
case 'a':
// TODO: K&R: the meaning of '\\a' is different in traditional C
ResultChar = 7;
break;
case 'b':
ResultChar = 8;
break;
case 'e':
if (Diags)
Diags->Report(Loc, diag::ext_nonstandard_escape) << "e";
ResultChar = 27;
break;
case 'E':
if (Diags)
Diags->Report(Loc, diag::ext_nonstandard_escape) << "E";
ResultChar = 27;
break;
case 'f':
ResultChar = 12;
break;
case 'n':
ResultChar = 10;
break;
case 'r':
ResultChar = 13;
break;
case 't':
ResultChar = 9;
break;
case 'v':
ResultChar = 11;
break;