xref: /aosp_15_r20/external/llvm/lib/TableGen/TGLexer.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Implement the Lexer for TableGen.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "TGLexer.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSwitch.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Config/config.h" // for strtoull()/strtoll() define
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/SourceMgr.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/TableGen/Error.h"
21*9880d681SAndroid Build Coastguard Worker #include <cctype>
22*9880d681SAndroid Build Coastguard Worker #include <cerrno>
23*9880d681SAndroid Build Coastguard Worker #include <cstdio>
24*9880d681SAndroid Build Coastguard Worker #include <cstdlib>
25*9880d681SAndroid Build Coastguard Worker #include <cstring>
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker 
TGLexer(SourceMgr & SM)29*9880d681SAndroid Build Coastguard Worker TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
30*9880d681SAndroid Build Coastguard Worker   CurBuffer = SrcMgr.getMainFileID();
31*9880d681SAndroid Build Coastguard Worker   CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
32*9880d681SAndroid Build Coastguard Worker   CurPtr = CurBuf.begin();
33*9880d681SAndroid Build Coastguard Worker   TokStart = nullptr;
34*9880d681SAndroid Build Coastguard Worker }
35*9880d681SAndroid Build Coastguard Worker 
getLoc() const36*9880d681SAndroid Build Coastguard Worker SMLoc TGLexer::getLoc() const {
37*9880d681SAndroid Build Coastguard Worker   return SMLoc::getFromPointer(TokStart);
38*9880d681SAndroid Build Coastguard Worker }
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker /// ReturnError - Set the error to the specified string at the specified
41*9880d681SAndroid Build Coastguard Worker /// location.  This is defined to always return tgtok::Error.
ReturnError(const char * Loc,const Twine & Msg)42*9880d681SAndroid Build Coastguard Worker tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
43*9880d681SAndroid Build Coastguard Worker   PrintError(Loc, Msg);
44*9880d681SAndroid Build Coastguard Worker   return tgtok::Error;
45*9880d681SAndroid Build Coastguard Worker }
46*9880d681SAndroid Build Coastguard Worker 
getNextChar()47*9880d681SAndroid Build Coastguard Worker int TGLexer::getNextChar() {
48*9880d681SAndroid Build Coastguard Worker   char CurChar = *CurPtr++;
49*9880d681SAndroid Build Coastguard Worker   switch (CurChar) {
50*9880d681SAndroid Build Coastguard Worker   default:
51*9880d681SAndroid Build Coastguard Worker     return (unsigned char)CurChar;
52*9880d681SAndroid Build Coastguard Worker   case 0: {
53*9880d681SAndroid Build Coastguard Worker     // A nul character in the stream is either the end of the current buffer or
54*9880d681SAndroid Build Coastguard Worker     // a random nul in the file.  Disambiguate that here.
55*9880d681SAndroid Build Coastguard Worker     if (CurPtr-1 != CurBuf.end())
56*9880d681SAndroid Build Coastguard Worker       return 0;  // Just whitespace.
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker     // If this is the end of an included file, pop the parent file off the
59*9880d681SAndroid Build Coastguard Worker     // include stack.
60*9880d681SAndroid Build Coastguard Worker     SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
61*9880d681SAndroid Build Coastguard Worker     if (ParentIncludeLoc != SMLoc()) {
62*9880d681SAndroid Build Coastguard Worker       CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
63*9880d681SAndroid Build Coastguard Worker       CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
64*9880d681SAndroid Build Coastguard Worker       CurPtr = ParentIncludeLoc.getPointer();
65*9880d681SAndroid Build Coastguard Worker       return getNextChar();
66*9880d681SAndroid Build Coastguard Worker     }
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker     // Otherwise, return end of file.
69*9880d681SAndroid Build Coastguard Worker     --CurPtr;  // Another call to lex will return EOF again.
70*9880d681SAndroid Build Coastguard Worker     return EOF;
71*9880d681SAndroid Build Coastguard Worker   }
72*9880d681SAndroid Build Coastguard Worker   case '\n':
73*9880d681SAndroid Build Coastguard Worker   case '\r':
74*9880d681SAndroid Build Coastguard Worker     // Handle the newline character by ignoring it and incrementing the line
75*9880d681SAndroid Build Coastguard Worker     // count.  However, be careful about 'dos style' files with \n\r in them.
76*9880d681SAndroid Build Coastguard Worker     // Only treat a \n\r or \r\n as a single line.
77*9880d681SAndroid Build Coastguard Worker     if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
78*9880d681SAndroid Build Coastguard Worker         *CurPtr != CurChar)
79*9880d681SAndroid Build Coastguard Worker       ++CurPtr;  // Eat the two char newline sequence.
80*9880d681SAndroid Build Coastguard Worker     return '\n';
81*9880d681SAndroid Build Coastguard Worker   }
82*9880d681SAndroid Build Coastguard Worker }
83*9880d681SAndroid Build Coastguard Worker 
peekNextChar(int Index)84*9880d681SAndroid Build Coastguard Worker int TGLexer::peekNextChar(int Index) {
85*9880d681SAndroid Build Coastguard Worker   return *(CurPtr + Index);
86*9880d681SAndroid Build Coastguard Worker }
87*9880d681SAndroid Build Coastguard Worker 
LexToken()88*9880d681SAndroid Build Coastguard Worker tgtok::TokKind TGLexer::LexToken() {
89*9880d681SAndroid Build Coastguard Worker   TokStart = CurPtr;
90*9880d681SAndroid Build Coastguard Worker   // This always consumes at least one character.
91*9880d681SAndroid Build Coastguard Worker   int CurChar = getNextChar();
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker   switch (CurChar) {
94*9880d681SAndroid Build Coastguard Worker   default:
95*9880d681SAndroid Build Coastguard Worker     // Handle letters: [a-zA-Z_]
96*9880d681SAndroid Build Coastguard Worker     if (isalpha(CurChar) || CurChar == '_')
97*9880d681SAndroid Build Coastguard Worker       return LexIdentifier();
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker     // Unknown character, emit an error.
100*9880d681SAndroid Build Coastguard Worker     return ReturnError(TokStart, "Unexpected character");
101*9880d681SAndroid Build Coastguard Worker   case EOF: return tgtok::Eof;
102*9880d681SAndroid Build Coastguard Worker   case ':': return tgtok::colon;
103*9880d681SAndroid Build Coastguard Worker   case ';': return tgtok::semi;
104*9880d681SAndroid Build Coastguard Worker   case '.': return tgtok::period;
105*9880d681SAndroid Build Coastguard Worker   case ',': return tgtok::comma;
106*9880d681SAndroid Build Coastguard Worker   case '<': return tgtok::less;
107*9880d681SAndroid Build Coastguard Worker   case '>': return tgtok::greater;
108*9880d681SAndroid Build Coastguard Worker   case ']': return tgtok::r_square;
109*9880d681SAndroid Build Coastguard Worker   case '{': return tgtok::l_brace;
110*9880d681SAndroid Build Coastguard Worker   case '}': return tgtok::r_brace;
111*9880d681SAndroid Build Coastguard Worker   case '(': return tgtok::l_paren;
112*9880d681SAndroid Build Coastguard Worker   case ')': return tgtok::r_paren;
113*9880d681SAndroid Build Coastguard Worker   case '=': return tgtok::equal;
114*9880d681SAndroid Build Coastguard Worker   case '?': return tgtok::question;
115*9880d681SAndroid Build Coastguard Worker   case '#': return tgtok::paste;
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker   case 0:
118*9880d681SAndroid Build Coastguard Worker   case ' ':
119*9880d681SAndroid Build Coastguard Worker   case '\t':
120*9880d681SAndroid Build Coastguard Worker   case '\n':
121*9880d681SAndroid Build Coastguard Worker   case '\r':
122*9880d681SAndroid Build Coastguard Worker     // Ignore whitespace.
123*9880d681SAndroid Build Coastguard Worker     return LexToken();
124*9880d681SAndroid Build Coastguard Worker   case '/':
125*9880d681SAndroid Build Coastguard Worker     // If this is the start of a // comment, skip until the end of the line or
126*9880d681SAndroid Build Coastguard Worker     // the end of the buffer.
127*9880d681SAndroid Build Coastguard Worker     if (*CurPtr == '/')
128*9880d681SAndroid Build Coastguard Worker       SkipBCPLComment();
129*9880d681SAndroid Build Coastguard Worker     else if (*CurPtr == '*') {
130*9880d681SAndroid Build Coastguard Worker       if (SkipCComment())
131*9880d681SAndroid Build Coastguard Worker         return tgtok::Error;
132*9880d681SAndroid Build Coastguard Worker     } else // Otherwise, this is an error.
133*9880d681SAndroid Build Coastguard Worker       return ReturnError(TokStart, "Unexpected character");
134*9880d681SAndroid Build Coastguard Worker     return LexToken();
135*9880d681SAndroid Build Coastguard Worker   case '-': case '+':
136*9880d681SAndroid Build Coastguard Worker   case '0': case '1': case '2': case '3': case '4': case '5': case '6':
137*9880d681SAndroid Build Coastguard Worker   case '7': case '8': case '9': {
138*9880d681SAndroid Build Coastguard Worker     int NextChar = 0;
139*9880d681SAndroid Build Coastguard Worker     if (isdigit(CurChar)) {
140*9880d681SAndroid Build Coastguard Worker       // Allow identifiers to start with a number if it is followed by
141*9880d681SAndroid Build Coastguard Worker       // an identifier.  This can happen with paste operations like
142*9880d681SAndroid Build Coastguard Worker       // foo#8i.
143*9880d681SAndroid Build Coastguard Worker       int i = 0;
144*9880d681SAndroid Build Coastguard Worker       do {
145*9880d681SAndroid Build Coastguard Worker         NextChar = peekNextChar(i++);
146*9880d681SAndroid Build Coastguard Worker       } while (isdigit(NextChar));
147*9880d681SAndroid Build Coastguard Worker 
148*9880d681SAndroid Build Coastguard Worker       if (NextChar == 'x' || NextChar == 'b') {
149*9880d681SAndroid Build Coastguard Worker         // If this is [0-9]b[01] or [0-9]x[0-9A-fa-f] this is most
150*9880d681SAndroid Build Coastguard Worker         // likely a number.
151*9880d681SAndroid Build Coastguard Worker         int NextNextChar = peekNextChar(i);
152*9880d681SAndroid Build Coastguard Worker         switch (NextNextChar) {
153*9880d681SAndroid Build Coastguard Worker         default:
154*9880d681SAndroid Build Coastguard Worker           break;
155*9880d681SAndroid Build Coastguard Worker         case '0': case '1':
156*9880d681SAndroid Build Coastguard Worker           if (NextChar == 'b')
157*9880d681SAndroid Build Coastguard Worker             return LexNumber();
158*9880d681SAndroid Build Coastguard Worker           // Fallthrough
159*9880d681SAndroid Build Coastguard Worker         case '2': case '3': case '4': case '5':
160*9880d681SAndroid Build Coastguard Worker         case '6': case '7': case '8': case '9':
161*9880d681SAndroid Build Coastguard Worker         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
162*9880d681SAndroid Build Coastguard Worker         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
163*9880d681SAndroid Build Coastguard Worker           if (NextChar == 'x')
164*9880d681SAndroid Build Coastguard Worker             return LexNumber();
165*9880d681SAndroid Build Coastguard Worker           break;
166*9880d681SAndroid Build Coastguard Worker         }
167*9880d681SAndroid Build Coastguard Worker       }
168*9880d681SAndroid Build Coastguard Worker     }
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker     if (isalpha(NextChar) || NextChar == '_')
171*9880d681SAndroid Build Coastguard Worker       return LexIdentifier();
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker     return LexNumber();
174*9880d681SAndroid Build Coastguard Worker   }
175*9880d681SAndroid Build Coastguard Worker   case '"': return LexString();
176*9880d681SAndroid Build Coastguard Worker   case '$': return LexVarName();
177*9880d681SAndroid Build Coastguard Worker   case '[': return LexBracket();
178*9880d681SAndroid Build Coastguard Worker   case '!': return LexExclaim();
179*9880d681SAndroid Build Coastguard Worker   }
180*9880d681SAndroid Build Coastguard Worker }
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker /// LexString - Lex "[^"]*"
LexString()183*9880d681SAndroid Build Coastguard Worker tgtok::TokKind TGLexer::LexString() {
184*9880d681SAndroid Build Coastguard Worker   const char *StrStart = CurPtr;
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker   CurStrVal = "";
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker   while (*CurPtr != '"') {
189*9880d681SAndroid Build Coastguard Worker     // If we hit the end of the buffer, report an error.
190*9880d681SAndroid Build Coastguard Worker     if (*CurPtr == 0 && CurPtr == CurBuf.end())
191*9880d681SAndroid Build Coastguard Worker       return ReturnError(StrStart, "End of file in string literal");
192*9880d681SAndroid Build Coastguard Worker 
193*9880d681SAndroid Build Coastguard Worker     if (*CurPtr == '\n' || *CurPtr == '\r')
194*9880d681SAndroid Build Coastguard Worker       return ReturnError(StrStart, "End of line in string literal");
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker     if (*CurPtr != '\\') {
197*9880d681SAndroid Build Coastguard Worker       CurStrVal += *CurPtr++;
198*9880d681SAndroid Build Coastguard Worker       continue;
199*9880d681SAndroid Build Coastguard Worker     }
200*9880d681SAndroid Build Coastguard Worker 
201*9880d681SAndroid Build Coastguard Worker     ++CurPtr;
202*9880d681SAndroid Build Coastguard Worker 
203*9880d681SAndroid Build Coastguard Worker     switch (*CurPtr) {
204*9880d681SAndroid Build Coastguard Worker     case '\\': case '\'': case '"':
205*9880d681SAndroid Build Coastguard Worker       // These turn into their literal character.
206*9880d681SAndroid Build Coastguard Worker       CurStrVal += *CurPtr++;
207*9880d681SAndroid Build Coastguard Worker       break;
208*9880d681SAndroid Build Coastguard Worker     case 't':
209*9880d681SAndroid Build Coastguard Worker       CurStrVal += '\t';
210*9880d681SAndroid Build Coastguard Worker       ++CurPtr;
211*9880d681SAndroid Build Coastguard Worker       break;
212*9880d681SAndroid Build Coastguard Worker     case 'n':
213*9880d681SAndroid Build Coastguard Worker       CurStrVal += '\n';
214*9880d681SAndroid Build Coastguard Worker       ++CurPtr;
215*9880d681SAndroid Build Coastguard Worker       break;
216*9880d681SAndroid Build Coastguard Worker 
217*9880d681SAndroid Build Coastguard Worker     case '\n':
218*9880d681SAndroid Build Coastguard Worker     case '\r':
219*9880d681SAndroid Build Coastguard Worker       return ReturnError(CurPtr, "escaped newlines not supported in tblgen");
220*9880d681SAndroid Build Coastguard Worker 
221*9880d681SAndroid Build Coastguard Worker     // If we hit the end of the buffer, report an error.
222*9880d681SAndroid Build Coastguard Worker     case '\0':
223*9880d681SAndroid Build Coastguard Worker       if (CurPtr == CurBuf.end())
224*9880d681SAndroid Build Coastguard Worker         return ReturnError(StrStart, "End of file in string literal");
225*9880d681SAndroid Build Coastguard Worker       // FALL THROUGH
226*9880d681SAndroid Build Coastguard Worker     default:
227*9880d681SAndroid Build Coastguard Worker       return ReturnError(CurPtr, "invalid escape in string literal");
228*9880d681SAndroid Build Coastguard Worker     }
229*9880d681SAndroid Build Coastguard Worker   }
230*9880d681SAndroid Build Coastguard Worker 
231*9880d681SAndroid Build Coastguard Worker   ++CurPtr;
232*9880d681SAndroid Build Coastguard Worker   return tgtok::StrVal;
233*9880d681SAndroid Build Coastguard Worker }
234*9880d681SAndroid Build Coastguard Worker 
LexVarName()235*9880d681SAndroid Build Coastguard Worker tgtok::TokKind TGLexer::LexVarName() {
236*9880d681SAndroid Build Coastguard Worker   if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
237*9880d681SAndroid Build Coastguard Worker     return ReturnError(TokStart, "Invalid variable name");
238*9880d681SAndroid Build Coastguard Worker 
239*9880d681SAndroid Build Coastguard Worker   // Otherwise, we're ok, consume the rest of the characters.
240*9880d681SAndroid Build Coastguard Worker   const char *VarNameStart = CurPtr++;
241*9880d681SAndroid Build Coastguard Worker 
242*9880d681SAndroid Build Coastguard Worker   while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
243*9880d681SAndroid Build Coastguard Worker     ++CurPtr;
244*9880d681SAndroid Build Coastguard Worker 
245*9880d681SAndroid Build Coastguard Worker   CurStrVal.assign(VarNameStart, CurPtr);
246*9880d681SAndroid Build Coastguard Worker   return tgtok::VarName;
247*9880d681SAndroid Build Coastguard Worker }
248*9880d681SAndroid Build Coastguard Worker 
249*9880d681SAndroid Build Coastguard Worker 
LexIdentifier()250*9880d681SAndroid Build Coastguard Worker tgtok::TokKind TGLexer::LexIdentifier() {
251*9880d681SAndroid Build Coastguard Worker   // The first letter is [a-zA-Z_#].
252*9880d681SAndroid Build Coastguard Worker   const char *IdentStart = TokStart;
253*9880d681SAndroid Build Coastguard Worker 
254*9880d681SAndroid Build Coastguard Worker   // Match the rest of the identifier regex: [0-9a-zA-Z_#]*
255*9880d681SAndroid Build Coastguard Worker   while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
256*9880d681SAndroid Build Coastguard Worker     ++CurPtr;
257*9880d681SAndroid Build Coastguard Worker 
258*9880d681SAndroid Build Coastguard Worker   // Check to see if this identifier is a keyword.
259*9880d681SAndroid Build Coastguard Worker   StringRef Str(IdentStart, CurPtr-IdentStart);
260*9880d681SAndroid Build Coastguard Worker 
261*9880d681SAndroid Build Coastguard Worker   if (Str == "include") {
262*9880d681SAndroid Build Coastguard Worker     if (LexInclude()) return tgtok::Error;
263*9880d681SAndroid Build Coastguard Worker     return Lex();
264*9880d681SAndroid Build Coastguard Worker   }
265*9880d681SAndroid Build Coastguard Worker 
266*9880d681SAndroid Build Coastguard Worker   tgtok::TokKind Kind = StringSwitch<tgtok::TokKind>(Str)
267*9880d681SAndroid Build Coastguard Worker     .Case("int", tgtok::Int)
268*9880d681SAndroid Build Coastguard Worker     .Case("bit", tgtok::Bit)
269*9880d681SAndroid Build Coastguard Worker     .Case("bits", tgtok::Bits)
270*9880d681SAndroid Build Coastguard Worker     .Case("string", tgtok::String)
271*9880d681SAndroid Build Coastguard Worker     .Case("list", tgtok::List)
272*9880d681SAndroid Build Coastguard Worker     .Case("code", tgtok::Code)
273*9880d681SAndroid Build Coastguard Worker     .Case("dag", tgtok::Dag)
274*9880d681SAndroid Build Coastguard Worker     .Case("class", tgtok::Class)
275*9880d681SAndroid Build Coastguard Worker     .Case("def", tgtok::Def)
276*9880d681SAndroid Build Coastguard Worker     .Case("foreach", tgtok::Foreach)
277*9880d681SAndroid Build Coastguard Worker     .Case("defm", tgtok::Defm)
278*9880d681SAndroid Build Coastguard Worker     .Case("multiclass", tgtok::MultiClass)
279*9880d681SAndroid Build Coastguard Worker     .Case("field", tgtok::Field)
280*9880d681SAndroid Build Coastguard Worker     .Case("let", tgtok::Let)
281*9880d681SAndroid Build Coastguard Worker     .Case("in", tgtok::In)
282*9880d681SAndroid Build Coastguard Worker     .Default(tgtok::Id);
283*9880d681SAndroid Build Coastguard Worker 
284*9880d681SAndroid Build Coastguard Worker   if (Kind == tgtok::Id)
285*9880d681SAndroid Build Coastguard Worker     CurStrVal.assign(Str.begin(), Str.end());
286*9880d681SAndroid Build Coastguard Worker   return Kind;
287*9880d681SAndroid Build Coastguard Worker }
288*9880d681SAndroid Build Coastguard Worker 
289*9880d681SAndroid Build Coastguard Worker /// LexInclude - We just read the "include" token.  Get the string token that
290*9880d681SAndroid Build Coastguard Worker /// comes next and enter the include.
LexInclude()291*9880d681SAndroid Build Coastguard Worker bool TGLexer::LexInclude() {
292*9880d681SAndroid Build Coastguard Worker   // The token after the include must be a string.
293*9880d681SAndroid Build Coastguard Worker   tgtok::TokKind Tok = LexToken();
294*9880d681SAndroid Build Coastguard Worker   if (Tok == tgtok::Error) return true;
295*9880d681SAndroid Build Coastguard Worker   if (Tok != tgtok::StrVal) {
296*9880d681SAndroid Build Coastguard Worker     PrintError(getLoc(), "Expected filename after include");
297*9880d681SAndroid Build Coastguard Worker     return true;
298*9880d681SAndroid Build Coastguard Worker   }
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker   // Get the string.
301*9880d681SAndroid Build Coastguard Worker   std::string Filename = CurStrVal;
302*9880d681SAndroid Build Coastguard Worker   std::string IncludedFile;
303*9880d681SAndroid Build Coastguard Worker 
304*9880d681SAndroid Build Coastguard Worker 
305*9880d681SAndroid Build Coastguard Worker   CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr),
306*9880d681SAndroid Build Coastguard Worker                                     IncludedFile);
307*9880d681SAndroid Build Coastguard Worker   if (!CurBuffer) {
308*9880d681SAndroid Build Coastguard Worker     PrintError(getLoc(), "Could not find include file '" + Filename + "'");
309*9880d681SAndroid Build Coastguard Worker     return true;
310*9880d681SAndroid Build Coastguard Worker   }
311*9880d681SAndroid Build Coastguard Worker 
312*9880d681SAndroid Build Coastguard Worker   DependenciesMapTy::const_iterator Found = Dependencies.find(IncludedFile);
313*9880d681SAndroid Build Coastguard Worker   if (Found != Dependencies.end()) {
314*9880d681SAndroid Build Coastguard Worker     PrintError(getLoc(),
315*9880d681SAndroid Build Coastguard Worker                "File '" + IncludedFile + "' has already been included.");
316*9880d681SAndroid Build Coastguard Worker     SrcMgr.PrintMessage(Found->second, SourceMgr::DK_Note,
317*9880d681SAndroid Build Coastguard Worker                         "previously included here");
318*9880d681SAndroid Build Coastguard Worker     return true;
319*9880d681SAndroid Build Coastguard Worker   }
320*9880d681SAndroid Build Coastguard Worker   Dependencies.insert(std::make_pair(IncludedFile, getLoc()));
321*9880d681SAndroid Build Coastguard Worker   // Save the line number and lex buffer of the includer.
322*9880d681SAndroid Build Coastguard Worker   CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
323*9880d681SAndroid Build Coastguard Worker   CurPtr = CurBuf.begin();
324*9880d681SAndroid Build Coastguard Worker   return false;
325*9880d681SAndroid Build Coastguard Worker }
326*9880d681SAndroid Build Coastguard Worker 
SkipBCPLComment()327*9880d681SAndroid Build Coastguard Worker void TGLexer::SkipBCPLComment() {
328*9880d681SAndroid Build Coastguard Worker   ++CurPtr;  // skip the second slash.
329*9880d681SAndroid Build Coastguard Worker   while (1) {
330*9880d681SAndroid Build Coastguard Worker     switch (*CurPtr) {
331*9880d681SAndroid Build Coastguard Worker     case '\n':
332*9880d681SAndroid Build Coastguard Worker     case '\r':
333*9880d681SAndroid Build Coastguard Worker       return;  // Newline is end of comment.
334*9880d681SAndroid Build Coastguard Worker     case 0:
335*9880d681SAndroid Build Coastguard Worker       // If this is the end of the buffer, end the comment.
336*9880d681SAndroid Build Coastguard Worker       if (CurPtr == CurBuf.end())
337*9880d681SAndroid Build Coastguard Worker         return;
338*9880d681SAndroid Build Coastguard Worker       break;
339*9880d681SAndroid Build Coastguard Worker     }
340*9880d681SAndroid Build Coastguard Worker     // Otherwise, skip the character.
341*9880d681SAndroid Build Coastguard Worker     ++CurPtr;
342*9880d681SAndroid Build Coastguard Worker   }
343*9880d681SAndroid Build Coastguard Worker }
344*9880d681SAndroid Build Coastguard Worker 
345*9880d681SAndroid Build Coastguard Worker /// SkipCComment - This skips C-style /**/ comments.  The only difference from C
346*9880d681SAndroid Build Coastguard Worker /// is that we allow nesting.
SkipCComment()347*9880d681SAndroid Build Coastguard Worker bool TGLexer::SkipCComment() {
348*9880d681SAndroid Build Coastguard Worker   ++CurPtr;  // skip the star.
349*9880d681SAndroid Build Coastguard Worker   unsigned CommentDepth = 1;
350*9880d681SAndroid Build Coastguard Worker 
351*9880d681SAndroid Build Coastguard Worker   while (1) {
352*9880d681SAndroid Build Coastguard Worker     int CurChar = getNextChar();
353*9880d681SAndroid Build Coastguard Worker     switch (CurChar) {
354*9880d681SAndroid Build Coastguard Worker     case EOF:
355*9880d681SAndroid Build Coastguard Worker       PrintError(TokStart, "Unterminated comment!");
356*9880d681SAndroid Build Coastguard Worker       return true;
357*9880d681SAndroid Build Coastguard Worker     case '*':
358*9880d681SAndroid Build Coastguard Worker       // End of the comment?
359*9880d681SAndroid Build Coastguard Worker       if (CurPtr[0] != '/') break;
360*9880d681SAndroid Build Coastguard Worker 
361*9880d681SAndroid Build Coastguard Worker       ++CurPtr;   // End the */.
362*9880d681SAndroid Build Coastguard Worker       if (--CommentDepth == 0)
363*9880d681SAndroid Build Coastguard Worker         return false;
364*9880d681SAndroid Build Coastguard Worker       break;
365*9880d681SAndroid Build Coastguard Worker     case '/':
366*9880d681SAndroid Build Coastguard Worker       // Start of a nested comment?
367*9880d681SAndroid Build Coastguard Worker       if (CurPtr[0] != '*') break;
368*9880d681SAndroid Build Coastguard Worker       ++CurPtr;
369*9880d681SAndroid Build Coastguard Worker       ++CommentDepth;
370*9880d681SAndroid Build Coastguard Worker       break;
371*9880d681SAndroid Build Coastguard Worker     }
372*9880d681SAndroid Build Coastguard Worker   }
373*9880d681SAndroid Build Coastguard Worker }
374*9880d681SAndroid Build Coastguard Worker 
375*9880d681SAndroid Build Coastguard Worker /// LexNumber - Lex:
376*9880d681SAndroid Build Coastguard Worker ///    [-+]?[0-9]+
377*9880d681SAndroid Build Coastguard Worker ///    0x[0-9a-fA-F]+
378*9880d681SAndroid Build Coastguard Worker ///    0b[01]+
LexNumber()379*9880d681SAndroid Build Coastguard Worker tgtok::TokKind TGLexer::LexNumber() {
380*9880d681SAndroid Build Coastguard Worker   if (CurPtr[-1] == '0') {
381*9880d681SAndroid Build Coastguard Worker     if (CurPtr[0] == 'x') {
382*9880d681SAndroid Build Coastguard Worker       ++CurPtr;
383*9880d681SAndroid Build Coastguard Worker       const char *NumStart = CurPtr;
384*9880d681SAndroid Build Coastguard Worker       while (isxdigit(CurPtr[0]))
385*9880d681SAndroid Build Coastguard Worker         ++CurPtr;
386*9880d681SAndroid Build Coastguard Worker 
387*9880d681SAndroid Build Coastguard Worker       // Requires at least one hex digit.
388*9880d681SAndroid Build Coastguard Worker       if (CurPtr == NumStart)
389*9880d681SAndroid Build Coastguard Worker         return ReturnError(TokStart, "Invalid hexadecimal number");
390*9880d681SAndroid Build Coastguard Worker 
391*9880d681SAndroid Build Coastguard Worker       errno = 0;
392*9880d681SAndroid Build Coastguard Worker       CurIntVal = strtoll(NumStart, nullptr, 16);
393*9880d681SAndroid Build Coastguard Worker       if (errno == EINVAL)
394*9880d681SAndroid Build Coastguard Worker         return ReturnError(TokStart, "Invalid hexadecimal number");
395*9880d681SAndroid Build Coastguard Worker       if (errno == ERANGE) {
396*9880d681SAndroid Build Coastguard Worker         errno = 0;
397*9880d681SAndroid Build Coastguard Worker         CurIntVal = (int64_t)strtoull(NumStart, nullptr, 16);
398*9880d681SAndroid Build Coastguard Worker         if (errno == EINVAL)
399*9880d681SAndroid Build Coastguard Worker           return ReturnError(TokStart, "Invalid hexadecimal number");
400*9880d681SAndroid Build Coastguard Worker         if (errno == ERANGE)
401*9880d681SAndroid Build Coastguard Worker           return ReturnError(TokStart, "Hexadecimal number out of range");
402*9880d681SAndroid Build Coastguard Worker       }
403*9880d681SAndroid Build Coastguard Worker       return tgtok::IntVal;
404*9880d681SAndroid Build Coastguard Worker     } else if (CurPtr[0] == 'b') {
405*9880d681SAndroid Build Coastguard Worker       ++CurPtr;
406*9880d681SAndroid Build Coastguard Worker       const char *NumStart = CurPtr;
407*9880d681SAndroid Build Coastguard Worker       while (CurPtr[0] == '0' || CurPtr[0] == '1')
408*9880d681SAndroid Build Coastguard Worker         ++CurPtr;
409*9880d681SAndroid Build Coastguard Worker 
410*9880d681SAndroid Build Coastguard Worker       // Requires at least one binary digit.
411*9880d681SAndroid Build Coastguard Worker       if (CurPtr == NumStart)
412*9880d681SAndroid Build Coastguard Worker         return ReturnError(CurPtr-2, "Invalid binary number");
413*9880d681SAndroid Build Coastguard Worker       CurIntVal = strtoll(NumStart, nullptr, 2);
414*9880d681SAndroid Build Coastguard Worker       return tgtok::BinaryIntVal;
415*9880d681SAndroid Build Coastguard Worker     }
416*9880d681SAndroid Build Coastguard Worker   }
417*9880d681SAndroid Build Coastguard Worker 
418*9880d681SAndroid Build Coastguard Worker   // Check for a sign without a digit.
419*9880d681SAndroid Build Coastguard Worker   if (!isdigit(CurPtr[0])) {
420*9880d681SAndroid Build Coastguard Worker     if (CurPtr[-1] == '-')
421*9880d681SAndroid Build Coastguard Worker       return tgtok::minus;
422*9880d681SAndroid Build Coastguard Worker     else if (CurPtr[-1] == '+')
423*9880d681SAndroid Build Coastguard Worker       return tgtok::plus;
424*9880d681SAndroid Build Coastguard Worker   }
425*9880d681SAndroid Build Coastguard Worker 
426*9880d681SAndroid Build Coastguard Worker   while (isdigit(CurPtr[0]))
427*9880d681SAndroid Build Coastguard Worker     ++CurPtr;
428*9880d681SAndroid Build Coastguard Worker   CurIntVal = strtoll(TokStart, nullptr, 10);
429*9880d681SAndroid Build Coastguard Worker   return tgtok::IntVal;
430*9880d681SAndroid Build Coastguard Worker }
431*9880d681SAndroid Build Coastguard Worker 
432*9880d681SAndroid Build Coastguard Worker /// LexBracket - We just read '['.  If this is a code block, return it,
433*9880d681SAndroid Build Coastguard Worker /// otherwise return the bracket.  Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
LexBracket()434*9880d681SAndroid Build Coastguard Worker tgtok::TokKind TGLexer::LexBracket() {
435*9880d681SAndroid Build Coastguard Worker   if (CurPtr[0] != '{')
436*9880d681SAndroid Build Coastguard Worker     return tgtok::l_square;
437*9880d681SAndroid Build Coastguard Worker   ++CurPtr;
438*9880d681SAndroid Build Coastguard Worker   const char *CodeStart = CurPtr;
439*9880d681SAndroid Build Coastguard Worker   while (1) {
440*9880d681SAndroid Build Coastguard Worker     int Char = getNextChar();
441*9880d681SAndroid Build Coastguard Worker     if (Char == EOF) break;
442*9880d681SAndroid Build Coastguard Worker 
443*9880d681SAndroid Build Coastguard Worker     if (Char != '}') continue;
444*9880d681SAndroid Build Coastguard Worker 
445*9880d681SAndroid Build Coastguard Worker     Char = getNextChar();
446*9880d681SAndroid Build Coastguard Worker     if (Char == EOF) break;
447*9880d681SAndroid Build Coastguard Worker     if (Char == ']') {
448*9880d681SAndroid Build Coastguard Worker       CurStrVal.assign(CodeStart, CurPtr-2);
449*9880d681SAndroid Build Coastguard Worker       return tgtok::CodeFragment;
450*9880d681SAndroid Build Coastguard Worker     }
451*9880d681SAndroid Build Coastguard Worker   }
452*9880d681SAndroid Build Coastguard Worker 
453*9880d681SAndroid Build Coastguard Worker   return ReturnError(CodeStart-2, "Unterminated Code Block");
454*9880d681SAndroid Build Coastguard Worker }
455*9880d681SAndroid Build Coastguard Worker 
456*9880d681SAndroid Build Coastguard Worker /// LexExclaim - Lex '!' and '![a-zA-Z]+'.
LexExclaim()457*9880d681SAndroid Build Coastguard Worker tgtok::TokKind TGLexer::LexExclaim() {
458*9880d681SAndroid Build Coastguard Worker   if (!isalpha(*CurPtr))
459*9880d681SAndroid Build Coastguard Worker     return ReturnError(CurPtr - 1, "Invalid \"!operator\"");
460*9880d681SAndroid Build Coastguard Worker 
461*9880d681SAndroid Build Coastguard Worker   const char *Start = CurPtr++;
462*9880d681SAndroid Build Coastguard Worker   while (isalpha(*CurPtr))
463*9880d681SAndroid Build Coastguard Worker     ++CurPtr;
464*9880d681SAndroid Build Coastguard Worker 
465*9880d681SAndroid Build Coastguard Worker   // Check to see which operator this is.
466*9880d681SAndroid Build Coastguard Worker   tgtok::TokKind Kind =
467*9880d681SAndroid Build Coastguard Worker     StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
468*9880d681SAndroid Build Coastguard Worker     .Case("eq", tgtok::XEq)
469*9880d681SAndroid Build Coastguard Worker     .Case("if", tgtok::XIf)
470*9880d681SAndroid Build Coastguard Worker     .Case("head", tgtok::XHead)
471*9880d681SAndroid Build Coastguard Worker     .Case("tail", tgtok::XTail)
472*9880d681SAndroid Build Coastguard Worker     .Case("con", tgtok::XConcat)
473*9880d681SAndroid Build Coastguard Worker     .Case("add", tgtok::XADD)
474*9880d681SAndroid Build Coastguard Worker     .Case("and", tgtok::XAND)
475*9880d681SAndroid Build Coastguard Worker     .Case("shl", tgtok::XSHL)
476*9880d681SAndroid Build Coastguard Worker     .Case("sra", tgtok::XSRA)
477*9880d681SAndroid Build Coastguard Worker     .Case("srl", tgtok::XSRL)
478*9880d681SAndroid Build Coastguard Worker     .Case("cast", tgtok::XCast)
479*9880d681SAndroid Build Coastguard Worker     .Case("empty", tgtok::XEmpty)
480*9880d681SAndroid Build Coastguard Worker     .Case("subst", tgtok::XSubst)
481*9880d681SAndroid Build Coastguard Worker     .Case("foreach", tgtok::XForEach)
482*9880d681SAndroid Build Coastguard Worker     .Case("listconcat", tgtok::XListConcat)
483*9880d681SAndroid Build Coastguard Worker     .Case("strconcat", tgtok::XStrConcat)
484*9880d681SAndroid Build Coastguard Worker     .Default(tgtok::Error);
485*9880d681SAndroid Build Coastguard Worker 
486*9880d681SAndroid Build Coastguard Worker   return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator");
487*9880d681SAndroid Build Coastguard Worker }
488*9880d681SAndroid Build Coastguard Worker 
489