summaryrefslogtreecommitdiff
path: root/utils/TableGen/FileLexer.l.cvs
blob: 3b60099bc103233fb16d77c66a652138a31c9f1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*===-- FileLexer.l - Scanner for TableGen Files ----------------*- C++ -*-===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This file defines a simple flex scanner for TableGen files.  This is pretty
// straight-forward, except for the magic to handle file inclusion.
//
//===----------------------------------------------------------------------===*/

%option prefix="File"
%option yylineno
%option nostdinit
%option never-interactive
%option batch
%option nodefault
%option 8bit
%option outfile="Lexer.cpp"
%option ecs
%option noreject
%option noyymore

%x comment

%{
#include "Record.h"
typedef std::pair<llvm::Record*, std::vector<llvm::Init*>*> SubClassRefTy;
#include "FileParser.h"

int Fileparse();

namespace llvm {

// Global variable recording the location of the include directory
std::vector<std::string> IncludeDirectories;

/// ParseInt - This has to handle the special case of binary numbers 0b0101
///
static int ParseInt(const char *Str) {
  if (Str[0] == '0' && Str[1] == 'b')
    return strtol(Str+2, 0, 2);
  return strtol(Str, 0, 0); 
}

static int CommentDepth = 0;

struct IncludeRec {
  std::string Filename;
  FILE *File;
  unsigned LineNo;
  YY_BUFFER_STATE Buffer;

  IncludeRec(const std::string &FN, FILE *F)
    : Filename(FN), File(F), LineNo(0){
  }
};

static std::vector<IncludeRec> IncludeStack;

std::ostream &err() {
  if (IncludeStack.empty())
    return std::cerr << "At end of input: ";

  for (unsigned i = 0, e = IncludeStack.size()-1; i != e; ++i)
    std::cerr << "Included from " << IncludeStack[i].Filename << ":"
              << IncludeStack[i].LineNo << ":\n";
  return std::cerr << "Parsing " << IncludeStack.back().Filename << ":"
                   << Filelineno << ": ";
}

/// ParseFile - this function begins the parsing of the specified tablegen file.
///
void ParseFile(const std::string &Filename, 
               const std::vector<std::string> &IncludeDirs) {
  FILE *F = stdin;
  if (Filename != "-") {
    F = fopen(Filename.c_str(), "r");

    if (F == 0) {
      std::cerr << "Could not open input file '" + Filename + "'!\n";
      exit (1);
    }
    IncludeStack.push_back(IncludeRec(Filename, F));
  } else {
    IncludeStack.push_back(IncludeRec("<stdin>", stdin));
  }

  // Record the location of the include directory so that the lexer can find
  // it later.
  IncludeDirectories = IncludeDirs;
 
  Filein = F;
  Filelineno = 1;
  Fileparse();
  Filein = stdin;
}

/// HandleInclude - This function is called when an include directive is
/// encountered in the input stream...
///
static void HandleInclude(const char *Buffer) {
  unsigned Length = yyleng;
  assert(Buffer[Length-1] == '"');
  Buffer += strlen("include ");
  Length -= strlen("include ");
  while (*Buffer != '"') {
    ++Buffer;
    --Length;
  }
  assert(Length >= 2 && "Double quotes not found?");
  std::string Filename(Buffer+1, Buffer+Length-1);
  //std::cerr << "Filename = '" << Filename << "'\n";

  // Save the line number and lex buffer of the includer...
  IncludeStack.back().LineNo = Filelineno;
  IncludeStack.back().Buffer = YY_CURRENT_BUFFER;

  // Open the new input file...
  yyin = fopen(Filename.c_str(), "r");
  if (yyin == 0) {
    // If we couldn't find the file in the current directory, look for it in
    // the include directories.
    //
    std::string NextFilename;
    for (unsigned i = 0, e = IncludeDirectories.size(); i != e; ++i) {
      NextFilename = IncludeDirectories[i] + "/" + Filename;
      if ((yyin = fopen(NextFilename.c_str(), "r")))
        break;
    }
    
    if (yyin == 0) {
      err() << "Could not find include file '" << Filename << "'!\n";
      exit(1);
    }
    Filename = NextFilename;
  }

  // Add the file to our include stack...
  IncludeStack.push_back(IncludeRec(Filename, yyin));
  Filelineno = 1;  // Reset line numbering...
  //yyrestart(yyin);    // Start lexing the new file...

  yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
}

/// yywrap - This is called when the lexer runs out of input in one of the
/// files. Switch back to an includer if an includee has run out of input.
///
extern "C"
int yywrap(void) {
  if (IncludeStack.back().File != stdin)
    fclose(IncludeStack.back().File);
  IncludeStack.pop_back();
  if (IncludeStack.empty()) return 1;  // Top-level file is done.

  // Otherwise, we need to switch back to a file which included the current one.
  Filelineno = IncludeStack.back().LineNo;  // Restore current line number
  yy_switch_to_buffer(IncludeStack.back().Buffer);
  return 0;
}

} // End llvm namespace

using namespace llvm;

%}

Comment      \/\/.*

Identifier   [a-zA-Z_][0-9a-zA-Z_]*
Integer      [-+]?[0-9]+|0x[0-9a-fA-F]+|0b[01]+
CodeFragment \[\{([^}]+|\}[^\]])*\}\]
StringVal    \"[^"]*\"
IncludeStr   include[ \t\n]+\"[^"]*\"

%%

{Comment}      { /* Ignore comments */ }

{IncludeStr}   { HandleInclude(yytext); }
{CodeFragment} { Filelval.StrVal = new std::string(yytext+2, yytext+yyleng-2);
                 return CODEFRAGMENT; }

int            { return INT; }
bit            { return BIT; }
bits           { return BITS; }
string         { return STRING; }
list           { return LIST; }
code           { return CODE; }
dag            { return DAG; }

class          { return CLASS; }
def            { return DEF; }
field          { return FIELD; }
let            { return LET; }
in             { return IN; }

!sra           { return SRATOK; }
!srl           { return SRLTOK; }
!shl           { return SHLTOK; }
!strconcat     { return STRCONCATTOK; }


{Identifier}   { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
                 return ID; }
${Identifier}  { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng);
                 return VARNAME; } 

{StringVal}    { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng-1);
                 return STRVAL; }

{Integer}      { Filelval.IntVal = ParseInt(Filetext); return INTVAL; }

[ \t\n\r]+     { /* Ignore whitespace */ }


"/*"                    { BEGIN(comment); CommentDepth++; }
<comment>[^*/]*         {} /* eat anything that's not a '*' or '/' */
<comment>"*"+[^*/]*     {} /* eat up '*'s not followed by '/'s */
<comment>"/*"           { ++CommentDepth; }
<comment>"/"+[^*/]*     {} /* eat up /'s not followed by *'s */
<comment>"*"+"/"        { if (!--CommentDepth) { BEGIN(INITIAL); } }
<comment><<EOF>>        { err() << "Unterminated comment!\n"; exit(1); }

.              { return Filetext[0]; }

%%