//===----------------------------------------------------------------------===//
#include "TGLexer.h"
-#include "llvm/Support/Streams.h"
+#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
-#include <ostream>
#include "llvm/Config/config.h"
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#include <cerrno>
using namespace llvm;
-TGLexer::TGLexer(MemoryBuffer *StartBuf) : CurLineNo(1), CurBuf(StartBuf) {
+TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
+ CurBuffer = 0;
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
CurPtr = CurBuf->getBufferStart();
TokStart = 0;
}
-TGLexer::~TGLexer() {
- while (!IncludeStack.empty()) {
- delete IncludeStack.back().Buffer;
- IncludeStack.pop_back();
- }
- delete CurBuf;
+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) {
return tgtok::Error;
}
-void TGLexer::PrintIncludeStack(std::ostream &OS) const {
- for (unsigned i = 0, e = IncludeStack.size(); i != e; ++i)
- OS << "Included from " << IncludeStack[i].Buffer->getBufferIdentifier()
- << ":" << IncludeStack[i].LineNo << ":\n";
- OS << "Parsing " << CurBuf->getBufferIdentifier() << ":"
- << CurLineNo << ": ";
+
+void TGLexer::PrintError(const char *Loc, const std::string &Msg) const {
+ SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
}
-/// PrintError - Print the error at the specified location.
-void TGLexer::PrintError(const char *ErrorLoc, const std::string &Msg) const {
- PrintIncludeStack(*cerr.stream());
- cerr << Msg << "\n";
- assert(ErrorLoc && "Location not specified!");
-
- // Scan backward to find the start of the line.
- const char *LineStart = ErrorLoc;
- while (LineStart != CurBuf->getBufferStart() &&
- LineStart[-1] != '\n' && LineStart[-1] != '\r')
- --LineStart;
- // Get the end of the line.
- const char *LineEnd = ErrorLoc;
- while (LineEnd != CurBuf->getBufferEnd() &&
- LineEnd[0] != '\n' && LineEnd[0] != '\r')
- ++LineEnd;
- // Print out the line.
- cerr << std::string(LineStart, LineEnd) << "\n";
- // Print out spaces before the carat.
- for (const char *Pos = LineStart; Pos != ErrorLoc; ++Pos)
- cerr << (*Pos == '\t' ? '\t' : ' ');
- cerr << "^\n";
+void TGLexer::PrintError(SMLoc Loc, const std::string &Msg) const {
+ SrcMgr.PrintMessage(Loc, Msg, "error");
}
+
int TGLexer::getNextChar() {
char CurChar = *CurPtr++;
switch (CurChar) {
default:
return (unsigned char)CurChar;
- case 0:
+ case 0: {
// A nul character in the stream is either the end of the current buffer or
// a random nul in the file. Disambiguate that here.
if (CurPtr-1 != CurBuf->getBufferEnd())
// If this is the end of an included file, pop the parent file off the
// include stack.
- if (!IncludeStack.empty()) {
- delete CurBuf;
- CurBuf = IncludeStack.back().Buffer;
- CurLineNo = IncludeStack.back().LineNo;
- CurPtr = IncludeStack.back().CurPtr;
- IncludeStack.pop_back();
+ SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
+ if (ParentIncludeLoc != SMLoc()) {
+ CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
+ CurPtr = ParentIncludeLoc.getPointer();
return getNextChar();
}
// Otherwise, return end of file.
--CurPtr; // Another call to lex will return EOF again.
return EOF;
+ }
case '\n':
case '\r':
// Handle the newline character by ignoring it and incrementing the line
if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
*CurPtr != CurChar)
++CurPtr; // Eat the two char newline sequence.
-
- ++CurLineNo;
return '\n';
}
}
switch (CurChar) {
default:
// Handle letters: [a-zA-Z_]
- if (isalpha(CurChar) || CurChar == '_')
+ 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;
}
const char *IdentStart = TokStart;
// Match the rest of the identifier regex: [0-9a-zA-Z_]*
- while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
- ++CurPtr;
+ while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_'
+ || *CurPtr == '#') {
+ // If this contains a '#', make sure it's value
+ if (*CurPtr == '#') {
+ if (strncmp(CurPtr, "#NAME#", 6) != 0) {
+ return tgtok::Error;
+ }
+ CurPtr += 6;
+ }
+ else {
+ ++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.
- IncludeStack.push_back(IncludeRec(CurBuf, CurPtr, CurLineNo));
-
- CurLineNo = 1; // Reset line numbering.
- 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(TokStart, "Invalid hexadecimal number");
+ if (errno == ERANGE) {
+ errno = 0;
+ CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
+ if (errno == EINVAL)
+ return ReturnError(TokStart, "Invalid hexadecimal number");
+ if (errno == ERANGE)
+ return ReturnError(TokStart, "Hexadecimal number out of range");
+ }
return tgtok::IntVal;
} else if (CurPtr[0] == 'b') {
++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;
-
+ 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 == 2 && !memcmp(Start, "eq", 2)) return tgtok::XEq;
+ if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat;
+ if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat;
+ if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
+ if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
+ if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
+ if (Len == 3 && !memcmp(Start, "car", 3)) return tgtok::XCar;
+ if (Len == 3 && !memcmp(Start, "cdr", 3)) return tgtok::XCdr;
+ if (Len == 4 && !memcmp(Start, "null", 4)) return tgtok::XNull;
+ if (Len == 2 && !memcmp(Start, "if", 2)) return tgtok::XIf;
+
return ReturnError(Start-1, "Unknown operator");
}