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