blob: 2b963607b8374ba92f31955fa8d4db93a1dd65cc [file] [log] [blame]
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +00001//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This class implements the lexer for assembly files.
11//
12//===----------------------------------------------------------------------===//
13
Chandler Carruth6bda14b2017-06-06 11:49:48 +000014#include "llvm/MC/MCParser/AsmLexer.h"
Eugene Zelenko33d7b762016-08-23 17:14:32 +000015#include "llvm/ADT/APInt.h"
16#include "llvm/ADT/ArrayRef.h"
Nirav Davee4c61532016-10-01 10:57:55 +000017#include "llvm/ADT/StringRef.h"
Nirav Dave157891c2016-10-03 13:48:27 +000018#include "llvm/ADT/StringSwitch.h"
Nirav Davee4c61532016-10-01 10:57:55 +000019#include "llvm/MC/MCAsmInfo.h"
Nirav Dave157891c2016-10-03 13:48:27 +000020#include "llvm/MC/MCParser/MCAsmLexer.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/Support/SMLoc.h"
Nirav Dave157891c2016-10-03 13:48:27 +000022#include "llvm/Support/SaveAndRestore.h"
Eugene Zelenko33d7b762016-08-23 17:14:32 +000023#include <cassert>
Nick Lewycky0de20af2010-12-19 20:43:38 +000024#include <cctype>
Duncan Sands376c6f12009-06-22 06:59:32 +000025#include <cstdio>
Eugene Zelenko33d7b762016-08-23 17:14:32 +000026#include <cstring>
Nirav Davee4c61532016-10-01 10:57:55 +000027#include <string>
Nirav Dave157891c2016-10-03 13:48:27 +000028#include <tuple>
Eugene Zelenko33d7b762016-08-23 17:14:32 +000029#include <utility>
Daniel Sanders3feeb9c2016-08-08 11:50:25 +000030
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +000031using namespace llvm;
32
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +000033AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
David Peixotto27aa0012013-12-06 23:05:33 +000034 AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@");
Chris Lattner4c501fc2009-06-24 00:33:19 +000035}
36
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +000037AsmLexer::~AsmLexer() = default;
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +000038
Rafael Espindola8026bd02014-07-06 14:17:29 +000039void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
40 CurBuf = Buf;
Jim Grosbach01af6c42011-02-11 19:05:56 +000041
Sean Callanan7a77eae2010-01-21 00:19:58 +000042 if (ptr)
43 CurPtr = ptr;
44 else
Rafael Espindola8026bd02014-07-06 14:17:29 +000045 CurPtr = CurBuf.begin();
Jim Grosbach01af6c42011-02-11 19:05:56 +000046
Craig Topper353eda42014-04-24 06:44:33 +000047 TokStart = nullptr;
Sean Callanan7a77eae2010-01-21 00:19:58 +000048}
49
Chris Lattnerd0765612009-06-21 19:21:25 +000050/// ReturnError - Set the error to the specified string at the specified
Daniel Dunbarf2dcd772009-07-28 16:08:33 +000051/// location. This is defined to always return AsmToken::Error.
Daniel Dunbar8368f4e2009-07-28 03:00:54 +000052AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
Sean Callanan70855e42010-01-20 22:18:24 +000053 SetError(SMLoc::getFromPointer(Loc), Msg);
Jim Grosbach01af6c42011-02-11 19:05:56 +000054
Nirav Dave1180e6892016-06-02 17:15:05 +000055 return AsmToken(AsmToken::Error, StringRef(Loc, CurPtr - Loc));
Chris Lattnerd0765612009-06-21 19:21:25 +000056}
57
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +000058int AsmLexer::getNextChar() {
Nirav Davefd910412016-06-17 16:06:17 +000059 if (CurPtr == CurBuf.end())
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +000060 return EOF;
Nirav Davefd910412016-06-17 16:06:17 +000061 return (unsigned char)*CurPtr++;
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +000062}
63
Daniel Dunbard116d8a2010-09-27 20:12:52 +000064/// LexFloatLiteral: [0-9]*[.][0-9]*([eE][+-]?[0-9]*)?
65///
66/// The leading integral digit sequence and dot should have already been
67/// consumed, some or all of the fractional digit sequence *can* have been
68/// consumed.
69AsmToken AsmLexer::LexFloatLiteral() {
70 // Skip the fractional digit sequence.
71 while (isdigit(*CurPtr))
72 ++CurPtr;
73
74 // Check for exponent; we intentionally accept a slighlty wider set of
75 // literals here and rely on the upstream client to reject invalid ones (e.g.,
76 // "1e+").
77 if (*CurPtr == 'e' || *CurPtr == 'E') {
78 ++CurPtr;
79 if (*CurPtr == '-' || *CurPtr == '+')
80 ++CurPtr;
81 while (isdigit(*CurPtr))
82 ++CurPtr;
83 }
84
85 return AsmToken(AsmToken::Real,
86 StringRef(TokStart, CurPtr - TokStart));
87}
88
Tim Northover1f256232013-08-14 14:23:31 +000089/// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+
90/// while making sure there are enough actual digits around for the constant to
91/// be valid.
92///
93/// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed
94/// before we get here.
95AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
96 assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') &&
97 "unexpected parse state in floating hex");
98 bool NoFracDigits = true;
99
100 // Skip the fractional part if there is one
101 if (*CurPtr == '.') {
102 ++CurPtr;
103
104 const char *FracStart = CurPtr;
105 while (isxdigit(*CurPtr))
106 ++CurPtr;
107
108 NoFracDigits = CurPtr == FracStart;
109 }
110
111 if (NoIntDigits && NoFracDigits)
112 return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
113 "expected at least one significand digit");
114
115 // Make sure we do have some kind of proper exponent part
116 if (*CurPtr != 'p' && *CurPtr != 'P')
117 return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
118 "expected exponent part 'p'");
119 ++CurPtr;
120
121 if (*CurPtr == '+' || *CurPtr == '-')
122 ++CurPtr;
123
124 // N.b. exponent digits are *not* hex
125 const char *ExpStart = CurPtr;
126 while (isdigit(*CurPtr))
127 ++CurPtr;
128
129 if (CurPtr == ExpStart)
130 return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
131 "expected at least one exponent digit");
132
133 return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart));
134}
135
Hans Wennborgce69d772013-10-18 20:46:28 +0000136/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]*
David Peixotto2cdc56d2013-12-06 20:35:58 +0000137static bool IsIdentifierChar(char c, bool AllowAt) {
138 return isalnum(c) || c == '_' || c == '$' || c == '.' ||
139 (c == '@' && AllowAt) || c == '?';
Daniel Dunbar3068a932010-09-24 01:59:31 +0000140}
Eugene Zelenko33d7b762016-08-23 17:14:32 +0000141
Daniel Dunbar8368f4e2009-07-28 03:00:54 +0000142AsmToken AsmLexer::LexIdentifier() {
Daniel Dunbar3068a932010-09-24 01:59:31 +0000143 // Check for floating point literals.
144 if (CurPtr[-1] == '.' && isdigit(*CurPtr)) {
Daniel Dunbard116d8a2010-09-27 20:12:52 +0000145 // Disambiguate a .1243foo identifier from a floating literal.
Daniel Dunbar3068a932010-09-24 01:59:31 +0000146 while (isdigit(*CurPtr))
147 ++CurPtr;
David Peixotto2cdc56d2013-12-06 20:35:58 +0000148 if (*CurPtr == 'e' || *CurPtr == 'E' ||
149 !IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
Daniel Dunbard116d8a2010-09-27 20:12:52 +0000150 return LexFloatLiteral();
Daniel Dunbar3068a932010-09-24 01:59:31 +0000151 }
152
David Peixotto2cdc56d2013-12-06 20:35:58 +0000153 while (IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
Chris Lattnerd0765612009-06-21 19:21:25 +0000154 ++CurPtr;
Jim Grosbach01af6c42011-02-11 19:05:56 +0000155
Chris Lattner6b55cb92010-04-14 04:40:28 +0000156 // Handle . as a special case.
Daniel Dunbarb0ceb762010-05-06 14:46:38 +0000157 if (CurPtr == TokStart+1 && TokStart[0] == '.')
158 return AsmToken(AsmToken::Dot, StringRef(TokStart, 1));
Jim Grosbach01af6c42011-02-11 19:05:56 +0000159
Daniel Dunbarf2dcd772009-07-28 16:08:33 +0000160 return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart));
Chris Lattnerd0765612009-06-21 19:21:25 +0000161}
162
Chris Lattnerd0765612009-06-21 19:21:25 +0000163/// LexSlash: Slash: /
164/// C-Style Comment: /* ... */
Daniel Dunbar8368f4e2009-07-28 03:00:54 +0000165AsmToken AsmLexer::LexSlash() {
Daniel Dunbar6b22f9c2009-06-29 21:58:22 +0000166 switch (*CurPtr) {
Richard Trieu7a083812016-02-18 22:09:30 +0000167 case '*':
Nirav Davefd910412016-06-17 16:06:17 +0000168 IsAtStartOfStatement = false;
Richard Trieu7a083812016-02-18 22:09:30 +0000169 break; // C style comment.
170 case '/':
171 ++CurPtr;
172 return LexLineComment();
173 default:
Nirav Davefd910412016-06-17 16:06:17 +0000174 IsAtStartOfStatement = false;
175 return AsmToken(AsmToken::Slash, StringRef(TokStart, 1));
Daniel Dunbar6b22f9c2009-06-29 21:58:22 +0000176 }
Chris Lattnerd0765612009-06-21 19:21:25 +0000177
178 // C Style comment.
179 ++CurPtr; // skip the star.
Oliver Stannard68e7c212016-12-08 10:31:21 +0000180 const char *CommentTextStart = CurPtr;
Nirav Davefd910412016-06-17 16:06:17 +0000181 while (CurPtr != CurBuf.end()) {
182 switch (*CurPtr++) {
Chris Lattnerd0765612009-06-21 19:21:25 +0000183 case '*':
184 // End of the comment?
Nirav Davefd910412016-06-17 16:06:17 +0000185 if (*CurPtr != '/')
186 break;
Oliver Stannard68e7c212016-12-08 10:31:21 +0000187 // If we have a CommentConsumer, notify it about the comment.
188 if (CommentConsumer) {
189 CommentConsumer->HandleComment(
190 SMLoc::getFromPointer(CommentTextStart),
191 StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
192 }
Chris Lattnerd0765612009-06-21 19:21:25 +0000193 ++CurPtr; // End the */.
Nirav Davefd910412016-06-17 16:06:17 +0000194 return AsmToken(AsmToken::Comment,
195 StringRef(TokStart, CurPtr - TokStart));
Chris Lattnerd0765612009-06-21 19:21:25 +0000196 }
197 }
Nirav Davefd910412016-06-17 16:06:17 +0000198 return ReturnError(TokStart, "unterminated comment");
Chris Lattnerd0765612009-06-21 19:21:25 +0000199}
200
Daniel Dunbar6b22f9c2009-06-29 21:58:22 +0000201/// LexLineComment: Comment: #[^\n]*
202/// : //[^\n]*
Daniel Dunbar8368f4e2009-07-28 03:00:54 +0000203AsmToken AsmLexer::LexLineComment() {
Nirav Davefd910412016-06-17 16:06:17 +0000204 // Mark This as an end of statement with a body of the
205 // comment. While it would be nicer to leave this two tokens,
206 // backwards compatability with TargetParsers makes keeping this in this form
207 // better.
Oliver Stannard68e7c212016-12-08 10:31:21 +0000208 const char *CommentTextStart = CurPtr;
Chris Lattnerd0765612009-06-21 19:21:25 +0000209 int CurChar = getNextChar();
Chris Lattnere8baa382011-08-04 19:31:26 +0000210 while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF)
Chris Lattnerd0765612009-06-21 19:21:25 +0000211 CurChar = getNextChar();
Jim Grosbach01af6c42011-02-11 19:05:56 +0000212
Oliver Stannard68e7c212016-12-08 10:31:21 +0000213 // If we have a CommentConsumer, notify it about the comment.
214 if (CommentConsumer) {
215 CommentConsumer->HandleComment(
216 SMLoc::getFromPointer(CommentTextStart),
217 StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
218 }
219
Nirav Davefd910412016-06-17 16:06:17 +0000220 IsAtStartOfLine = true;
Nirav Dave8b3dc872016-07-29 14:42:00 +0000221 // This is a whole line comment. leave newline
Nirav Davefd910412016-06-17 16:06:17 +0000222 if (IsAtStartOfStatement)
223 return AsmToken(AsmToken::EndOfStatement,
224 StringRef(TokStart, CurPtr - TokStart));
225 IsAtStartOfStatement = true;
226
227 return AsmToken(AsmToken::EndOfStatement,
228 StringRef(TokStart, CurPtr - 1 - TokStart));
Chris Lattnerd0765612009-06-21 19:21:25 +0000229}
230
Chris Lattner02db8f62010-08-24 00:43:25 +0000231static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
Jim Grosbach94a22602013-02-26 20:17:10 +0000232 // Skip ULL, UL, U, L and LL suffices.
233 if (CurPtr[0] == 'U')
234 ++CurPtr;
235 if (CurPtr[0] == 'L')
236 ++CurPtr;
237 if (CurPtr[0] == 'L')
238 ++CurPtr;
Chris Lattner02db8f62010-08-24 00:43:25 +0000239}
240
Chad Rosier8bc65562013-02-12 01:00:01 +0000241// Look ahead to search for first non-hex digit, if it's [hH], then we treat the
242// integer as a hexadecimal, possibly with leading zeroes.
243static unsigned doLookAhead(const char *&CurPtr, unsigned DefaultRadix) {
Craig Topper353eda42014-04-24 06:44:33 +0000244 const char *FirstHex = nullptr;
Chad Rosier8bc65562013-02-12 01:00:01 +0000245 const char *LookAhead = CurPtr;
Eugene Zelenko33d7b762016-08-23 17:14:32 +0000246 while (true) {
Chad Rosier8bc65562013-02-12 01:00:01 +0000247 if (isdigit(*LookAhead)) {
248 ++LookAhead;
249 } else if (isxdigit(*LookAhead)) {
250 if (!FirstHex)
251 FirstHex = LookAhead;
252 ++LookAhead;
253 } else {
254 break;
255 }
256 }
257 bool isHex = *LookAhead == 'h' || *LookAhead == 'H';
Rafael Espindola86d53452013-02-14 16:23:08 +0000258 CurPtr = isHex || !FirstHex ? LookAhead : FirstHex;
Chad Rosier8bc65562013-02-12 01:00:01 +0000259 if (isHex)
260 return 16;
261 return DefaultRadix;
262}
263
David Woodhousef42a6662014-02-01 16:20:54 +0000264static AsmToken intToken(StringRef Ref, APInt &Value)
265{
266 if (Value.isIntN(64))
267 return AsmToken(AsmToken::Integer, Ref, Value);
268 return AsmToken(AsmToken::BigNum, Ref, Value);
269}
270
Chris Lattnerd0765612009-06-21 19:21:25 +0000271/// LexDigit: First character is [0-9].
272/// Local Label: [0-9][:]
Rafael Espindola86d53452013-02-14 16:23:08 +0000273/// Forward/Backward Label: [0-9][fb]
274/// Binary integer: 0b[01]+
Chris Lattnerd0765612009-06-21 19:21:25 +0000275/// Octal integer: 0[0-7]+
Chad Rosier8bc65562013-02-12 01:00:01 +0000276/// Hex integer: 0x[0-9a-fA-F]+ or [0x]?[0-9][0-9a-fA-F]*[hH]
Chris Lattnerd0765612009-06-21 19:21:25 +0000277/// Decimal integer: [1-9][0-9]*
Daniel Dunbar8368f4e2009-07-28 03:00:54 +0000278AsmToken AsmLexer::LexDigit() {
Yunzhong Gao27ea29b2016-09-02 23:15:29 +0000279 // MASM-flavor binary integer: [01]+[bB]
280 // MASM-flavor hexadecimal integer: [0-9][0-9a-fA-F]*[hH]
281 if (IsParsingMSInlineAsm && isdigit(CurPtr[-1])) {
282 const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ?
283 CurPtr - 1 : nullptr;
284 const char *OldCurPtr = CurPtr;
285 while (isxdigit(*CurPtr)) {
286 if (*CurPtr != '0' && *CurPtr != '1' && !FirstNonBinary)
287 FirstNonBinary = CurPtr;
288 ++CurPtr;
289 }
290
291 unsigned Radix = 0;
292 if (*CurPtr == 'h' || *CurPtr == 'H') {
293 // hexadecimal number
294 ++CurPtr;
295 Radix = 16;
296 } else if (FirstNonBinary && FirstNonBinary + 1 == CurPtr &&
297 (*FirstNonBinary == 'b' || *FirstNonBinary == 'B'))
298 Radix = 2;
299
300 if (Radix == 2 || Radix == 16) {
301 StringRef Result(TokStart, CurPtr - TokStart);
302 APInt Value(128, 0, true);
303
304 if (Result.drop_back().getAsInteger(Radix, Value))
305 return ReturnError(TokStart, Radix == 2 ? "invalid binary number" :
306 "invalid hexdecimal number");
307
308 // MSVC accepts and ignores type suffices on integer literals.
309 SkipIgnoredIntegerSuffix(CurPtr);
310
311 return intToken(Result, Value);
312 }
313
314 // octal/decimal integers, or floating point numbers, fall through
315 CurPtr = OldCurPtr;
316 }
317
Chris Lattnerd0765612009-06-21 19:21:25 +0000318 // Decimal integer: [1-9][0-9]*
Daniel Dunbarce17f722010-09-24 17:10:26 +0000319 if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
Chad Rosier8bc65562013-02-12 01:00:01 +0000320 unsigned Radix = doLookAhead(CurPtr, 10);
Rafael Espindola86d53452013-02-14 16:23:08 +0000321 bool isHex = Radix == 16;
Daniel Dunbar3068a932010-09-24 01:59:31 +0000322 // Check for floating point literals.
Rafael Espindola86d53452013-02-14 16:23:08 +0000323 if (!isHex && (*CurPtr == '.' || *CurPtr == 'e')) {
Daniel Dunbar3068a932010-09-24 01:59:31 +0000324 ++CurPtr;
Daniel Dunbard116d8a2010-09-27 20:12:52 +0000325 return LexFloatLiteral();
Daniel Dunbar3068a932010-09-24 01:59:31 +0000326 }
327
Chris Lattnere6494012010-01-22 07:34:12 +0000328 StringRef Result(TokStart, CurPtr - TokStart);
Chris Lattner02db8f62010-08-24 00:43:25 +0000329
David Woodhousef42a6662014-02-01 16:20:54 +0000330 APInt Value(128, 0, true);
331 if (Result.getAsInteger(Radix, Value))
332 return ReturnError(TokStart, !isHex ? "invalid decimal number" :
Chad Rosier8bc65562013-02-12 01:00:01 +0000333 "invalid hexdecimal number");
Jim Grosbach01af6c42011-02-11 19:05:56 +0000334
Chad Rosier8bc65562013-02-12 01:00:01 +0000335 // Consume the [bB][hH].
336 if (Radix == 2 || Radix == 16)
337 ++CurPtr;
338
Jim Grosbach94a22602013-02-26 20:17:10 +0000339 // The darwin/x86 (and x86-64) assembler accepts and ignores type
340 // suffices on integer literals.
Chris Lattner02db8f62010-08-24 00:43:25 +0000341 SkipIgnoredIntegerSuffix(CurPtr);
Jim Grosbach01af6c42011-02-11 19:05:56 +0000342
David Woodhousef42a6662014-02-01 16:20:54 +0000343 return intToken(Result, Value);
Chris Lattnerd0765612009-06-21 19:21:25 +0000344 }
Jim Grosbach01af6c42011-02-11 19:05:56 +0000345
Yunzhong Gao27ea29b2016-09-02 23:15:29 +0000346 if (!IsParsingMSInlineAsm && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
Rafael Espindola86d53452013-02-14 16:23:08 +0000347 ++CurPtr;
348 // See if we actually have "0b" as part of something like "jmp 0b\n"
349 if (!isdigit(CurPtr[0])) {
350 --CurPtr;
351 StringRef Result(TokStart, CurPtr - TokStart);
352 return AsmToken(AsmToken::Integer, Result, 0);
353 }
354 const char *NumStart = CurPtr;
Chris Lattnerd0765612009-06-21 19:21:25 +0000355 while (CurPtr[0] == '0' || CurPtr[0] == '1')
356 ++CurPtr;
Jim Grosbach01af6c42011-02-11 19:05:56 +0000357
Chris Lattnerd0765612009-06-21 19:21:25 +0000358 // Requires at least one binary digit.
359 if (CurPtr == NumStart)
Eric Christopherffc0e1f2011-04-12 00:18:03 +0000360 return ReturnError(TokStart, "invalid binary number");
Jim Grosbach01af6c42011-02-11 19:05:56 +0000361
Chris Lattnere6494012010-01-22 07:34:12 +0000362 StringRef Result(TokStart, CurPtr - TokStart);
Jim Grosbach01af6c42011-02-11 19:05:56 +0000363
David Woodhousef42a6662014-02-01 16:20:54 +0000364 APInt Value(128, 0, true);
Chris Lattner02db8f62010-08-24 00:43:25 +0000365 if (Result.substr(2).getAsInteger(2, Value))
Eric Christopherffc0e1f2011-04-12 00:18:03 +0000366 return ReturnError(TokStart, "invalid binary number");
Jim Grosbach01af6c42011-02-11 19:05:56 +0000367
Chris Lattner02db8f62010-08-24 00:43:25 +0000368 // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
369 // suffixes on integer literals.
370 SkipIgnoredIntegerSuffix(CurPtr);
Jim Grosbach01af6c42011-02-11 19:05:56 +0000371
David Woodhousef42a6662014-02-01 16:20:54 +0000372 return intToken(Result, Value);
Chris Lattnerd0765612009-06-21 19:21:25 +0000373 }
Jim Grosbach01af6c42011-02-11 19:05:56 +0000374
Colin LeMahieu01431462016-03-18 18:22:07 +0000375 if ((*CurPtr == 'x') || (*CurPtr == 'X')) {
Chris Lattnerd0765612009-06-21 19:21:25 +0000376 ++CurPtr;
377 const char *NumStart = CurPtr;
378 while (isxdigit(CurPtr[0]))
379 ++CurPtr;
Jim Grosbach01af6c42011-02-11 19:05:56 +0000380
Tim Northover1f256232013-08-14 14:23:31 +0000381 // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
382 // diagnosed by LexHexFloatLiteral).
383 if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P')
384 return LexHexFloatLiteral(NumStart == CurPtr);
385
386 // Otherwise requires at least one hex digit.
Chris Lattnerd0765612009-06-21 19:21:25 +0000387 if (CurPtr == NumStart)
Eric Christopherffc0e1f2011-04-12 00:18:03 +0000388 return ReturnError(CurPtr-2, "invalid hexadecimal number");
Chris Lattner6401c882010-01-22 01:17:12 +0000389
David Woodhousef42a6662014-02-01 16:20:54 +0000390 APInt Result(128, 0);
Chris Lattner6401c882010-01-22 01:17:12 +0000391 if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result))
Eric Christopherffc0e1f2011-04-12 00:18:03 +0000392 return ReturnError(TokStart, "invalid hexadecimal number");
Jim Grosbach01af6c42011-02-11 19:05:56 +0000393
Chad Rosier8bc65562013-02-12 01:00:01 +0000394 // Consume the optional [hH].
Yunzhong Gao27ea29b2016-09-02 23:15:29 +0000395 if (!IsParsingMSInlineAsm && (*CurPtr == 'h' || *CurPtr == 'H'))
Chad Rosier8bc65562013-02-12 01:00:01 +0000396 ++CurPtr;
397
Chris Lattner02db8f62010-08-24 00:43:25 +0000398 // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
399 // suffixes on integer literals.
400 SkipIgnoredIntegerSuffix(CurPtr);
Jim Grosbach01af6c42011-02-11 19:05:56 +0000401
David Woodhousef42a6662014-02-01 16:20:54 +0000402 return intToken(StringRef(TokStart, CurPtr - TokStart), Result);
Chris Lattnerd0765612009-06-21 19:21:25 +0000403 }
Jim Grosbach01af6c42011-02-11 19:05:56 +0000404
Matt Beaumont-Gay0e760da2013-02-25 18:11:18 +0000405 // Either octal or hexadecimal.
David Woodhousef42a6662014-02-01 16:20:54 +0000406 APInt Value(128, 0, true);
Chad Rosier8bc65562013-02-12 01:00:01 +0000407 unsigned Radix = doLookAhead(CurPtr, 8);
Rafael Espindola86d53452013-02-14 16:23:08 +0000408 bool isHex = Radix == 16;
Chad Rosier8bc65562013-02-12 01:00:01 +0000409 StringRef Result(TokStart, CurPtr - TokStart);
410 if (Result.getAsInteger(Radix, Value))
Rafael Espindola86d53452013-02-14 16:23:08 +0000411 return ReturnError(TokStart, !isHex ? "invalid octal number" :
Chad Rosier559cea42013-02-12 01:12:24 +0000412 "invalid hexdecimal number");
Jim Grosbach01af6c42011-02-11 19:05:56 +0000413
Rafael Espindola86d53452013-02-14 16:23:08 +0000414 // Consume the [hH].
415 if (Radix == 16)
Chad Rosier8bc65562013-02-12 01:00:01 +0000416 ++CurPtr;
417
Chris Lattner02db8f62010-08-24 00:43:25 +0000418 // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
419 // suffixes on integer literals.
420 SkipIgnoredIntegerSuffix(CurPtr);
Jim Grosbach01af6c42011-02-11 19:05:56 +0000421
David Woodhousef42a6662014-02-01 16:20:54 +0000422 return intToken(Result, Value);
Chris Lattnerd0765612009-06-21 19:21:25 +0000423}
424
Roman Divacky71d29162010-12-18 08:56:37 +0000425/// LexSingleQuote: Integer: 'b'
426AsmToken AsmLexer::LexSingleQuote() {
427 int CurChar = getNextChar();
428
429 if (CurChar == '\\')
430 CurChar = getNextChar();
431
432 if (CurChar == EOF)
433 return ReturnError(TokStart, "unterminated single quote");
434
435 CurChar = getNextChar();
436
437 if (CurChar != '\'')
438 return ReturnError(TokStart, "single quote way too long");
439
440 // The idea here being that 'c' is basically just an integral
441 // constant.
442 StringRef Res = StringRef(TokStart,CurPtr - TokStart);
443 long long Value;
444
445 if (Res.startswith("\'\\")) {
446 char theChar = Res[2];
447 switch (theChar) {
448 default: Value = theChar; break;
449 case '\'': Value = '\''; break;
450 case 't': Value = '\t'; break;
451 case 'n': Value = '\n'; break;
452 case 'b': Value = '\b'; break;
453 }
454 } else
455 Value = TokStart[1];
456
Jim Grosbach01af6c42011-02-11 19:05:56 +0000457 return AsmToken(AsmToken::Integer, Res, Value);
Roman Divacky71d29162010-12-18 08:56:37 +0000458}
459
Chris Lattner419a9742009-06-21 19:56:35 +0000460/// LexQuote: String: "..."
Daniel Dunbar8368f4e2009-07-28 03:00:54 +0000461AsmToken AsmLexer::LexQuote() {
Chris Lattner419a9742009-06-21 19:56:35 +0000462 int CurChar = getNextChar();
463 // TODO: does gas allow multiline string constants?
464 while (CurChar != '"') {
465 if (CurChar == '\\') {
466 // Allow \", etc.
467 CurChar = getNextChar();
468 }
Jim Grosbach01af6c42011-02-11 19:05:56 +0000469
Chris Lattner2adc9e72009-06-21 21:22:11 +0000470 if (CurChar == EOF)
471 return ReturnError(TokStart, "unterminated string constant");
Chris Lattner419a9742009-06-21 19:56:35 +0000472
473 CurChar = getNextChar();
474 }
Jim Grosbach01af6c42011-02-11 19:05:56 +0000475
Daniel Dunbarf2dcd772009-07-28 16:08:33 +0000476 return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
Chris Lattner419a9742009-06-21 19:56:35 +0000477}
478
Chris Lattnercb307a272009-08-10 01:39:42 +0000479StringRef AsmLexer::LexUntilEndOfStatement() {
480 TokStart = CurPtr;
481
Saleem Abdulrasoolbb67af42014-08-14 02:51:43 +0000482 while (!isAtStartOfComment(CurPtr) && // Start of line comment.
Jim Grosbacha3df87f2011-03-24 18:46:34 +0000483 !isAtStatementSeparator(CurPtr) && // End of statement marker.
Nirav Davefd910412016-06-17 16:06:17 +0000484 *CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
Chris Lattnercb307a272009-08-10 01:39:42 +0000485 ++CurPtr;
Kevin Enderbyf92f9902009-09-04 21:45:34 +0000486 }
Chris Lattnercb307a272009-08-10 01:39:42 +0000487 return StringRef(TokStart, CurPtr-TokStart);
488}
Chris Lattnerd0765612009-06-21 19:21:25 +0000489
Kevin Enderby72553612011-09-13 23:45:18 +0000490StringRef AsmLexer::LexUntilEndOfLine() {
491 TokStart = CurPtr;
492
Nirav Davefd910412016-06-17 16:06:17 +0000493 while (*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
Kevin Enderby72553612011-09-13 23:45:18 +0000494 ++CurPtr;
495 }
496 return StringRef(TokStart, CurPtr-TokStart);
497}
498
Benjamin Kramer1ee99a82015-08-17 14:35:25 +0000499size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf,
500 bool ShouldSkipSpace) {
Nirav Dave157891c2016-10-03 13:48:27 +0000501 SaveAndRestore<const char *> SavedTokenStart(TokStart);
502 SaveAndRestore<const char *> SavedCurPtr(CurPtr);
503 SaveAndRestore<bool> SavedAtStartOfLine(IsAtStartOfLine);
504 SaveAndRestore<bool> SavedAtStartOfStatement(IsAtStartOfStatement);
505 SaveAndRestore<bool> SavedSkipSpace(SkipSpace, ShouldSkipSpace);
506 SaveAndRestore<bool> SavedIsPeeking(IsPeeking, true);
Saleem Abdulrasoola879fab2014-02-09 23:29:24 +0000507 std::string SavedErr = getErr();
508 SMLoc SavedErrLoc = getErrLoc();
509
Benjamin Kramer1ee99a82015-08-17 14:35:25 +0000510 size_t ReadCount;
511 for (ReadCount = 0; ReadCount < Buf.size(); ++ReadCount) {
512 AsmToken Token = LexToken();
513
514 Buf[ReadCount] = Token;
515
516 if (Token.is(AsmToken::Eof))
517 break;
518 }
Saleem Abdulrasoola879fab2014-02-09 23:29:24 +0000519
520 SetError(SavedErrLoc, SavedErr);
Benjamin Kramer1ee99a82015-08-17 14:35:25 +0000521 return ReadCount;
Saleem Abdulrasoola879fab2014-02-09 23:29:24 +0000522}
523
Saleem Abdulrasoolbb67af42014-08-14 02:51:43 +0000524bool AsmLexer::isAtStartOfComment(const char *Ptr) {
Mehdi Amini36d33fc2016-10-01 06:46:33 +0000525 StringRef CommentString = MAI.getCommentString();
Saleem Abdulrasoolbb67af42014-08-14 02:51:43 +0000526
Mehdi Amini36d33fc2016-10-01 06:46:33 +0000527 if (CommentString.size() == 1)
Saleem Abdulrasoolbb67af42014-08-14 02:51:43 +0000528 return CommentString[0] == Ptr[0];
529
Nirav Dave157891c2016-10-03 13:48:27 +0000530 // Allow # preprocessor commments also be counted as comments for "##" cases
Saleem Abdulrasoolbb67af42014-08-14 02:51:43 +0000531 if (CommentString[1] == '#')
532 return CommentString[0] == Ptr[0];
533
Mehdi Amini36d33fc2016-10-01 06:46:33 +0000534 return strncmp(Ptr, CommentString.data(), CommentString.size()) == 0;
Kevin Enderbyecd879a2009-09-16 18:08:00 +0000535}
536
Jim Grosbacha3df87f2011-03-24 18:46:34 +0000537bool AsmLexer::isAtStatementSeparator(const char *Ptr) {
538 return strncmp(Ptr, MAI.getSeparatorString(),
539 strlen(MAI.getSeparatorString())) == 0;
540}
541
Daniel Dunbar8368f4e2009-07-28 03:00:54 +0000542AsmToken AsmLexer::LexToken() {
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +0000543 TokStart = CurPtr;
544 // This always consumes at least one character.
545 int CurChar = getNextChar();
Jim Grosbach01af6c42011-02-11 19:05:56 +0000546
Nirav Dave157891c2016-10-03 13:48:27 +0000547 if (!IsPeeking && CurChar == '#' && IsAtStartOfStatement) {
Nirav Davefd910412016-06-17 16:06:17 +0000548 // If this starts with a '#', this may be a cpp
549 // hash directive and otherwise a line comment.
550 AsmToken TokenBuf[2];
551 MutableArrayRef<AsmToken> Buf(TokenBuf, 2);
552 size_t num = peekTokens(Buf, true);
553 // There cannot be a space preceeding this
554 if (IsAtStartOfLine && num == 2 && TokenBuf[0].is(AsmToken::Integer) &&
555 TokenBuf[1].is(AsmToken::String)) {
556 CurPtr = TokStart; // reset curPtr;
557 StringRef s = LexUntilEndOfLine();
558 UnLex(TokenBuf[1]);
559 UnLex(TokenBuf[0]);
560 return AsmToken(AsmToken::HashDirective, s);
561 }
Kevin Enderbyecd879a2009-09-16 18:08:00 +0000562 return LexLineComment();
Kevin Enderby72553612011-09-13 23:45:18 +0000563 }
Nirav Davefd910412016-06-17 16:06:17 +0000564
565 if (isAtStartOfComment(TokStart))
566 return LexLineComment();
567
Jim Grosbacha3df87f2011-03-24 18:46:34 +0000568 if (isAtStatementSeparator(TokStart)) {
569 CurPtr += strlen(MAI.getSeparatorString()) - 1;
Nirav Davefd910412016-06-17 16:06:17 +0000570 IsAtStartOfLine = true;
571 IsAtStartOfStatement = true;
Jim Grosbacha3df87f2011-03-24 18:46:34 +0000572 return AsmToken(AsmToken::EndOfStatement,
573 StringRef(TokStart, strlen(MAI.getSeparatorString())));
574 }
Kevin Enderbyf92f9902009-09-04 21:45:34 +0000575
Jim Grosbacha9aa3c12011-09-15 16:52:06 +0000576 // If we're missing a newline at EOF, make sure we still get an
577 // EndOfStatement token before the Eof token.
Nirav Davefd910412016-06-17 16:06:17 +0000578 if (CurChar == EOF && !IsAtStartOfStatement) {
579 IsAtStartOfLine = true;
580 IsAtStartOfStatement = true;
Jim Grosbacha9aa3c12011-09-15 16:52:06 +0000581 return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
582 }
Nirav Davefd910412016-06-17 16:06:17 +0000583 IsAtStartOfLine = false;
584 bool OldIsAtStartOfStatement = IsAtStartOfStatement;
585 IsAtStartOfStatement = false;
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +0000586 switch (CurChar) {
587 default:
Daniel Dunbarb0ceb762010-05-06 14:46:38 +0000588 // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
589 if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
Chris Lattnerd0765612009-06-21 19:21:25 +0000590 return LexIdentifier();
Jim Grosbach01af6c42011-02-11 19:05:56 +0000591
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +0000592 // Unknown character, emit an error.
Chris Lattnerb0133452009-06-21 20:16:42 +0000593 return ReturnError(TokStart, "invalid character in input");
Nirav Davefd910412016-06-17 16:06:17 +0000594 case EOF:
595 IsAtStartOfLine = true;
596 IsAtStartOfStatement = true;
597 return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +0000598 case 0:
599 case ' ':
600 case '\t':
Nirav Davefd910412016-06-17 16:06:17 +0000601 IsAtStartOfStatement = OldIsAtStartOfStatement;
602 while (*CurPtr == ' ' || *CurPtr == '\t')
603 CurPtr++;
604 if (SkipSpace)
605 return LexToken(); // Ignore whitespace.
606 else
607 return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart));
608 case '\n':
Jim Grosbacha3df87f2011-03-24 18:46:34 +0000609 case '\r':
Nirav Davefd910412016-06-17 16:06:17 +0000610 IsAtStartOfLine = true;
611 IsAtStartOfStatement = true;
Jim Grosbacha3df87f2011-03-24 18:46:34 +0000612 return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
Daniel Dunbarf2dcd772009-07-28 16:08:33 +0000613 case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
614 case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
615 case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
616 case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
617 case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
618 case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
Kevin Enderby9c0f7fc2009-09-04 22:40:31 +0000619 case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
620 case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
621 case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
622 case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
Daniel Dunbarf2dcd772009-07-28 16:08:33 +0000623 case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
624 case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
Daniel Dunbarb0ceb762010-05-06 14:46:38 +0000625 case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
Matt Flemingec9d6fa2010-05-21 11:36:59 +0000626 case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1));
Rafael Espindola1134ab232011-06-05 02:43:45 +0000627 case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1));
Jim Grosbach01af6c42011-02-11 19:05:56 +0000628 case '=':
Richard Trieu7a083812016-02-18 22:09:30 +0000629 if (*CurPtr == '=') {
630 ++CurPtr;
631 return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
632 }
Daniel Dunbarf2dcd772009-07-28 16:08:33 +0000633 return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
Jim Grosbach01af6c42011-02-11 19:05:56 +0000634 case '|':
Richard Trieu7a083812016-02-18 22:09:30 +0000635 if (*CurPtr == '|') {
636 ++CurPtr;
637 return AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2));
638 }
Daniel Dunbarf2dcd772009-07-28 16:08:33 +0000639 return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1));
640 case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
Jim Grosbach01af6c42011-02-11 19:05:56 +0000641 case '&':
Richard Trieu7a083812016-02-18 22:09:30 +0000642 if (*CurPtr == '&') {
643 ++CurPtr;
644 return AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2));
645 }
Daniel Dunbarf2dcd772009-07-28 16:08:33 +0000646 return AsmToken(AsmToken::Amp, StringRef(TokStart, 1));
Jim Grosbach01af6c42011-02-11 19:05:56 +0000647 case '!':
Richard Trieu7a083812016-02-18 22:09:30 +0000648 if (*CurPtr == '=') {
649 ++CurPtr;
650 return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
651 }
Daniel Dunbarf2dcd772009-07-28 16:08:33 +0000652 return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1));
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000653 case '%':
654 if (MAI.hasMipsExpressions()) {
655 AsmToken::TokenKind Operator;
656 unsigned OperatorLength;
657
658 std::tie(Operator, OperatorLength) =
659 StringSwitch<std::pair<AsmToken::TokenKind, unsigned>>(
660 StringRef(CurPtr))
661 .StartsWith("call16", {AsmToken::PercentCall16, 7})
662 .StartsWith("call_hi", {AsmToken::PercentCall_Hi, 8})
663 .StartsWith("call_lo", {AsmToken::PercentCall_Lo, 8})
664 .StartsWith("dtprel_hi", {AsmToken::PercentDtprel_Hi, 10})
665 .StartsWith("dtprel_lo", {AsmToken::PercentDtprel_Lo, 10})
666 .StartsWith("got_disp", {AsmToken::PercentGot_Disp, 9})
667 .StartsWith("got_hi", {AsmToken::PercentGot_Hi, 7})
668 .StartsWith("got_lo", {AsmToken::PercentGot_Lo, 7})
669 .StartsWith("got_ofst", {AsmToken::PercentGot_Ofst, 9})
670 .StartsWith("got_page", {AsmToken::PercentGot_Page, 9})
671 .StartsWith("gottprel", {AsmToken::PercentGottprel, 9})
672 .StartsWith("got", {AsmToken::PercentGot, 4})
673 .StartsWith("gp_rel", {AsmToken::PercentGp_Rel, 7})
674 .StartsWith("higher", {AsmToken::PercentHigher, 7})
675 .StartsWith("highest", {AsmToken::PercentHighest, 8})
676 .StartsWith("hi", {AsmToken::PercentHi, 3})
677 .StartsWith("lo", {AsmToken::PercentLo, 3})
678 .StartsWith("neg", {AsmToken::PercentNeg, 4})
679 .StartsWith("pcrel_hi", {AsmToken::PercentPcrel_Hi, 9})
680 .StartsWith("pcrel_lo", {AsmToken::PercentPcrel_Lo, 9})
681 .StartsWith("tlsgd", {AsmToken::PercentTlsgd, 6})
682 .StartsWith("tlsldm", {AsmToken::PercentTlsldm, 7})
683 .StartsWith("tprel_hi", {AsmToken::PercentTprel_Hi, 9})
684 .StartsWith("tprel_lo", {AsmToken::PercentTprel_Lo, 9})
685 .Default({AsmToken::Percent, 1});
686
687 if (Operator != AsmToken::Percent) {
688 CurPtr += OperatorLength - 1;
689 return AsmToken(Operator, StringRef(TokStart, OperatorLength));
690 }
691 }
692 return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
Nirav Davefd910412016-06-17 16:06:17 +0000693 case '/':
694 IsAtStartOfStatement = OldIsAtStartOfStatement;
695 return LexSlash();
Kevin Enderbyf92f9902009-09-04 21:45:34 +0000696 case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
Roman Divacky71d29162010-12-18 08:56:37 +0000697 case '\'': return LexSingleQuote();
Chris Lattner419a9742009-06-21 19:56:35 +0000698 case '"': return LexQuote();
Chris Lattnerd0765612009-06-21 19:21:25 +0000699 case '0': case '1': case '2': case '3': case '4':
700 case '5': case '6': case '7': case '8': case '9':
701 return LexDigit();
Chris Lattnerf97d8bb2009-06-23 05:57:07 +0000702 case '<':
Daniel Dunbar7e8d6c72009-06-29 20:37:27 +0000703 switch (*CurPtr) {
Richard Trieu7a083812016-02-18 22:09:30 +0000704 case '<':
705 ++CurPtr;
706 return AsmToken(AsmToken::LessLess, StringRef(TokStart, 2));
707 case '=':
708 ++CurPtr;
709 return AsmToken(AsmToken::LessEqual, StringRef(TokStart, 2));
710 case '>':
711 ++CurPtr;
712 return AsmToken(AsmToken::LessGreater, StringRef(TokStart, 2));
713 default:
714 return AsmToken(AsmToken::Less, StringRef(TokStart, 1));
Chris Lattnerf97d8bb2009-06-23 05:57:07 +0000715 }
Chris Lattnerf97d8bb2009-06-23 05:57:07 +0000716 case '>':
Daniel Dunbar7e8d6c72009-06-29 20:37:27 +0000717 switch (*CurPtr) {
Richard Trieu7a083812016-02-18 22:09:30 +0000718 case '>':
719 ++CurPtr;
720 return AsmToken(AsmToken::GreaterGreater, StringRef(TokStart, 2));
721 case '=':
722 ++CurPtr;
723 return AsmToken(AsmToken::GreaterEqual, StringRef(TokStart, 2));
724 default:
725 return AsmToken(AsmToken::Greater, StringRef(TokStart, 1));
Chris Lattnerf97d8bb2009-06-23 05:57:07 +0000726 }
Jim Grosbach01af6c42011-02-11 19:05:56 +0000727
Chris Lattnerd0765612009-06-21 19:21:25 +0000728 // TODO: Quoted identifiers (objc methods etc)
729 // local labels: [0-9][:]
730 // Forward/backward labels: [0-9][fb]
731 // Integers, fp constants, character constants.
Chris Lattnerc8dfbcb2009-06-21 07:19:10 +0000732 }
Duncan Sands376c6f12009-06-22 06:59:32 +0000733}