Reverting unnecessary commit of generated files.
[oota-llvm.git] / utils / TableGen / FileLexer.l.cvs
1 /*===-- FileLexer.l - Scanner for TableGen Files ----------------*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a simple flex scanner for TableGen files.  This is pretty
11 // straight-forward, except for the magic to handle file inclusion.
12 //
13 //===----------------------------------------------------------------------===*/
14
15 %option prefix="File"
16 %option yylineno
17 %option nostdinit
18 %option never-interactive
19 %option batch
20 %option nodefault
21 %option 8bit
22 %option outfile="Lexer.cpp"
23 %option ecs
24 %option noreject
25 %option noyymore
26
27 %x comment
28
29 %{
30 #include "llvm/Config/config.h"
31 #include "llvm/Support/Streams.h"
32 #include "Record.h"
33 typedef std::pair<llvm::Record*, std::vector<llvm::Init*>*> SubClassRefTy;
34 #include "FileParser.h"
35
36 int Fileparse();
37
38 namespace llvm {
39
40 // Global variable recording the location of the include directory
41 std::vector<std::string> IncludeDirectories;
42
43 /// ParseInt - This has to handle the special case of binary numbers 0b0101
44 ///
45 static int ParseInt(const char *Str) {
46   if (Str[0] == '0' && Str[1] == 'b')
47     return strtoll(Str+2, 0, 2);
48   return strtoll(Str, 0, 0); 
49 }
50
51 static int CommentDepth = 0;
52
53 struct IncludeRec {
54   std::string Filename;
55   FILE *File;
56   unsigned LineNo;
57   YY_BUFFER_STATE Buffer;
58
59   IncludeRec(const std::string &FN, FILE *F)
60     : Filename(FN), File(F), LineNo(0){
61   }
62 };
63
64 static std::vector<IncludeRec> IncludeStack;
65
66 std::ostream &err() {
67   if (IncludeStack.empty()) {
68     cerr << "At end of input: ";
69     return *cerr.stream();
70   }
71
72   for (unsigned i = 0, e = IncludeStack.size()-1; i != e; ++i)
73     cerr << "Included from " << IncludeStack[i].Filename << ":"
74          << IncludeStack[i].LineNo << ":\n";
75   cerr << "Parsing " << IncludeStack.back().Filename << ":"
76        << Filelineno << ": ";
77   return *cerr.stream();
78 }
79
80 /// ParseFile - this function begins the parsing of the specified tablegen file.
81 ///
82 void ParseFile(const std::string &Filename, 
83                const std::vector<std::string> &IncludeDirs) {
84   FILE *F = stdin;
85   if (Filename != "-") {
86     F = fopen(Filename.c_str(), "r");
87
88     if (F == 0) {
89       cerr << "Could not open input file '" + Filename + "'!\n";
90       exit (1);
91     }
92     IncludeStack.push_back(IncludeRec(Filename, F));
93   } else {
94     IncludeStack.push_back(IncludeRec("<stdin>", stdin));
95   }
96
97   // Record the location of the include directory so that the lexer can find
98   // it later.
99   IncludeDirectories = IncludeDirs;
100  
101   Filein = F;
102   Filelineno = 1;
103   Fileparse();
104   Filein = stdin;
105 }
106
107 /// HandleInclude - This function is called when an include directive is
108 /// encountered in the input stream...
109 ///
110 static void HandleInclude(const char *Buffer) {
111   unsigned Length = yyleng;
112   assert(Buffer[Length-1] == '"');
113   Buffer += strlen("include ");
114   Length -= strlen("include ");
115   while (*Buffer != '"') {
116     ++Buffer;
117     --Length;
118   }
119   assert(Length >= 2 && "Double quotes not found?");
120   std::string Filename(Buffer+1, Buffer+Length-1);
121   //cerr << "Filename = '" << Filename << "'\n";
122
123   // Save the line number and lex buffer of the includer...
124   IncludeStack.back().LineNo = Filelineno;
125   IncludeStack.back().Buffer = YY_CURRENT_BUFFER;
126
127   // Open the new input file...
128   yyin = fopen(Filename.c_str(), "r");
129   if (yyin == 0) {
130     // If we couldn't find the file in the current directory, look for it in
131     // the include directories.
132     //
133     std::string NextFilename;
134     for (unsigned i = 0, e = IncludeDirectories.size(); i != e; ++i) {
135       NextFilename = IncludeDirectories[i] + "/" + Filename;
136       if ((yyin = fopen(NextFilename.c_str(), "r")))
137         break;
138     }
139     
140     if (yyin == 0) {
141       err() << "Could not find include file '" << Filename << "'!\n";
142       exit(1);
143     }
144     Filename = NextFilename;
145   }
146
147   // Add the file to our include stack...
148   IncludeStack.push_back(IncludeRec(Filename, yyin));
149   Filelineno = 1;  // Reset line numbering...
150   //yyrestart(yyin);    // Start lexing the new file...
151
152   yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
153 }
154
155 /// yywrap - This is called when the lexer runs out of input in one of the
156 /// files. Switch back to an includer if an includee has run out of input.
157 ///
158 extern "C"
159 int yywrap(void) {
160   if (IncludeStack.back().File != stdin)
161     fclose(IncludeStack.back().File);
162   IncludeStack.pop_back();
163   if (IncludeStack.empty()) return 1;  // Top-level file is done.
164
165   // Otherwise, we need to switch back to a file which included the current one.
166   Filelineno = IncludeStack.back().LineNo;  // Restore current line number
167   yy_switch_to_buffer(IncludeStack.back().Buffer);
168   return 0;
169 }
170
171 } // End llvm namespace
172
173 using namespace llvm;
174
175 %}
176
177 Comment      \/\/.*
178
179 Identifier   [a-zA-Z_][0-9a-zA-Z_]*
180 Integer      [-+]?[0-9]+|0x[0-9a-fA-F]+|0b[01]+
181 CodeFragment \[\{([^}]+|\}[^\]])*\}\]
182 StringVal    \"[^"]*\"
183 IncludeStr   include[ \t\n]+\"[^"]*\"
184
185 %%
186
187 {Comment}      { /* Ignore comments */ }
188
189 {IncludeStr}   { HandleInclude(yytext); }
190 {CodeFragment} { Filelval.StrVal = new std::string(yytext+2, yytext+yyleng-2);
191                  return CODEFRAGMENT; }
192
193 int            { return INT; }
194 bit            { return BIT; }
195 bits           { return BITS; }
196 string         { return STRING; }
197 list           { return LIST; }
198 code           { return CODE; }
199 dag            { return DAG; }
200
201 class          { return CLASS; }
202 def            { return DEF; }
203 defm           { return DEFM; }
204 multiclass     { return MULTICLASS; }
205 field          { return FIELD; }
206 let            { return LET; }
207 in             { return IN; }
208
209 !con           { return CONCATTOK; }
210 !sra           { return SRATOK; }
211 !srl           { return SRLTOK; }
212 !shl           { return SHLTOK; }
213 !strconcat     { return STRCONCATTOK; }
214
215
216 {Identifier}   { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
217                  return ID; }
218 ${Identifier}  { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng);
219                  return VARNAME; } 
220
221 {StringVal}    { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng-1);
222                  return STRVAL; }
223
224 {Integer}      { Filelval.IntVal = ParseInt(Filetext); return INTVAL; }
225
226 [ \t\n\r]+     { /* Ignore whitespace */ }
227
228
229 "/*"                    { BEGIN(comment); CommentDepth++; }
230 <comment>[^*/]*         {} /* eat anything that's not a '*' or '/' */
231 <comment>"*"+[^*/]*     {} /* eat up '*'s not followed by '/'s */
232 <comment>"/*"           { ++CommentDepth; }
233 <comment>"/"+[^*/]*     {} /* eat up /'s not followed by *'s */
234 <comment>"*"+"/"        { if (!--CommentDepth) { BEGIN(INITIAL); } }
235 <comment><<EOF>>        { err() << "Unterminated comment!\n"; exit(1); }
236
237 .              { return Filetext[0]; }
238
239 %%
240