TGLexer.cpp revision 63f97201dc9dcebbe84d1b73113166c64212b4b8
1a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
2a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner//
3a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner//                     The LLVM Compiler Infrastructure
4a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner//
5a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner// This file is distributed under the University of Illinois Open Source
6a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner// License. See LICENSE.TXT for details.
7a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner//
8a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner//===----------------------------------------------------------------------===//
9a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner//
10a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner// Implement the Lexer for TableGen.
11a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner//
12a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner//===----------------------------------------------------------------------===//
13a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
146aaca046d2896d8396314f4b1b6ad7a000034330Chris Lattner#include "TGLexer.h"
15a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include "llvm/Support/Streams.h"
16a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include "llvm/Support/MemoryBuffer.h"
17a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include <ostream>
18a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include "llvm/Config/config.h"
19a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include <cctype>
20a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include <cstdio>
21a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include <cstdlib>
22a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include <cstring>
23a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include <cerrno>
24a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnerusing namespace llvm;
25a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
26a8058744229a44e80f90c8530bb7fe47cbab1b70Chris LattnerTGLexer::TGLexer(MemoryBuffer *StartBuf) : CurLineNo(1), CurBuf(StartBuf) {
27a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurPtr = CurBuf->getBufferStart();
28a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  TokStart = 0;
29a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
30a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
31a8058744229a44e80f90c8530bb7fe47cbab1b70Chris LattnerTGLexer::~TGLexer() {
32a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (!IncludeStack.empty()) {
33a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    delete IncludeStack.back().Buffer;
34a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    IncludeStack.pop_back();
35a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
36a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  delete CurBuf;
37a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
38a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
39a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// ReturnError - Set the error to the specified string at the specified
40c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner/// location.  This is defined to always return tgtok::Error.
41c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattnertgtok::TokKind TGLexer::ReturnError(const char *Loc, const std::string &Msg) {
42c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  PrintError(Loc, Msg);
43c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  return tgtok::Error;
44c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner}
45c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
46a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnervoid TGLexer::PrintIncludeStack(std::ostream &OS) const {
47c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  for (unsigned i = 0, e = IncludeStack.size(); i != e; ++i)
48a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    OS << "Included from " << IncludeStack[i].Buffer->getBufferIdentifier()
49a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner       << ":" << IncludeStack[i].LineNo << ":\n";
50a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  OS << "Parsing " << CurBuf->getBufferIdentifier() << ":"
51a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner     << CurLineNo << ": ";
52a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
53c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
54a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// PrintError - Print the error at the specified location.
55a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnervoid TGLexer::PrintError(const char *ErrorLoc,  const std::string &Msg) const {
56a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  PrintIncludeStack(*cerr.stream());
57a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  cerr << Msg << "\n";
58a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  assert(ErrorLoc && "Location not specified!");
59a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
60a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Scan backward to find the start of the line.
61c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  const char *LineStart = ErrorLoc;
62c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  while (LineStart != CurBuf->getBufferStart() &&
63c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner         LineStart[-1] != '\n' && LineStart[-1] != '\r')
64c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner    --LineStart;
65c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  // Get the end of the line.
66c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  const char *LineEnd = ErrorLoc;
67c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  while (LineEnd != CurBuf->getBufferEnd() &&
68c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner         LineEnd[0] != '\n' && LineEnd[0] != '\r')
69c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner    ++LineEnd;
70c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  // Print out the line.
71c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  cerr << std::string(LineStart, LineEnd) << "\n";
72c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  // Print out spaces before the carat.
73c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  for (const char *Pos = LineStart; Pos != ErrorLoc; ++Pos)
74c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner    cerr << (*Pos == '\t' ? '\t' : ' ');
75c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  cerr << "^\n";
76c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner}
77c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
78c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattnerint TGLexer::getNextChar() {
79c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  char CurChar = *CurPtr++;
80c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  switch (CurChar) {
81c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  default:
82c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner    return (unsigned char)CurChar;
83c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  case 0:
84c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner    // A nul character in the stream is either the end of the current buffer or
85a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // a random nul in the file.  Disambiguate that here.
86a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (CurPtr-1 != CurBuf->getBufferEnd())
87a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return 0;  // Just whitespace.
88a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
89c1819188b6c971b91c680a9a3c077b84a110e5fdChris Lattner    // If this is the end of an included file, pop the parent file off the
90a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // include stack.
91a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (!IncludeStack.empty()) {
92a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      delete CurBuf;
93a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      CurBuf = IncludeStack.back().Buffer;
94a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      CurLineNo = IncludeStack.back().LineNo;
95a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      CurPtr = IncludeStack.back().CurPtr;
96a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      IncludeStack.pop_back();
97a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return getNextChar();
98a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
99a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
100a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Otherwise, return end of file.
101a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    --CurPtr;  // Another call to lex will return EOF again.
102a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return EOF;
103a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\n':
104a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\r':
105a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Handle the newline character by ignoring it and incrementing the line
106a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // count.  However, be careful about 'dos style' files with \n\r in them.
107a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Only treat a \n\r or \r\n as a single line.
108a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
109a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        *CurPtr != CurChar)
110a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CurPtr;  // Eat the two char newline sequence.
111a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
112a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurLineNo;
113a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return '\n';
114a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
115a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
116a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
117c1819188b6c971b91c680a9a3c077b84a110e5fdChris Lattnertgtok::TokKind TGLexer::LexToken() {
118a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  TokStart = CurPtr;
119a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // This always consumes at least one character.
120a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  int CurChar = getNextChar();
121a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
122a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  switch (CurChar) {
123a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  default:
124a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Handle letters: [a-zA-Z_]
125a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (isalpha(CurChar) || CurChar == '_')
126a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return LexIdentifier();
127a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
128a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Unknown character, emit an error.
129a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return ReturnError(TokStart, "Unexpected character");
130a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case EOF: return tgtok::Eof;
131a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case ':': return tgtok::colon;
132a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case ';': return tgtok::semi;
133a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '.': return tgtok::period;
134a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case ',': return tgtok::comma;
135a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '<': return tgtok::less;
136a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '>': return tgtok::greater;
137a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case ']': return tgtok::r_square;
138a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '{': return tgtok::l_brace;
139a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '}': return tgtok::r_brace;
140a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '(': return tgtok::l_paren;
141a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case ')': return tgtok::r_paren;
142a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '=': return tgtok::equal;
143a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '?': return tgtok::question;
144a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
145a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case 0:
146a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case ' ':
147a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\t':
148a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\n':
149a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\r':
150a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Ignore whitespace.
151a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return LexToken();
152a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '/':
153a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // If this is the start of a // comment, skip until the end of the line or
154a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // the end of the buffer.
155a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (*CurPtr == '/')
156a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      SkipBCPLComment();
157a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    else if (*CurPtr == '*') {
158a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (SkipCComment())
159a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        return tgtok::Error;
160a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    } else // Otherwise, this is an error.
161a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return ReturnError(TokStart, "Unexpected character");
162a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return LexToken();
163a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '-': case '+':
164a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '0': case '1': case '2': case '3': case '4': case '5': case '6':
165a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '7': case '8': case '9':
166a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return LexNumber();
167a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '"': return LexString();
168a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '$': return LexVarName();
169a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '[': return LexBracket();
170a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '!': return LexExclaim();
171a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
172c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner}
173c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
174c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner/// LexString - Lex "[^"]*"
175c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattnertgtok::TokKind TGLexer::LexString() {
176c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  const char *StrStart = CurPtr;
177a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
178a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (*CurPtr != '"') {
179a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // If we hit the end of the buffer, report an error.
180a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
181a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return ReturnError(StrStart, "End of file in string literal");
182a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
183a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (*CurPtr == '\n' || *CurPtr == '\r')
184a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return ReturnError(StrStart, "End of line in string literal");
185a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
186a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
187a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
188a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
189a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurStrVal.assign(StrStart, CurPtr);
190a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  ++CurPtr;
191a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  return tgtok::StrVal;
192a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
193a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
194a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnertgtok::TokKind TGLexer::LexVarName() {
195a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
196a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return ReturnError(TokStart, "Invalid variable name");
197a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
198a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Otherwise, we're ok, consume the rest of the characters.
199a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  const char *VarNameStart = CurPtr++;
200a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
201a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
202a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
203a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
204a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurStrVal.assign(VarNameStart, CurPtr);
205a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  return tgtok::VarName;
206a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
207a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
208a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
209a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnertgtok::TokKind TGLexer::LexIdentifier() {
210a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // The first letter is [a-zA-Z_].
211a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  const char *IdentStart = TokStart;
212a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
213a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Match the rest of the identifier regex: [0-9a-zA-Z_]*
214a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
215a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
216a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
217a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Check to see if this identifier is a keyword.
218a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  unsigned Len = CurPtr-IdentStart;
219a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
220a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 3 && !memcmp(IdentStart, "int", 3)) return tgtok::Int;
221a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 3 && !memcmp(IdentStart, "bit", 3)) return tgtok::Bit;
222a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 4 && !memcmp(IdentStart, "bits", 4)) return tgtok::Bits;
223a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 6 && !memcmp(IdentStart, "string", 6)) return tgtok::String;
224a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 4 && !memcmp(IdentStart, "list", 4)) return tgtok::List;
225a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 4 && !memcmp(IdentStart, "code", 4)) return tgtok::Code;
226a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 3 && !memcmp(IdentStart, "dag", 3)) return tgtok::Dag;
227a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
228a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 5 && !memcmp(IdentStart, "class", 5)) return tgtok::Class;
229a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 3 && !memcmp(IdentStart, "def", 3)) return tgtok::Def;
230a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 4 && !memcmp(IdentStart, "defm", 4)) return tgtok::Defm;
231a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 10 && !memcmp(IdentStart, "multiclass", 10))
232a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return tgtok::MultiClass;
233a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 5 && !memcmp(IdentStart, "field", 5)) return tgtok::Field;
234a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 3 && !memcmp(IdentStart, "let", 3)) return tgtok::Let;
235a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 2 && !memcmp(IdentStart, "in", 2)) return tgtok::In;
236a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
237a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 7 && !memcmp(IdentStart, "include", 7)) {
238a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (LexInclude()) return tgtok::Error;
239a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return Lex();
240a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
241c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
242a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurStrVal.assign(IdentStart, CurPtr);
243a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  return tgtok::Id;
244a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
245c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
246a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// LexInclude - We just read the "include" token.  Get the string token that
247a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// comes next and enter the include.
248a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnerbool TGLexer::LexInclude() {
249a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // The token after the include must be a string.
250a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  tgtok::TokKind Tok = LexToken();
251a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Tok == tgtok::Error) return true;
252a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Tok != tgtok::StrVal) {
253a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    PrintError(getLoc(), "Expected filename after include");
254a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return true;
255a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
256a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
257a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Get the string.
258a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  std::string Filename = CurStrVal;
259a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
260a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Try to find the file.
261a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  MemoryBuffer *NewBuf = MemoryBuffer::getFile(Filename.c_str());
262a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
263c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  // If the file didn't exist directly, see if it's in an include path.
264a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBuf; ++i) {
265a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    std::string IncFile = IncludeDirectories[i] + "/" + Filename;
266a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    NewBuf = MemoryBuffer::getFile(IncFile.c_str());
267a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
268a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
269a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (NewBuf == 0) {
270a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    PrintError(getLoc(), "Could not find include file '" + Filename + "'");
271a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return true;
272a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
273a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
274a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Save the line number and lex buffer of the includer.
275a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  IncludeStack.push_back(IncludeRec(CurBuf, CurPtr, CurLineNo));
276a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
277a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurLineNo = 1;  // Reset line numbering.
278a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurBuf = NewBuf;
279a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurPtr = CurBuf->getBufferStart();
280a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  return false;
281a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
282a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
283a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnervoid TGLexer::SkipBCPLComment() {
284a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  ++CurPtr;  // skip the second slash.
285a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (1) {
286a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    switch (*CurPtr) {
287a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case '\n':
288a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case '\r':
289a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return;  // Newline is end of comment.
290a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case 0:
291a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      // If this is the end of the buffer, end the comment.
292a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (CurPtr == CurBuf->getBufferEnd())
293a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        return;
294a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      break;
295a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
296a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Otherwise, skip the character.
297c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner    ++CurPtr;
298a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
299a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
300a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
301a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// SkipCComment - This skips C-style /**/ comments.  The only difference from C
302a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// is that we allow nesting.
303a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnerbool TGLexer::SkipCComment() {
304a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  ++CurPtr;  // skip the star.
305c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  unsigned CommentDepth = 1;
306a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
307a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (1) {
308a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    int CurChar = getNextChar();
309a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    switch (CurChar) {
310a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case EOF:
311a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      PrintError(TokStart, "Unterminated comment!");
312a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return true;
313a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case '*':
314a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      // End of the comment?
315a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (CurPtr[0] != '/') break;
316a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
317a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CurPtr;   // End the */.
318a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (--CommentDepth == 0)
319a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        return false;
320a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      break;
321a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case '/':
322a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      // Start of a nested comment?
323a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (CurPtr[0] != '*') break;
324a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CurPtr;
325a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CommentDepth;
326a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      break;
327a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
328a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
329a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
330a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
331a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// LexNumber - Lex:
332a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner///    [-+]?[0-9]+
333a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner///    0x[0-9a-fA-F]+
334a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner///    0b[01]+
335a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnertgtok::TokKind TGLexer::LexNumber() {
336a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (CurPtr[-1] == '0') {
337a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (CurPtr[0] == 'x') {
338a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CurPtr;
339c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner      const char *NumStart = CurPtr;
340c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner      while (isxdigit(CurPtr[0]))
341c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner        ++CurPtr;
342c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
343a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      // Requires at least one hex digit.
344a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (CurPtr == NumStart)
345a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        return ReturnError(CurPtr-2, "Invalid hexadecimal number");
346a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
347a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      errno = 0;
348a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      CurIntVal = strtoll(NumStart, 0, 16);
349a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (errno == EINVAL)
350c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner        return ReturnError(CurPtr-2, "Invalid hexadecimal number");
351c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner      if (errno == ERANGE) {
352c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner        errno = 0;
353c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner        CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
354a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        if (errno == EINVAL)
355a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner          return ReturnError(CurPtr-2, "Invalid hexadecimal number");
356a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        if (errno == ERANGE)
357a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner          return ReturnError(CurPtr-2, "Hexadecimal number out of range");
358a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      }
359a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return tgtok::IntVal;
360a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    } else if (CurPtr[0] == 'b') {
361a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CurPtr;
362a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      const char *NumStart = CurPtr;
363a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      while (CurPtr[0] == '0' || CurPtr[0] == '1')
364a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        ++CurPtr;
365a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
366a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      // Requires at least one binary digit.
367a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (CurPtr == NumStart)
368a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        return ReturnError(CurPtr-2, "Invalid binary number");
369a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      CurIntVal = strtoll(NumStart, 0, 2);
370a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return tgtok::IntVal;
371a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
372a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
373a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
374a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Check for a sign without a digit.
375a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (!isdigit(CurPtr[0])) {
376a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (CurPtr[-1] == '-')
377a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return tgtok::minus;
378a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    else if (CurPtr[-1] == '+')
379a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return tgtok::plus;
380a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
381a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
382a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (isdigit(CurPtr[0]))
383a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
384a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurIntVal = strtoll(TokStart, 0, 10);
385a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  return tgtok::IntVal;
386a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
387a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
388a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// LexBracket - We just read '['.  If this is a code block, return it,
389a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// otherwise return the bracket.  Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
390a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnertgtok::TokKind TGLexer::LexBracket() {
391a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (CurPtr[0] != '{')
392c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner    return tgtok::l_square;
393a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  ++CurPtr;
394a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  const char *CodeStart = CurPtr;
395a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (1) {
396a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    int Char = getNextChar();
397a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (Char == EOF) break;
398a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
399a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (Char != '}') continue;
400a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
401a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    Char = getNextChar();
402a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (Char == EOF) break;
403a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (Char == ']') {
404a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      CurStrVal.assign(CodeStart, CurPtr-2);
405a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return tgtok::CodeFragment;
406a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
407a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
408a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
409a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  return ReturnError(CodeStart-2, "Unterminated Code Block");
410a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
411a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
412a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
413c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattnertgtok::TokKind TGLexer::LexExclaim() {
414a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (!isalpha(*CurPtr))
415a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return ReturnError(CurPtr-1, "Invalid \"!operator\"");
416a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
417a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  const char *Start = CurPtr++;
418a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (isalpha(*CurPtr))
419a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
420a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
421a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Check to see which operator this is.
422a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  unsigned Len = CurPtr-Start;
423a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
424a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 3 && !memcmp(Start, "con", 3)) return tgtok::XConcat;
425a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 3 && !memcmp(Start, "sra", 3)) return tgtok::XSRA;
426a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 3 && !memcmp(Start, "srl", 3)) return tgtok::XSRL;
427a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 3 && !memcmp(Start, "shl", 3)) return tgtok::XSHL;
428a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat;
429a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
430a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  return ReturnError(Start-1, "Unknown operator");
431a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
432a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
433a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner