//===----------------------------------------------------------------------===//
#include "TGLexer.h"
-#include "TGSourceMgr.h"
-#include "llvm/Support/Streams.h"
+#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
-#include <ostream>
#include "llvm/Config/config.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cerrno>
using namespace llvm;
-TGLexer::TGLexer(TGSourceMgr &SM) : SrcMgr(SM) {
+TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
CurBuffer = 0;
CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
CurPtr = CurBuf->getBufferStart();
TokStart = 0;
}
+SMLoc TGLexer::getLoc() const {
+ return SMLoc::getFromPointer(TokStart);
+}
+
/// ReturnError - Set the error to the specified string at the specified
/// location. This is defined to always return tgtok::Error.
-tgtok::TokKind TGLexer::ReturnError(const char *Loc, const std::string &Msg) {
+tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
PrintError(Loc, Msg);
return tgtok::Error;
}
-void TGLexer::PrintError(LocTy Loc, const std::string &Msg) const {
- SrcMgr.PrintError(Loc, Msg);
+void TGLexer::PrintError(const char *Loc, const Twine &Msg) const {
+ SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
+}
+
+void TGLexer::PrintError(SMLoc Loc, const Twine &Msg) const {
+ SrcMgr.PrintMessage(Loc, Msg, "error");
}
+
int TGLexer::getNextChar() {
char CurChar = *CurPtr++;
switch (CurChar) {
// If this is the end of an included file, pop the parent file off the
// include stack.
- TGLocTy ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
- if (ParentIncludeLoc != TGLocTy()) {
+ SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
+ if (ParentIncludeLoc != SMLoc()) {
CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
- CurPtr = ParentIncludeLoc;
+ CurPtr = ParentIncludeLoc.getPointer();
return getNextChar();
}
switch (CurChar) {
default:
- // Handle letters: [a-zA-Z_]
- if (isalpha(CurChar) || CurChar == '_')
+ // Handle letters: [a-zA-Z_#]
+ if (isalpha(CurChar) || CurChar == '_' || CurChar == '#')
return LexIdentifier();
// Unknown character, emit an error.
tgtok::TokKind TGLexer::LexString() {
const char *StrStart = CurPtr;
+ CurStrVal = "";
+
while (*CurPtr != '"') {
// If we hit the end of the buffer, report an error.
if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
if (*CurPtr == '\n' || *CurPtr == '\r')
return ReturnError(StrStart, "End of line in string literal");
+ if (*CurPtr != '\\') {
+ CurStrVal += *CurPtr++;
+ continue;
+ }
+
++CurPtr;
+
+ switch (*CurPtr) {
+ case '\\': case '\'': case '"':
+ // These turn into their literal character.
+ CurStrVal += *CurPtr++;
+ break;
+ case 't':
+ CurStrVal += '\t';
+ ++CurPtr;
+ break;
+ case 'n':
+ CurStrVal += '\n';
+ ++CurPtr;
+ break;
+
+ case '\n':
+ case '\r':
+ return ReturnError(CurPtr, "escaped newlines not supported in tblgen");
+
+ // If we hit the end of the buffer, report an error.
+ case '\0':
+ if (CurPtr == CurBuf->getBufferEnd())
+ return ReturnError(StrStart, "End of file in string literal");
+ // FALL THROUGH
+ default:
+ return ReturnError(CurPtr, "invalid escape in string literal");
+ }
}
- CurStrVal.assign(StrStart, CurPtr);
++CurPtr;
return tgtok::StrVal;
}
tgtok::TokKind TGLexer::LexIdentifier() {
- // The first letter is [a-zA-Z_].
+ // The first letter is [a-zA-Z_#].
const char *IdentStart = TokStart;
- // Match the rest of the identifier regex: [0-9a-zA-Z_]*
- while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
+ // Match the rest of the identifier regex: [0-9a-zA-Z_#]*
+ while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' ||
+ *CurPtr == '#')
++CurPtr;
+
// Check to see if this identifier is a keyword.
unsigned Len = CurPtr-IdentStart;
// Get the string.
std::string Filename = CurStrVal;
- // Try to find the file.
- MemoryBuffer *NewBuf = MemoryBuffer::getFile(Filename.c_str());
-
- // If the file didn't exist directly, see if it's in an include path.
- for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBuf; ++i) {
- std::string IncFile = IncludeDirectories[i] + "/" + Filename;
- NewBuf = MemoryBuffer::getFile(IncFile.c_str());
- }
-
- if (NewBuf == 0) {
+
+ CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr));
+ if (CurBuffer == -1) {
PrintError(getLoc(), "Could not find include file '" + Filename + "'");
return true;
}
// Save the line number and lex buffer of the includer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(NewBuf, CurPtr);
-
- CurBuf = NewBuf;
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
CurPtr = CurBuf->getBufferStart();
return false;
}
// Requires at least one hex digit.
if (CurPtr == NumStart)
- return ReturnError(CurPtr-2, "Invalid hexadecimal number");
+ return ReturnError(TokStart, "Invalid hexadecimal number");
errno = 0;
CurIntVal = strtoll(NumStart, 0, 16);
if (errno == EINVAL)
- return ReturnError(CurPtr-2, "Invalid hexadecimal number");
+ return ReturnError(TokStart, "Invalid hexadecimal number");
if (errno == ERANGE) {
errno = 0;
CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
if (errno == EINVAL)
- return ReturnError(CurPtr-2, "Invalid hexadecimal number");
+ return ReturnError(TokStart, "Invalid hexadecimal number");
if (errno == ERANGE)
- return ReturnError(CurPtr-2, "Hexadecimal number out of range");
+ return ReturnError(TokStart, "Hexadecimal number out of range");
}
return tgtok::IntVal;
} else if (CurPtr[0] == 'b') {
/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
tgtok::TokKind TGLexer::LexExclaim() {
if (!isalpha(*CurPtr))
- return ReturnError(CurPtr-1, "Invalid \"!operator\"");
+ return ReturnError(CurPtr - 1, "Invalid \"!operator\"");
const char *Start = CurPtr++;
while (isalpha(*CurPtr))
++CurPtr;
// Check to see which operator this is.
- unsigned Len = CurPtr-Start;
-
- if (Len == 3 && !memcmp(Start, "con", 3)) return tgtok::XConcat;
- if (Len == 3 && !memcmp(Start, "sra", 3)) return tgtok::XSRA;
- if (Len == 3 && !memcmp(Start, "srl", 3)) return tgtok::XSRL;
- if (Len == 3 && !memcmp(Start, "shl", 3)) return tgtok::XSHL;
- if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat;
-
- return ReturnError(Start-1, "Unknown operator");
+ tgtok::TokKind Kind =
+ StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
+ .Case("eq", tgtok::XEq)
+ .Case("if", tgtok::XIf)
+ .Case("head", tgtok::XHead)
+ .Case("tail", tgtok::XTail)
+ .Case("con", tgtok::XConcat)
+ .Case("shl", tgtok::XSHL)
+ .Case("sra", tgtok::XSRA)
+ .Case("srl", tgtok::XSRL)
+ .Case("cast", tgtok::XCast)
+ .Case("empty", tgtok::XEmpty)
+ .Case("subst", tgtok::XSubst)
+ .Case("foreach", tgtok::XForEach)
+ .Case("strconcat", tgtok::XStrConcat)
+ .Default(tgtok::Error);
+
+ return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator");
}