17#include "llvm/Config/config.h"
38} PreprocessorDirs[] = {
50 CurPtr = CurBuf.
begin();
54 PrepIncludeStack.push_back(
55 std::make_unique<std::vector<PreprocessorControlDesc>>());
58 for (
const std::string &MacroName : Macros)
59 DefinedMacros.
insert(MacroName);
81bool TGLexer::processEOF() {
83 if (ParentIncludeLoc !=
SMLoc()) {
88 if (!prepExitInclude(
false))
104 prepExitInclude(
true);
108int TGLexer::getNextChar() {
109 char CurChar = *CurPtr++;
112 return (
unsigned char)CurChar;
117 if (CurPtr - 1 == CurBuf.
end()) {
122 "NUL character is invalid in source; treated as space");
131 if ((*CurPtr ==
'\n' || (*CurPtr ==
'\r')) &&
138int TGLexer::peekNextChar(
int Index)
const {
139 return *(CurPtr +
Index);
145 int CurChar = getNextChar();
150 if (isalpha(CurChar) || CurChar ==
'_')
151 return LexIdentifier();
154 return ReturnError(TokStart,
"Unexpected character");
180 if (FileOrLineStart) {
183 return lexPreprocessor(Kind);
191 if (peekNextChar(0) ==
'.') {
193 if (peekNextChar(0) ==
'.') {
197 return ReturnError(TokStart,
"Invalid '..' punctuation");
208 return LexToken(FileOrLineStart);
211 return LexToken(
true);
217 else if (*CurPtr ==
'*') {
221 return ReturnError(TokStart,
"Unexpected character");
222 return LexToken(FileOrLineStart);
224 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
225 case '7':
case '8':
case '9': {
227 if (isdigit(CurChar)) {
233 NextChar = peekNextChar(i++);
234 }
while (isdigit(NextChar));
236 if (NextChar ==
'x' || NextChar ==
'b') {
239 int NextNextChar = peekNextChar(i);
240 switch (NextNextChar) {
247 case '2':
case '3':
case '4':
case '5':
248 case '6':
case '7':
case '8':
case '9':
249 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
250 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
258 if (isalpha(NextChar) || NextChar ==
'_')
259 return LexIdentifier();
263 case '"':
return LexString();
264 case '$':
return LexVarName();
265 case '[':
return LexBracket();
266 case '!':
return LexExclaim();
272 const char *StrStart = CurPtr;
276 while (*CurPtr !=
'"') {
278 if (*CurPtr == 0 && CurPtr == CurBuf.
end())
279 return ReturnError(StrStart,
"End of file in string literal");
281 if (*CurPtr ==
'\n' || *CurPtr ==
'\r')
282 return ReturnError(StrStart,
"End of line in string literal");
284 if (*CurPtr !=
'\\') {
285 CurStrVal += *CurPtr++;
292 case '\\':
case '\'':
case '"':
294 CurStrVal += *CurPtr++;
307 return ReturnError(CurPtr,
"escaped newlines not supported in tblgen");
311 if (CurPtr == CurBuf.
end())
312 return ReturnError(StrStart,
"End of file in string literal");
315 return ReturnError(CurPtr,
"invalid escape in string literal");
324 if (!isalpha(CurPtr[0]) && CurPtr[0] !=
'_')
325 return ReturnError(TokStart,
"Invalid variable name");
328 const char *VarNameStart = CurPtr++;
330 while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr ==
'_')
333 CurStrVal.assign(VarNameStart, CurPtr);
339 const char *IdentStart = TokStart;
342 while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr ==
'_')
346 StringRef Str(IdentStart, CurPtr-IdentStart);
381 CurStrVal.assign(Str.begin(), Str.end());
392bool TGLexer::LexInclude() {
403 std::string IncludedFile;
412 Dependencies.insert(IncludedFile);
415 CurPtr = CurBuf.
begin();
417 PrepIncludeStack.push_back(
418 std::make_unique<std::vector<PreprocessorControlDesc>>());
424void TGLexer::SkipBCPLComment() {
432bool TGLexer::SkipCComment() {
434 unsigned CommentDepth = 1;
437 int CurChar = getNextChar();
440 PrintError(TokStart,
"Unterminated comment!");
444 if (CurPtr[0] !=
'/')
break;
447 if (--CommentDepth == 0)
452 if (CurPtr[0] !=
'*')
break;
465 if (CurPtr[-1] ==
'0') {
466 if (CurPtr[0] ==
'x') {
468 const char *NumStart = CurPtr;
469 while (isxdigit(CurPtr[0]))
473 if (CurPtr == NumStart)
474 return ReturnError(TokStart,
"Invalid hexadecimal number");
477 CurIntVal = strtoll(NumStart,
nullptr, 16);
479 return ReturnError(TokStart,
"Invalid hexadecimal number");
480 if (errno == ERANGE) {
482 CurIntVal = (int64_t)strtoull(NumStart,
nullptr, 16);
484 return ReturnError(TokStart,
"Invalid hexadecimal number");
486 return ReturnError(TokStart,
"Hexadecimal number out of range");
489 }
else if (CurPtr[0] ==
'b') {
491 const char *NumStart = CurPtr;
492 while (CurPtr[0] ==
'0' || CurPtr[0] ==
'1')
496 if (CurPtr == NumStart)
497 return ReturnError(CurPtr-2,
"Invalid binary number");
498 CurIntVal = strtoll(NumStart,
nullptr, 2);
504 if (!isdigit(CurPtr[0])) {
505 if (CurPtr[-1] ==
'-')
507 else if (CurPtr[-1] ==
'+')
511 while (isdigit(CurPtr[0]))
513 CurIntVal = strtoll(TokStart,
nullptr, 10);
520 if (CurPtr[0] !=
'{')
523 const char *CodeStart = CurPtr;
525 int Char = getNextChar();
526 if (Char == EOF)
break;
528 if (Char !=
'}')
continue;
530 Char = getNextChar();
531 if (Char == EOF)
break;
533 CurStrVal.assign(CodeStart, CurPtr-2);
538 return ReturnError(CodeStart - 2,
"Unterminated code block");
543 if (!isalpha(*CurPtr))
544 return ReturnError(CurPtr - 1,
"Invalid \"!operator\"");
546 const char *Start = CurPtr++;
547 while (isalpha(*CurPtr))
602bool TGLexer::prepExitInclude(
bool IncludeStackMustBeEmpty) {
605 if (!PrepIncludeStack.back()->empty()) {
606 prepReportPreprocessorStackError();
612 if (PrepIncludeStack.empty()) {
616 PrepIncludeStack.pop_back();
618 if (IncludeStackMustBeEmpty) {
619 if (!PrepIncludeStack.empty())
622 if (PrepIncludeStack.empty())
630 for (
const auto &PD : PreprocessorDirs) {
631 int NextChar = *CurPtr;
634 for (;
I < strlen(
PD.Word); ++
I) {
635 if (NextChar !=
PD.Word[
I]) {
640 NextChar = peekNextChar(
I + 1);
650 if (NextChar ==
' ' || NextChar ==
'\t' || NextChar == EOF ||
670 if (NextChar ==
'/') {
671 NextChar = peekNextChar(
I + 1);
673 if (NextChar ==
'*' || NextChar ==
'/')
687 for (
const auto &PD : PreprocessorDirs)
688 if (
PD.Kind == Kind) {
690 CurPtr += strlen(
PD.Word);
695 "prepEatPreprocessorDirective()");
703 if (!prepEatPreprocessorDirective(Kind))
705 "preprocessor directive");
708 StringRef MacroName = prepLexMacroName();
710 if (MacroName.
empty())
711 return ReturnError(TokStart,
"Expected macro name after " + IfTokName);
713 bool MacroIsDefined = DefinedMacros.
count(MacroName) != 0;
717 MacroIsDefined = !MacroIsDefined;
723 PrepIncludeStack.back()->push_back(
726 if (!prepSkipDirectiveEnd())
727 return ReturnError(CurPtr,
"Only comments are supported after " +
728 IfTokName +
" NAME");
732 if (!ReturnNextLiveToken)
744 if (prepSkipRegion(ReturnNextLiveToken))
751 if (PrepIncludeStack.back()->empty())
752 return ReturnError(TokStart,
"#else without #ifdef or #ifndef");
754 PreprocessorControlDesc IfdefEntry = PrepIncludeStack.back()->back();
758 return ReturnError(IfdefEntry.SrcPos,
"Previous #else is here");
763 PrepIncludeStack.back()->pop_back();
764 PrepIncludeStack.back()->push_back(
767 if (!prepSkipDirectiveEnd())
768 return ReturnError(CurPtr,
"Only comments are supported after #else");
772 if (ReturnNextLiveToken) {
773 if (prepSkipRegion(ReturnNextLiveToken))
784 if (PrepIncludeStack.back()->empty())
785 return ReturnError(TokStart,
"#endif without #ifdef");
787 auto &IfdefOrElseEntry = PrepIncludeStack.back()->back();
795 if (!prepSkipDirectiveEnd())
796 return ReturnError(CurPtr,
"Only comments are supported after #endif");
798 PrepIncludeStack.back()->pop_back();
802 if (ReturnNextLiveToken) {
809 StringRef MacroName = prepLexMacroName();
810 if (MacroName.
empty())
811 return ReturnError(TokStart,
"Expected macro name after #define");
813 if (!DefinedMacros.
insert(MacroName).second)
815 "Duplicate definition of macro: " +
Twine(MacroName));
817 if (!prepSkipDirectiveEnd())
818 return ReturnError(CurPtr,
819 "Only comments are supported after #define NAME");
821 if (!ReturnNextLiveToken) {
833bool TGLexer::prepSkipRegion(
bool MustNeverBeFalse) {
834 if (!MustNeverBeFalse)
842 if (!prepSkipLineBegin())
870 if (Kind != ProcessedKind)
872 "returned different token kinds");
878 if (prepIsProcessingEnabled()) {
881 "preprocessing directive");
887 }
while (CurPtr != CurBuf.
end());
891 prepReportPreprocessorStackError();
897 while (*CurPtr ==
' ' || *CurPtr ==
'\t')
902 if (*CurPtr !=
'_' && !isalpha(*CurPtr))
906 while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr ==
'_')
909 return StringRef(TokStart, CurPtr - TokStart);
912bool TGLexer::prepSkipLineBegin() {
913 while (CurPtr != CurBuf.
end()) {
922 int NextChar = peekNextChar(1);
923 if (NextChar ==
'*') {
961bool TGLexer::prepSkipDirectiveEnd() {
962 while (CurPtr != CurBuf.
end()) {
973 int NextChar = peekNextChar(1);
974 if (NextChar ==
'/') {
980 }
else if (NextChar ==
'*') {
1022void TGLexer::prepSkipToLineEnd() {
1023 while (*CurPtr !=
'\n' && *CurPtr !=
'\r' && CurPtr != CurBuf.
end())
1027bool TGLexer::prepIsProcessingEnabled() {
1028 for (
const PreprocessorControlDesc &
I :
1036void TGLexer::prepReportPreprocessorStackError() {
1037 if (PrepIncludeStack.back()->empty())
1039 "empty control stack");
1041 auto &PrepControl = PrepIncludeStack.back()->back();
1042 PrintError(CurBuf.
end(),
"Reached EOF without matching #endif");
1043 PrintError(PrepControl.SrcPos,
"The latest preprocessor control is here");
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
StringRef getBuffer() const
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
const char * getPointer() const
Represents a range in source code.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
unsigned getMainFileID() const
const MemoryBuffer * getMemoryBuffer(unsigned i) const
SMLoc getParentIncludeLoc(unsigned i) const
unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
static constexpr size_t npos
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
std::pair< typename Base::iterator, bool > insert(StringRef key)
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
SMRange getLocRange() const
TGLexer(SourceMgr &SrcMgr, ArrayRef< std::string > Macros)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
support::ulittle32_t Word
This is an optimization pass for GlobalISel generic memory operations.
void PrintFatalError(const Twine &Msg)
void PrintError(const Twine &Msg)
void PrintWarning(const Twine &Msg)
auto reverse(ContainerTy &&C)