blob: c6be4f8a118937ac68250ebb033f73c0df76a4ba [file] [log] [blame]
Chris Lattnera8058742007-11-18 02:57:27 +00001//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner30609102007-12-29 20:37:13 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Chris Lattnera8058742007-11-18 02:57:27 +00007//
8//===----------------------------------------------------------------------===//
9//
10// Implement the Lexer for TableGen.
11//
12//===----------------------------------------------------------------------===//
13
Chris Lattner6aaca042007-11-18 05:25:45 +000014#include "TGLexer.h"
Bill Wendlingcd466f52010-12-08 20:02:49 +000015#include "llvm/ADT/StringSwitch.h"
16#include "llvm/ADT/Twine.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000017#include "llvm/Config/config.h" // for strtoull()/strtoll() define
18#include "llvm/Support/MemoryBuffer.h"
19#include "llvm/Support/SourceMgr.h"
20#include "llvm/TableGen/Error.h"
Chris Lattnera8058742007-11-18 02:57:27 +000021#include <cctype>
Chandler Carruthd04a8d42012-12-03 16:50:05 +000022#include <cerrno>
Duncan Sands4520dd22008-10-08 07:23:46 +000023#include <cstdio>
Anton Korobeynikovae9f3a32008-02-20 11:08:44 +000024#include <cstdlib>
25#include <cstring>
Dylan Noblesmith8cc300c2011-12-22 23:08:39 +000026
Chris Lattnera8058742007-11-18 02:57:27 +000027using namespace llvm;
28
Chris Lattner8070ea32009-06-21 03:41:50 +000029TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
Chris Lattneraa739d22009-03-13 07:05:43 +000030 CurBuffer = 0;
31 CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
Chris Lattnera8058742007-11-18 02:57:27 +000032 CurPtr = CurBuf->getBufferStart();
Chris Lattner56a9fcf2007-11-19 07:43:52 +000033 TokStart = 0;
Chris Lattnera8058742007-11-18 02:57:27 +000034}
35
Chris Lattner1e3a8a42009-06-21 03:39:35 +000036SMLoc TGLexer::getLoc() const {
37 return SMLoc::getFromPointer(TokStart);
Chris Lattner1c8ae592009-03-13 16:01:53 +000038}
39
Chris Lattnerc8a9bbc2007-11-19 07:38:58 +000040/// ReturnError - Set the error to the specified string at the specified
Chris Lattnerf4601652007-11-22 20:49:04 +000041/// location. This is defined to always return tgtok::Error.
Benjamin Kramerd1e17032010-09-27 17:42:11 +000042tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
Chris Lattnerc8a9bbc2007-11-19 07:38:58 +000043 PrintError(Loc, Msg);
Chris Lattnerf4601652007-11-22 20:49:04 +000044 return tgtok::Error;
Chris Lattnerc8a9bbc2007-11-19 07:38:58 +000045}
Chris Lattnera8058742007-11-18 02:57:27 +000046
Chris Lattnera8058742007-11-18 02:57:27 +000047int TGLexer::getNextChar() {
48 char CurChar = *CurPtr++;
49 switch (CurChar) {
50 default:
Chris Lattnerc1819182007-11-18 05:48:46 +000051 return (unsigned char)CurChar;
Chris Lattneraa739d22009-03-13 07:05:43 +000052 case 0: {
Chris Lattnera8058742007-11-18 02:57:27 +000053 // A nul character in the stream is either the end of the current buffer or
54 // a random nul in the file. Disambiguate that here.
55 if (CurPtr-1 != CurBuf->getBufferEnd())
56 return 0; // Just whitespace.
57
58 // If this is the end of an included file, pop the parent file off the
59 // include stack.
Chris Lattner1e3a8a42009-06-21 03:39:35 +000060 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
61 if (ParentIncludeLoc != SMLoc()) {
Chris Lattneraa739d22009-03-13 07:05:43 +000062 CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
63 CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
Chris Lattner1c8ae592009-03-13 16:01:53 +000064 CurPtr = ParentIncludeLoc.getPointer();
Chris Lattnera8058742007-11-18 02:57:27 +000065 return getNextChar();
66 }
67
68 // Otherwise, return end of file.
69 --CurPtr; // Another call to lex will return EOF again.
70 return EOF;
Chris Lattneraa739d22009-03-13 07:05:43 +000071 }
Chris Lattnera8058742007-11-18 02:57:27 +000072 case '\n':
73 case '\r':
74 // Handle the newline character by ignoring it and incrementing the line
75 // count. However, be careful about 'dos style' files with \n\r in them.
76 // Only treat a \n\r or \r\n as a single line.
77 if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
78 *CurPtr != CurChar)
Chris Lattnerc1819182007-11-18 05:48:46 +000079 ++CurPtr; // Eat the two char newline sequence.
Chris Lattnera8058742007-11-18 02:57:27 +000080 return '\n';
81 }
82}
83
David Greenea761f922011-10-19 13:03:35 +000084int TGLexer::peekNextChar(int Index) {
85 return *(CurPtr + Index);
86}
87
Chris Lattnerf4601652007-11-22 20:49:04 +000088tgtok::TokKind TGLexer::LexToken() {
Chris Lattner56a9fcf2007-11-19 07:43:52 +000089 TokStart = CurPtr;
Chris Lattnera8058742007-11-18 02:57:27 +000090 // This always consumes at least one character.
91 int CurChar = getNextChar();
92
93 switch (CurChar) {
94 default:
David Greened3d1cad2011-10-19 13:04:43 +000095 // Handle letters: [a-zA-Z_]
96 if (isalpha(CurChar) || CurChar == '_')
Chris Lattnera8058742007-11-18 02:57:27 +000097 return LexIdentifier();
David Greened3d1cad2011-10-19 13:04:43 +000098
Chris Lattnerf4601652007-11-22 20:49:04 +000099 // Unknown character, emit an error.
100 return ReturnError(TokStart, "Unexpected character");
101 case EOF: return tgtok::Eof;
102 case ':': return tgtok::colon;
103 case ';': return tgtok::semi;
104 case '.': return tgtok::period;
105 case ',': return tgtok::comma;
106 case '<': return tgtok::less;
107 case '>': return tgtok::greater;
108 case ']': return tgtok::r_square;
109 case '{': return tgtok::l_brace;
110 case '}': return tgtok::r_brace;
111 case '(': return tgtok::l_paren;
112 case ')': return tgtok::r_paren;
113 case '=': return tgtok::equal;
114 case '?': return tgtok::question;
David Greened3d1cad2011-10-19 13:04:43 +0000115 case '#': return tgtok::paste;
Chris Lattnerf4601652007-11-22 20:49:04 +0000116
Chris Lattnera8058742007-11-18 02:57:27 +0000117 case 0:
118 case ' ':
119 case '\t':
120 case '\n':
121 case '\r':
122 // Ignore whitespace.
123 return LexToken();
124 case '/':
125 // If this is the start of a // comment, skip until the end of the line or
126 // the end of the buffer.
127 if (*CurPtr == '/')
128 SkipBCPLComment();
129 else if (*CurPtr == '*') {
130 if (SkipCComment())
Chris Lattnerf4601652007-11-22 20:49:04 +0000131 return tgtok::Error;
132 } else // Otherwise, this is an error.
133 return ReturnError(TokStart, "Unexpected character");
Chris Lattnera8058742007-11-18 02:57:27 +0000134 return LexToken();
135 case '-': case '+':
136 case '0': case '1': case '2': case '3': case '4': case '5': case '6':
David Greene7efe9362011-10-19 13:03:39 +0000137 case '7': case '8': case '9': {
138 int NextChar = 0;
139 if (isdigit(CurChar)) {
140 // Allow identifiers to start with a number if it is followed by
141 // an identifier. This can happen with paste operations like
142 // foo#8i.
143 int i = 0;
144 do {
145 NextChar = peekNextChar(i++);
146 } while (isdigit(NextChar));
147
148 if (NextChar == 'x' || NextChar == 'b') {
149 // If this is [0-9]b[01] or [0-9]x[0-9A-fa-f] this is most
150 // likely a number.
151 int NextNextChar = peekNextChar(i);
152 switch (NextNextChar) {
153 default:
154 break;
155 case '0': case '1':
156 if (NextChar == 'b')
157 return LexNumber();
158 // Fallthrough
159 case '2': case '3': case '4': case '5':
160 case '6': case '7': case '8': case '9':
161 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
162 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
163 if (NextChar == 'x')
164 return LexNumber();
165 break;
166 }
167 }
168 }
169
170 if (isalpha(NextChar) || NextChar == '_')
171 return LexIdentifier();
172
Chris Lattnera8058742007-11-18 02:57:27 +0000173 return LexNumber();
David Greene7efe9362011-10-19 13:03:39 +0000174 }
Chris Lattnera8058742007-11-18 02:57:27 +0000175 case '"': return LexString();
176 case '$': return LexVarName();
177 case '[': return LexBracket();
178 case '!': return LexExclaim();
179 }
180}
181
182/// LexString - Lex "[^"]*"
Chris Lattnerf4601652007-11-22 20:49:04 +0000183tgtok::TokKind TGLexer::LexString() {
Chris Lattnera8058742007-11-18 02:57:27 +0000184 const char *StrStart = CurPtr;
185
Chris Lattnerea9f4df2009-03-13 21:03:27 +0000186 CurStrVal = "";
187
Chris Lattnera8058742007-11-18 02:57:27 +0000188 while (*CurPtr != '"') {
189 // If we hit the end of the buffer, report an error.
Chris Lattnerc8a9bbc2007-11-19 07:38:58 +0000190 if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
191 return ReturnError(StrStart, "End of file in string literal");
192
193 if (*CurPtr == '\n' || *CurPtr == '\r')
194 return ReturnError(StrStart, "End of line in string literal");
Chris Lattnera8058742007-11-18 02:57:27 +0000195
Chris Lattnerea9f4df2009-03-13 21:03:27 +0000196 if (*CurPtr != '\\') {
197 CurStrVal += *CurPtr++;
198 continue;
199 }
200
Chris Lattnera8058742007-11-18 02:57:27 +0000201 ++CurPtr;
Chris Lattnerea9f4df2009-03-13 21:03:27 +0000202
203 switch (*CurPtr) {
204 case '\\': case '\'': case '"':
205 // These turn into their literal character.
206 CurStrVal += *CurPtr++;
207 break;
Chris Lattnere023bb62009-03-13 21:23:43 +0000208 case 't':
Chris Lattner7f3b28a2009-03-13 21:33:17 +0000209 CurStrVal += '\t';
Chris Lattnere023bb62009-03-13 21:23:43 +0000210 ++CurPtr;
211 break;
212 case 'n':
Chris Lattner7f3b28a2009-03-13 21:33:17 +0000213 CurStrVal += '\n';
Chris Lattnere023bb62009-03-13 21:23:43 +0000214 ++CurPtr;
215 break;
216
Chris Lattnerea9f4df2009-03-13 21:03:27 +0000217 case '\n':
218 case '\r':
219 return ReturnError(CurPtr, "escaped newlines not supported in tblgen");
220
221 // If we hit the end of the buffer, report an error.
222 case '\0':
223 if (CurPtr == CurBuf->getBufferEnd())
224 return ReturnError(StrStart, "End of file in string literal");
225 // FALL THROUGH
226 default:
227 return ReturnError(CurPtr, "invalid escape in string literal");
228 }
Chris Lattnera8058742007-11-18 02:57:27 +0000229 }
230
Chris Lattnera8058742007-11-18 02:57:27 +0000231 ++CurPtr;
Chris Lattnerf4601652007-11-22 20:49:04 +0000232 return tgtok::StrVal;
Chris Lattnera8058742007-11-18 02:57:27 +0000233}
234
Chris Lattnerf4601652007-11-22 20:49:04 +0000235tgtok::TokKind TGLexer::LexVarName() {
Chris Lattnera8058742007-11-18 02:57:27 +0000236 if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
Chris Lattnerf4601652007-11-22 20:49:04 +0000237 return ReturnError(TokStart, "Invalid variable name");
Chris Lattnera8058742007-11-18 02:57:27 +0000238
239 // Otherwise, we're ok, consume the rest of the characters.
240 const char *VarNameStart = CurPtr++;
241
242 while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
243 ++CurPtr;
244
Chris Lattnerf4601652007-11-22 20:49:04 +0000245 CurStrVal.assign(VarNameStart, CurPtr);
246 return tgtok::VarName;
Chris Lattnera8058742007-11-18 02:57:27 +0000247}
248
249
Chris Lattnerf4601652007-11-22 20:49:04 +0000250tgtok::TokKind TGLexer::LexIdentifier() {
Chris Lattnerc2b08752010-10-05 22:59:29 +0000251 // The first letter is [a-zA-Z_#].
Chris Lattnerf4601652007-11-22 20:49:04 +0000252 const char *IdentStart = TokStart;
Benjamin Kramer37d42af2011-10-06 18:23:56 +0000253
Chris Lattnerc2b08752010-10-05 22:59:29 +0000254 // Match the rest of the identifier regex: [0-9a-zA-Z_#]*
David Greened3d1cad2011-10-19 13:04:43 +0000255 while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
Chris Lattnerc2b08752010-10-05 22:59:29 +0000256 ++CurPtr;
Benjamin Kramer37d42af2011-10-06 18:23:56 +0000257
Chris Lattnera8058742007-11-18 02:57:27 +0000258 // Check to see if this identifier is a keyword.
Benjamin Kramer37d42af2011-10-06 18:23:56 +0000259 StringRef Str(IdentStart, CurPtr-IdentStart);
260
Benjamin Kramer37d42af2011-10-06 18:23:56 +0000261 if (Str == "include") {
Chris Lattnerf4601652007-11-22 20:49:04 +0000262 if (LexInclude()) return tgtok::Error;
263 return Lex();
Chris Lattnera8058742007-11-18 02:57:27 +0000264 }
Benjamin Kramer37d42af2011-10-06 18:23:56 +0000265
Benjamin Krameree573182011-10-06 18:53:43 +0000266 tgtok::TokKind Kind = StringSwitch<tgtok::TokKind>(Str)
267 .Case("int", tgtok::Int)
268 .Case("bit", tgtok::Bit)
269 .Case("bits", tgtok::Bits)
270 .Case("string", tgtok::String)
271 .Case("list", tgtok::List)
272 .Case("code", tgtok::Code)
273 .Case("dag", tgtok::Dag)
274 .Case("class", tgtok::Class)
275 .Case("def", tgtok::Def)
David Greenecebb4ee2012-02-22 16:09:41 +0000276 .Case("foreach", tgtok::Foreach)
Benjamin Krameree573182011-10-06 18:53:43 +0000277 .Case("defm", tgtok::Defm)
278 .Case("multiclass", tgtok::MultiClass)
279 .Case("field", tgtok::Field)
280 .Case("let", tgtok::Let)
281 .Case("in", tgtok::In)
282 .Default(tgtok::Id);
283
284 if (Kind == tgtok::Id)
285 CurStrVal.assign(Str.begin(), Str.end());
286 return Kind;
Chris Lattnera8058742007-11-18 02:57:27 +0000287}
288
289/// LexInclude - We just read the "include" token. Get the string token that
290/// comes next and enter the include.
291bool TGLexer::LexInclude() {
292 // The token after the include must be a string.
Chris Lattnerf4601652007-11-22 20:49:04 +0000293 tgtok::TokKind Tok = LexToken();
294 if (Tok == tgtok::Error) return true;
295 if (Tok != tgtok::StrVal) {
296 PrintError(getLoc(), "Expected filename after include");
Chris Lattnera8058742007-11-18 02:57:27 +0000297 return true;
298 }
299
300 // Get the string.
Chris Lattnerf4601652007-11-22 20:49:04 +0000301 std::string Filename = CurStrVal;
Joerg Sonnenbergerdd137902011-06-01 13:10:15 +0000302 std::string IncludedFile;
Chris Lattnera8058742007-11-18 02:57:27 +0000303
Chris Lattner7ee5d5f2009-06-21 05:06:04 +0000304
Joerg Sonnenbergerdd137902011-06-01 13:10:15 +0000305 CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr),
306 IncludedFile);
Chris Lattnerd926e042009-06-21 05:33:06 +0000307 if (CurBuffer == -1) {
Chris Lattnerf4601652007-11-22 20:49:04 +0000308 PrintError(getLoc(), "Could not find include file '" + Filename + "'");
Chris Lattnera8058742007-11-18 02:57:27 +0000309 return true;
310 }
311
Sean Silvaa170f522013-02-07 04:30:39 +0000312 DependenciesMapTy::const_iterator Found = Dependencies.find(IncludedFile);
313 if (Found != Dependencies.end()) {
314 PrintError(getLoc(),
315 "File '" + IncludedFile + "' has already been included.");
316 SrcMgr.PrintMessage(Found->second, SourceMgr::DK_Note,
317 "previously included here");
318 return true;
319 }
320 Dependencies.insert(std::make_pair(IncludedFile, getLoc()));
Chris Lattnera8058742007-11-18 02:57:27 +0000321 // Save the line number and lex buffer of the includer.
Chris Lattner7ee5d5f2009-06-21 05:06:04 +0000322 CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
Chris Lattnera8058742007-11-18 02:57:27 +0000323 CurPtr = CurBuf->getBufferStart();
324 return false;
325}
326
327void TGLexer::SkipBCPLComment() {
328 ++CurPtr; // skip the second slash.
329 while (1) {
330 switch (*CurPtr) {
331 case '\n':
332 case '\r':
333 return; // Newline is end of comment.
334 case 0:
335 // If this is the end of the buffer, end the comment.
336 if (CurPtr == CurBuf->getBufferEnd())
337 return;
338 break;
339 }
340 // Otherwise, skip the character.
341 ++CurPtr;
342 }
343}
344
345/// SkipCComment - This skips C-style /**/ comments. The only difference from C
346/// is that we allow nesting.
347bool TGLexer::SkipCComment() {
348 ++CurPtr; // skip the star.
349 unsigned CommentDepth = 1;
350
351 while (1) {
352 int CurChar = getNextChar();
353 switch (CurChar) {
354 case EOF:
Chris Lattnerf4601652007-11-22 20:49:04 +0000355 PrintError(TokStart, "Unterminated comment!");
Chris Lattnera8058742007-11-18 02:57:27 +0000356 return true;
357 case '*':
358 // End of the comment?
359 if (CurPtr[0] != '/') break;
360
361 ++CurPtr; // End the */.
362 if (--CommentDepth == 0)
363 return false;
364 break;
365 case '/':
366 // Start of a nested comment?
367 if (CurPtr[0] != '*') break;
368 ++CurPtr;
369 ++CommentDepth;
370 break;
371 }
372 }
373}
374
375/// LexNumber - Lex:
376/// [-+]?[0-9]+
377/// 0x[0-9a-fA-F]+
378/// 0b[01]+
Chris Lattnerf4601652007-11-22 20:49:04 +0000379tgtok::TokKind TGLexer::LexNumber() {
Chris Lattnera8058742007-11-18 02:57:27 +0000380 if (CurPtr[-1] == '0') {
381 if (CurPtr[0] == 'x') {
382 ++CurPtr;
Chris Lattnerf4601652007-11-22 20:49:04 +0000383 const char *NumStart = CurPtr;
Chris Lattnera8058742007-11-18 02:57:27 +0000384 while (isxdigit(CurPtr[0]))
385 ++CurPtr;
386
Chris Lattnerc8a9bbc2007-11-19 07:38:58 +0000387 // Requires at least one hex digit.
388 if (CurPtr == NumStart)
Chris Lattner4226bb02009-06-21 19:22:49 +0000389 return ReturnError(TokStart, "Invalid hexadecimal number");
Chris Lattnerc8a9bbc2007-11-19 07:38:58 +0000390
Dan Gohman63f97202008-10-17 01:33:43 +0000391 errno = 0;
Chris Lattnerf4601652007-11-22 20:49:04 +0000392 CurIntVal = strtoll(NumStart, 0, 16);
Dan Gohman63f97202008-10-17 01:33:43 +0000393 if (errno == EINVAL)
Chris Lattner4226bb02009-06-21 19:22:49 +0000394 return ReturnError(TokStart, "Invalid hexadecimal number");
Dan Gohman63f97202008-10-17 01:33:43 +0000395 if (errno == ERANGE) {
396 errno = 0;
397 CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
398 if (errno == EINVAL)
Chris Lattner4226bb02009-06-21 19:22:49 +0000399 return ReturnError(TokStart, "Invalid hexadecimal number");
Dan Gohman63f97202008-10-17 01:33:43 +0000400 if (errno == ERANGE)
Chris Lattner4226bb02009-06-21 19:22:49 +0000401 return ReturnError(TokStart, "Hexadecimal number out of range");
Dan Gohman63f97202008-10-17 01:33:43 +0000402 }
Chris Lattnerf4601652007-11-22 20:49:04 +0000403 return tgtok::IntVal;
Chris Lattnera8058742007-11-18 02:57:27 +0000404 } else if (CurPtr[0] == 'b') {
405 ++CurPtr;
Chris Lattnerf4601652007-11-22 20:49:04 +0000406 const char *NumStart = CurPtr;
Chris Lattnera8058742007-11-18 02:57:27 +0000407 while (CurPtr[0] == '0' || CurPtr[0] == '1')
408 ++CurPtr;
Chris Lattnerc8a9bbc2007-11-19 07:38:58 +0000409
410 // Requires at least one binary digit.
411 if (CurPtr == NumStart)
412 return ReturnError(CurPtr-2, "Invalid binary number");
Chris Lattnerf4601652007-11-22 20:49:04 +0000413 CurIntVal = strtoll(NumStart, 0, 2);
414 return tgtok::IntVal;
Chris Lattnera8058742007-11-18 02:57:27 +0000415 }
416 }
417
418 // Check for a sign without a digit.
Chris Lattnerf4601652007-11-22 20:49:04 +0000419 if (!isdigit(CurPtr[0])) {
420 if (CurPtr[-1] == '-')
421 return tgtok::minus;
422 else if (CurPtr[-1] == '+')
423 return tgtok::plus;
Chris Lattnera8058742007-11-18 02:57:27 +0000424 }
425
426 while (isdigit(CurPtr[0]))
427 ++CurPtr;
Chris Lattnerf4601652007-11-22 20:49:04 +0000428 CurIntVal = strtoll(TokStart, 0, 10);
429 return tgtok::IntVal;
Chris Lattnera8058742007-11-18 02:57:27 +0000430}
431
432/// LexBracket - We just read '['. If this is a code block, return it,
433/// otherwise return the bracket. Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
Chris Lattnerf4601652007-11-22 20:49:04 +0000434tgtok::TokKind TGLexer::LexBracket() {
Chris Lattnera8058742007-11-18 02:57:27 +0000435 if (CurPtr[0] != '{')
Chris Lattnerf4601652007-11-22 20:49:04 +0000436 return tgtok::l_square;
Chris Lattnera8058742007-11-18 02:57:27 +0000437 ++CurPtr;
438 const char *CodeStart = CurPtr;
439 while (1) {
440 int Char = getNextChar();
441 if (Char == EOF) break;
442
443 if (Char != '}') continue;
444
445 Char = getNextChar();
446 if (Char == EOF) break;
447 if (Char == ']') {
Chris Lattnerf4601652007-11-22 20:49:04 +0000448 CurStrVal.assign(CodeStart, CurPtr-2);
449 return tgtok::CodeFragment;
Chris Lattnera8058742007-11-18 02:57:27 +0000450 }
451 }
452
Chris Lattnerc8a9bbc2007-11-19 07:38:58 +0000453 return ReturnError(CodeStart-2, "Unterminated Code Block");
Chris Lattnera8058742007-11-18 02:57:27 +0000454}
455
456/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
Chris Lattnerf4601652007-11-22 20:49:04 +0000457tgtok::TokKind TGLexer::LexExclaim() {
Chris Lattnera8058742007-11-18 02:57:27 +0000458 if (!isalpha(*CurPtr))
Bill Wendlingdd2b6cb2010-12-08 13:03:15 +0000459 return ReturnError(CurPtr - 1, "Invalid \"!operator\"");
Chris Lattnera8058742007-11-18 02:57:27 +0000460
461 const char *Start = CurPtr++;
462 while (isalpha(*CurPtr))
463 ++CurPtr;
464
465 // Check to see which operator this is.
Bill Wendlingcd466f52010-12-08 20:02:49 +0000466 tgtok::TokKind Kind =
467 StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
468 .Case("eq", tgtok::XEq)
469 .Case("if", tgtok::XIf)
David Greene1434f662011-01-07 17:05:37 +0000470 .Case("head", tgtok::XHead)
471 .Case("tail", tgtok::XTail)
Bill Wendlingcd466f52010-12-08 20:02:49 +0000472 .Case("con", tgtok::XConcat)
Hal Finkeld23a41c2013-01-25 14:49:08 +0000473 .Case("add", tgtok::XADD)
Bill Wendlingcd466f52010-12-08 20:02:49 +0000474 .Case("shl", tgtok::XSHL)
475 .Case("sra", tgtok::XSRA)
476 .Case("srl", tgtok::XSRL)
477 .Case("cast", tgtok::XCast)
David Greene1434f662011-01-07 17:05:37 +0000478 .Case("empty", tgtok::XEmpty)
Bill Wendlingcd466f52010-12-08 20:02:49 +0000479 .Case("subst", tgtok::XSubst)
480 .Case("foreach", tgtok::XForEach)
481 .Case("strconcat", tgtok::XStrConcat)
482 .Default(tgtok::Error);
David Greened418c1b2009-05-14 20:54:48 +0000483
Bill Wendlingcd466f52010-12-08 20:02:49 +0000484 return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator");
Chris Lattnera8058742007-11-18 02:57:27 +0000485}
486