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"
15cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling#include "llvm/ADT/StringSwitch.h"
16cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling#include "llvm/ADT/Twine.h"
17d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Config/config.h" // for strtoull()/strtoll() define
18d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/MemoryBuffer.h"
19d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/SourceMgr.h"
20d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/TableGen/Error.h"
21a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner#include <cctype>
22d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include <cerrno>
234520dd2b7b20af07d5a3e4d06d964a532044eb10Duncan Sands#include <cstdio>
24ae9f3a3b7c915f725aef5a7250e88eaeddda03c6Anton Korobeynikov#include <cstdlib>
25ae9f3a3b7c915f725aef5a7250e88eaeddda03c6Anton Korobeynikov#include <cstring>
268cc300cb3415d1d806e6f9e6ecb7c3d3f8341ad2Dylan Noblesmith
27a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnerusing namespace llvm;
28a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
298070ea3f068980d08cc10381f4c9369d19a91353Chris LattnerTGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
30aa739d26b1e65aec7f9afa1cde7e069c081ea355Chris Lattner  CurBuffer = 0;
31aa739d26b1e65aec7f9afa1cde7e069c081ea355Chris Lattner  CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
32a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurPtr = CurBuf->getBufferStart();
3356a9fcfd1e19c7adfcc4c948e2f5e471ca8ed241Chris Lattner  TokStart = 0;
34a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
35a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
361e3a8a492471f5dc3f50452af9eb9a2dfb1aeb39Chris LattnerSMLoc TGLexer::getLoc() const {
371e3a8a492471f5dc3f50452af9eb9a2dfb1aeb39Chris Lattner  return SMLoc::getFromPointer(TokStart);
381c8ae59dfdc85d917db0333ae0b93e2be4ca6c36Chris Lattner}
391c8ae59dfdc85d917db0333ae0b93e2be4ca6c36Chris Lattner
40c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner/// ReturnError - Set the error to the specified string at the specified
41f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner/// location.  This is defined to always return tgtok::Error.
42d1e1703c39742f3c9fc3d27a442ff59bbdbfb5aaBenjamin Kramertgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
43c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  PrintError(Loc, Msg);
44f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  return tgtok::Error;
45a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
46a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
47a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnerint TGLexer::getNextChar() {
48a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  char CurChar = *CurPtr++;
49a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  switch (CurChar) {
50a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  default:
51c1819188b6c971b91c680a9a3c077b84a110e5fdChris Lattner    return (unsigned char)CurChar;
52aa739d26b1e65aec7f9afa1cde7e069c081ea355Chris Lattner  case 0: {
53a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // A nul character in the stream is either the end of the current buffer or
54a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // a random nul in the file.  Disambiguate that here.
55a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (CurPtr-1 != CurBuf->getBufferEnd())
56a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return 0;  // Just whitespace.
57a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
58a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // If this is the end of an included file, pop the parent file off the
59a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // include stack.
601e3a8a492471f5dc3f50452af9eb9a2dfb1aeb39Chris Lattner    SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
611e3a8a492471f5dc3f50452af9eb9a2dfb1aeb39Chris Lattner    if (ParentIncludeLoc != SMLoc()) {
62aa739d26b1e65aec7f9afa1cde7e069c081ea355Chris Lattner      CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
63aa739d26b1e65aec7f9afa1cde7e069c081ea355Chris Lattner      CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
641c8ae59dfdc85d917db0333ae0b93e2be4ca6c36Chris Lattner      CurPtr = ParentIncludeLoc.getPointer();
65a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return getNextChar();
66a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
67a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
68a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Otherwise, return end of file.
69a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    --CurPtr;  // Another call to lex will return EOF again.
70a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return EOF;
71aa739d26b1e65aec7f9afa1cde7e069c081ea355Chris Lattner  }
72a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\n':
73a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\r':
74a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Handle the newline character by ignoring it and incrementing the line
75a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // count.  However, be careful about 'dos style' files with \n\r in them.
76a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Only treat a \n\r or \r\n as a single line.
77a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
78a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        *CurPtr != CurChar)
79c1819188b6c971b91c680a9a3c077b84a110e5fdChris Lattner      ++CurPtr;  // Eat the two char newline sequence.
80a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return '\n';
81a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
82a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
83a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
84a761f92cd38572dd65cc995c5f59b9c2c0f51068David Greeneint TGLexer::peekNextChar(int Index) {
85a761f92cd38572dd65cc995c5f59b9c2c0f51068David Greene  return *(CurPtr + Index);
86a761f92cd38572dd65cc995c5f59b9c2c0f51068David Greene}
87a761f92cd38572dd65cc995c5f59b9c2c0f51068David Greene
88f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattnertgtok::TokKind TGLexer::LexToken() {
8956a9fcfd1e19c7adfcc4c948e2f5e471ca8ed241Chris Lattner  TokStart = CurPtr;
90a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // This always consumes at least one character.
91a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  int CurChar = getNextChar();
92a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
93a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  switch (CurChar) {
94a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  default:
95d3d1cad535d1c88e13e8e082c136260ee624967fDavid Greene    // Handle letters: [a-zA-Z_]
96d3d1cad535d1c88e13e8e082c136260ee624967fDavid Greene    if (isalpha(CurChar) || CurChar == '_')
97a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return LexIdentifier();
98d3d1cad535d1c88e13e8e082c136260ee624967fDavid Greene
99f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    // Unknown character, emit an error.
100f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    return ReturnError(TokStart, "Unexpected character");
101f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case EOF: return tgtok::Eof;
102f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case ':': return tgtok::colon;
103f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case ';': return tgtok::semi;
104f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case '.': return tgtok::period;
105f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case ',': return tgtok::comma;
106f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case '<': return tgtok::less;
107f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case '>': return tgtok::greater;
108f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case ']': return tgtok::r_square;
109f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case '{': return tgtok::l_brace;
110f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case '}': return tgtok::r_brace;
111f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case '(': return tgtok::l_paren;
112f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case ')': return tgtok::r_paren;
113f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case '=': return tgtok::equal;
114f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  case '?': return tgtok::question;
115d3d1cad535d1c88e13e8e082c136260ee624967fDavid Greene  case '#': return tgtok::paste;
116f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner
117a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case 0:
118a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case ' ':
119a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\t':
120a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\n':
121a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '\r':
122a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Ignore whitespace.
123a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return LexToken();
124a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '/':
125a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // If this is the start of a // comment, skip until the end of the line or
126a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // the end of the buffer.
127a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (*CurPtr == '/')
128a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      SkipBCPLComment();
129a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    else if (*CurPtr == '*') {
130a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (SkipCComment())
131f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner        return tgtok::Error;
132f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    } else // Otherwise, this is an error.
133f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      return ReturnError(TokStart, "Unexpected character");
134a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return LexToken();
135a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '-': case '+':
136a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '0': case '1': case '2': case '3': case '4': case '5': case '6':
1377efe93625183a52733c23adc02c5c9c4337a7970David Greene  case '7': case '8': case '9': {
1387efe93625183a52733c23adc02c5c9c4337a7970David Greene    int NextChar = 0;
1397efe93625183a52733c23adc02c5c9c4337a7970David Greene    if (isdigit(CurChar)) {
1407efe93625183a52733c23adc02c5c9c4337a7970David Greene      // Allow identifiers to start with a number if it is followed by
1417efe93625183a52733c23adc02c5c9c4337a7970David Greene      // an identifier.  This can happen with paste operations like
1427efe93625183a52733c23adc02c5c9c4337a7970David Greene      // foo#8i.
1437efe93625183a52733c23adc02c5c9c4337a7970David Greene      int i = 0;
1447efe93625183a52733c23adc02c5c9c4337a7970David Greene      do {
1457efe93625183a52733c23adc02c5c9c4337a7970David Greene        NextChar = peekNextChar(i++);
1467efe93625183a52733c23adc02c5c9c4337a7970David Greene      } while (isdigit(NextChar));
1477efe93625183a52733c23adc02c5c9c4337a7970David Greene
1487efe93625183a52733c23adc02c5c9c4337a7970David Greene      if (NextChar == 'x' || NextChar == 'b') {
1497efe93625183a52733c23adc02c5c9c4337a7970David Greene        // If this is [0-9]b[01] or [0-9]x[0-9A-fa-f] this is most
1507efe93625183a52733c23adc02c5c9c4337a7970David Greene        // likely a number.
1517efe93625183a52733c23adc02c5c9c4337a7970David Greene        int NextNextChar = peekNextChar(i);
1527efe93625183a52733c23adc02c5c9c4337a7970David Greene        switch (NextNextChar) {
1537efe93625183a52733c23adc02c5c9c4337a7970David Greene        default:
1547efe93625183a52733c23adc02c5c9c4337a7970David Greene          break;
1557efe93625183a52733c23adc02c5c9c4337a7970David Greene        case '0': case '1':
1567efe93625183a52733c23adc02c5c9c4337a7970David Greene          if (NextChar == 'b')
1577efe93625183a52733c23adc02c5c9c4337a7970David Greene            return LexNumber();
1587efe93625183a52733c23adc02c5c9c4337a7970David Greene          // Fallthrough
1597efe93625183a52733c23adc02c5c9c4337a7970David Greene        case '2': case '3': case '4': case '5':
1607efe93625183a52733c23adc02c5c9c4337a7970David Greene        case '6': case '7': case '8': case '9':
1617efe93625183a52733c23adc02c5c9c4337a7970David Greene        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
1627efe93625183a52733c23adc02c5c9c4337a7970David Greene        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
1637efe93625183a52733c23adc02c5c9c4337a7970David Greene          if (NextChar == 'x')
1647efe93625183a52733c23adc02c5c9c4337a7970David Greene            return LexNumber();
1657efe93625183a52733c23adc02c5c9c4337a7970David Greene          break;
1667efe93625183a52733c23adc02c5c9c4337a7970David Greene        }
1677efe93625183a52733c23adc02c5c9c4337a7970David Greene      }
1687efe93625183a52733c23adc02c5c9c4337a7970David Greene    }
1697efe93625183a52733c23adc02c5c9c4337a7970David Greene
1707efe93625183a52733c23adc02c5c9c4337a7970David Greene    if (isalpha(NextChar) || NextChar == '_')
1717efe93625183a52733c23adc02c5c9c4337a7970David Greene      return LexIdentifier();
1727efe93625183a52733c23adc02c5c9c4337a7970David Greene
173a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return LexNumber();
1747efe93625183a52733c23adc02c5c9c4337a7970David Greene  }
175a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '"': return LexString();
176a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '$': return LexVarName();
177a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '[': return LexBracket();
178a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  case '!': return LexExclaim();
179a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
180a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
181a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
182a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// LexString - Lex "[^"]*"
183f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattnertgtok::TokKind TGLexer::LexString() {
184a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  const char *StrStart = CurPtr;
185a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
186ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner  CurStrVal = "";
187ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner
188a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (*CurPtr != '"') {
189a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // If we hit the end of the buffer, report an error.
190c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner    if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
191c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner      return ReturnError(StrStart, "End of file in string literal");
192c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
193c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner    if (*CurPtr == '\n' || *CurPtr == '\r')
194c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner      return ReturnError(StrStart, "End of line in string literal");
195a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
196ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    if (*CurPtr != '\\') {
197ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner      CurStrVal += *CurPtr++;
198ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner      continue;
199ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    }
200ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner
201a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
202ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner
203ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    switch (*CurPtr) {
204ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    case '\\': case '\'': case '"':
205ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner      // These turn into their literal character.
206ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner      CurStrVal += *CurPtr++;
207ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner      break;
208e023bb693605f0354bba176f7d87a21cc7aa3785Chris Lattner    case 't':
2097f3b28a7867a35ec56a4ed80546e64995d69483eChris Lattner      CurStrVal += '\t';
210e023bb693605f0354bba176f7d87a21cc7aa3785Chris Lattner      ++CurPtr;
211e023bb693605f0354bba176f7d87a21cc7aa3785Chris Lattner      break;
212e023bb693605f0354bba176f7d87a21cc7aa3785Chris Lattner    case 'n':
2137f3b28a7867a35ec56a4ed80546e64995d69483eChris Lattner      CurStrVal += '\n';
214e023bb693605f0354bba176f7d87a21cc7aa3785Chris Lattner      ++CurPtr;
215e023bb693605f0354bba176f7d87a21cc7aa3785Chris Lattner      break;
216e023bb693605f0354bba176f7d87a21cc7aa3785Chris Lattner
217ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    case '\n':
218ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    case '\r':
219ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner      return ReturnError(CurPtr, "escaped newlines not supported in tblgen");
220ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner
221ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    // If we hit the end of the buffer, report an error.
222ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    case '\0':
223ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner      if (CurPtr == CurBuf->getBufferEnd())
224ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner        return ReturnError(StrStart, "End of file in string literal");
225ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner      // FALL THROUGH
226ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    default:
227ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner      return ReturnError(CurPtr, "invalid escape in string literal");
228ea9f4df616995a70fff368c2cc0cf69df636aeafChris Lattner    }
229a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
230a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
231a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  ++CurPtr;
232f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  return tgtok::StrVal;
233a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
234a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
235f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattnertgtok::TokKind TGLexer::LexVarName() {
236a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
237f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    return ReturnError(TokStart, "Invalid variable name");
238a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
239a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Otherwise, we're ok, consume the rest of the characters.
240a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  const char *VarNameStart = CurPtr++;
241a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
242a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
243a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
244a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
245f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  CurStrVal.assign(VarNameStart, CurPtr);
246f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  return tgtok::VarName;
247a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
248a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
249a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
250f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattnertgtok::TokKind TGLexer::LexIdentifier() {
251c2b0875b8d9e08a19f9ed9fae02fb121e4fc4a1fChris Lattner  // The first letter is [a-zA-Z_#].
252f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  const char *IdentStart = TokStart;
25337d42af584f07c78d990a8f1bb128046aab2182dBenjamin Kramer
254c2b0875b8d9e08a19f9ed9fae02fb121e4fc4a1fChris Lattner  // Match the rest of the identifier regex: [0-9a-zA-Z_#]*
255d3d1cad535d1c88e13e8e082c136260ee624967fDavid Greene  while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
256c2b0875b8d9e08a19f9ed9fae02fb121e4fc4a1fChris Lattner    ++CurPtr;
25737d42af584f07c78d990a8f1bb128046aab2182dBenjamin Kramer
258a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Check to see if this identifier is a keyword.
25937d42af584f07c78d990a8f1bb128046aab2182dBenjamin Kramer  StringRef Str(IdentStart, CurPtr-IdentStart);
26037d42af584f07c78d990a8f1bb128046aab2182dBenjamin Kramer
26137d42af584f07c78d990a8f1bb128046aab2182dBenjamin Kramer  if (Str == "include") {
262f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    if (LexInclude()) return tgtok::Error;
263f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    return Lex();
264a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
26537d42af584f07c78d990a8f1bb128046aab2182dBenjamin Kramer
266ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer  tgtok::TokKind Kind = StringSwitch<tgtok::TokKind>(Str)
267ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("int", tgtok::Int)
268ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("bit", tgtok::Bit)
269ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("bits", tgtok::Bits)
270ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("string", tgtok::String)
271ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("list", tgtok::List)
272ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("code", tgtok::Code)
273ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("dag", tgtok::Dag)
274ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("class", tgtok::Class)
275ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("def", tgtok::Def)
276cebb4ee93a0064e4a2cb1fd1da7455b01e5655cbDavid Greene    .Case("foreach", tgtok::Foreach)
277ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("defm", tgtok::Defm)
278ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("multiclass", tgtok::MultiClass)
279ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("field", tgtok::Field)
280ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("let", tgtok::Let)
281ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Case("in", tgtok::In)
282ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    .Default(tgtok::Id);
283ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer
284ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer  if (Kind == tgtok::Id)
285ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer    CurStrVal.assign(Str.begin(), Str.end());
286ee573189c653c3261102ccd627bb571ab7535034Benjamin Kramer  return Kind;
287a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
288a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
289a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// LexInclude - We just read the "include" token.  Get the string token that
290a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// comes next and enter the include.
291a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnerbool TGLexer::LexInclude() {
292a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // The token after the include must be a string.
293f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  tgtok::TokKind Tok = LexToken();
294f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  if (Tok == tgtok::Error) return true;
295f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  if (Tok != tgtok::StrVal) {
296f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    PrintError(getLoc(), "Expected filename after include");
297a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return true;
298a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
299a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
300a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Get the string.
301f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  std::string Filename = CurStrVal;
302dd137903e47fdb5822724baaddae88f119badc86Joerg Sonnenberger  std::string IncludedFile;
303a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
3047ee5d5f97b3fa709038ff7fd640dc775efaadc26Chris Lattner
305dd137903e47fdb5822724baaddae88f119badc86Joerg Sonnenberger  CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr),
306dd137903e47fdb5822724baaddae88f119badc86Joerg Sonnenberger                                    IncludedFile);
307d926e048c1409d3105e1ccd166e9369ab454a81dChris Lattner  if (CurBuffer == -1) {
308f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    PrintError(getLoc(), "Could not find include file '" + Filename + "'");
309a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    return true;
310a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
311a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
312a170f520a990a50c35f72d81b4415dc4c3ec50deSean Silva  DependenciesMapTy::const_iterator Found = Dependencies.find(IncludedFile);
313a170f520a990a50c35f72d81b4415dc4c3ec50deSean Silva  if (Found != Dependencies.end()) {
314a170f520a990a50c35f72d81b4415dc4c3ec50deSean Silva    PrintError(getLoc(),
315a170f520a990a50c35f72d81b4415dc4c3ec50deSean Silva               "File '" + IncludedFile + "' has already been included.");
316a170f520a990a50c35f72d81b4415dc4c3ec50deSean Silva    SrcMgr.PrintMessage(Found->second, SourceMgr::DK_Note,
317a170f520a990a50c35f72d81b4415dc4c3ec50deSean Silva                        "previously included here");
318a170f520a990a50c35f72d81b4415dc4c3ec50deSean Silva    return true;
319a170f520a990a50c35f72d81b4415dc4c3ec50deSean Silva  }
320a170f520a990a50c35f72d81b4415dc4c3ec50deSean Silva  Dependencies.insert(std::make_pair(IncludedFile, getLoc()));
321a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Save the line number and lex buffer of the includer.
3227ee5d5f97b3fa709038ff7fd640dc775efaadc26Chris Lattner  CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
323a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  CurPtr = CurBuf->getBufferStart();
324a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  return false;
325a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
326a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
327a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnervoid TGLexer::SkipBCPLComment() {
328a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  ++CurPtr;  // skip the second slash.
329a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (1) {
330a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    switch (*CurPtr) {
331a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case '\n':
332a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case '\r':
333a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return;  // Newline is end of comment.
334a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case 0:
335a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      // If this is the end of the buffer, end the comment.
336a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (CurPtr == CurBuf->getBufferEnd())
337a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        return;
338a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      break;
339a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
340a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    // Otherwise, skip the character.
341a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
342a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
343a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
344a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
345a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// SkipCComment - This skips C-style /**/ comments.  The only difference from C
346a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// is that we allow nesting.
347a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattnerbool TGLexer::SkipCComment() {
348a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  ++CurPtr;  // skip the star.
349a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  unsigned CommentDepth = 1;
350a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
351a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (1) {
352a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    int CurChar = getNextChar();
353a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    switch (CurChar) {
354a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case EOF:
355f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      PrintError(TokStart, "Unterminated comment!");
356a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      return true;
357a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case '*':
358a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      // End of the comment?
359a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (CurPtr[0] != '/') break;
360a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
361a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CurPtr;   // End the */.
362a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (--CommentDepth == 0)
363a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        return false;
364a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      break;
365a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    case '/':
366a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      // Start of a nested comment?
367a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      if (CurPtr[0] != '*') break;
368a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CurPtr;
369a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CommentDepth;
370a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      break;
371a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
372a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
373a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
374a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
375a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// LexNumber - Lex:
376a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner///    [-+]?[0-9]+
377a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner///    0x[0-9a-fA-F]+
378a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner///    0b[01]+
379f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattnertgtok::TokKind TGLexer::LexNumber() {
380a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (CurPtr[-1] == '0') {
381a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (CurPtr[0] == 'x') {
382a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CurPtr;
383f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      const char *NumStart = CurPtr;
384a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      while (isxdigit(CurPtr[0]))
385a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        ++CurPtr;
386a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
387c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner      // Requires at least one hex digit.
388c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner      if (CurPtr == NumStart)
3894226bb02fb623e2aa39cad819140df541f95bd8bChris Lattner        return ReturnError(TokStart, "Invalid hexadecimal number");
390c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
39163f97201dc9dcebbe84d1b73113166c64212b4b8Dan Gohman      errno = 0;
392f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      CurIntVal = strtoll(NumStart, 0, 16);
39363f97201dc9dcebbe84d1b73113166c64212b4b8Dan Gohman      if (errno == EINVAL)
3944226bb02fb623e2aa39cad819140df541f95bd8bChris Lattner        return ReturnError(TokStart, "Invalid hexadecimal number");
39563f97201dc9dcebbe84d1b73113166c64212b4b8Dan Gohman      if (errno == ERANGE) {
39663f97201dc9dcebbe84d1b73113166c64212b4b8Dan Gohman        errno = 0;
39763f97201dc9dcebbe84d1b73113166c64212b4b8Dan Gohman        CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
39863f97201dc9dcebbe84d1b73113166c64212b4b8Dan Gohman        if (errno == EINVAL)
3994226bb02fb623e2aa39cad819140df541f95bd8bChris Lattner          return ReturnError(TokStart, "Invalid hexadecimal number");
40063f97201dc9dcebbe84d1b73113166c64212b4b8Dan Gohman        if (errno == ERANGE)
4014226bb02fb623e2aa39cad819140df541f95bd8bChris Lattner          return ReturnError(TokStart, "Hexadecimal number out of range");
40263f97201dc9dcebbe84d1b73113166c64212b4b8Dan Gohman      }
403f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      return tgtok::IntVal;
404a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    } else if (CurPtr[0] == 'b') {
405a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      ++CurPtr;
406f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      const char *NumStart = CurPtr;
407a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner      while (CurPtr[0] == '0' || CurPtr[0] == '1')
408a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner        ++CurPtr;
409c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner
410c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner      // Requires at least one binary digit.
411c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner      if (CurPtr == NumStart)
412c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner        return ReturnError(CurPtr-2, "Invalid binary number");
413f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      CurIntVal = strtoll(NumStart, 0, 2);
414f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      return tgtok::IntVal;
415a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
416a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
417a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
418a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Check for a sign without a digit.
419f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  if (!isdigit(CurPtr[0])) {
420f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    if (CurPtr[-1] == '-')
421f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      return tgtok::minus;
422f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    else if (CurPtr[-1] == '+')
423f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      return tgtok::plus;
424a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
425a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
426a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (isdigit(CurPtr[0]))
427a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
428f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  CurIntVal = strtoll(TokStart, 0, 10);
429f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner  return tgtok::IntVal;
430a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
431a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
432a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// LexBracket - We just read '['.  If this is a code block, return it,
433a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// otherwise return the bracket.  Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
434f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattnertgtok::TokKind TGLexer::LexBracket() {
435a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (CurPtr[0] != '{')
436f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner    return tgtok::l_square;
437a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  ++CurPtr;
438a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  const char *CodeStart = CurPtr;
439a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (1) {
440a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    int Char = getNextChar();
441a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (Char == EOF) break;
442a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
443a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (Char != '}') continue;
444a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
445a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    Char = getNextChar();
446a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (Char == EOF) break;
447a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    if (Char == ']') {
448f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      CurStrVal.assign(CodeStart, CurPtr-2);
449f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattner      return tgtok::CodeFragment;
450a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    }
451a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  }
452a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
453c8a9bbcbc777f5071ed67879b9f6f3b02c5d1e34Chris Lattner  return ReturnError(CodeStart-2, "Unterminated Code Block");
454a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
455a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
456a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
457f460165a4c1bf4bc762f9b3f12b9ed284b89cc99Chris Lattnertgtok::TokKind TGLexer::LexExclaim() {
458a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  if (!isalpha(*CurPtr))
459dd2b6cbb624691fcdfda2f7e962789417b04b16bBill Wendling    return ReturnError(CurPtr - 1, "Invalid \"!operator\"");
460a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
461a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  const char *Start = CurPtr++;
462a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  while (isalpha(*CurPtr))
463a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner    ++CurPtr;
464a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
465a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner  // Check to see which operator this is.
466cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling  tgtok::TokKind Kind =
467cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
468cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("eq", tgtok::XEq)
469cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("if", tgtok::XIf)
4701434f66b2e132a707e2c8ccb3350ea13fb5aa051David Greene    .Case("head", tgtok::XHead)
4711434f66b2e132a707e2c8ccb3350ea13fb5aa051David Greene    .Case("tail", tgtok::XTail)
472cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("con", tgtok::XConcat)
473d23a41c153712b929bd84f5e713bda5db5d6e66dHal Finkel    .Case("add", tgtok::XADD)
474cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("shl", tgtok::XSHL)
475cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("sra", tgtok::XSRA)
476cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("srl", tgtok::XSRL)
477cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("cast", tgtok::XCast)
4781434f66b2e132a707e2c8ccb3350ea13fb5aa051David Greene    .Case("empty", tgtok::XEmpty)
479cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("subst", tgtok::XSubst)
480cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("foreach", tgtok::XForEach)
481cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Case("strconcat", tgtok::XStrConcat)
482cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling    .Default(tgtok::Error);
483cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling
484cd466f582aa83074294ab1a31b26eedd5a2fd025Bill Wendling  return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator");
485a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner}
486a8058744229a44e80f90c8530bb7fe47cbab1b70Chris Lattner
487