Dummy implementation of the pthread library.
[oota-llvm.git] / utils / TableGen / FileLexer.l
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 "Record.h"
31 typedef std::pair<llvm::Record*, std::vector<llvm::Init*>*> SubClassRefTy;
32 #include "FileParser.h"
33
34 int Fileparse();
35
36 namespace llvm {
37
38 // Global variable recording the location of the include directory
39 std::string IncludeDirectory;
40
41 // ParseInt - This has to handle the special case of binary numbers 0b0101
42 static int ParseInt(const char *Str) {
43   if (Str[0] == '0' && Str[1] == 'b')
44     return strtol(Str+2, 0, 2);
45   return strtol(Str, 0, 0); 
46 }
47
48 static int CommentDepth = 0;
49
50 struct IncludeRec {
51   std::string Filename;
52   FILE *File;
53   unsigned LineNo;
54   YY_BUFFER_STATE Buffer;
55
56   IncludeRec(const std::string &FN, FILE *F)
57     : Filename(FN), File(F), LineNo(0){
58   }
59 };
60
61 static std::vector<IncludeRec> IncludeStack;
62
63
64 std::ostream &err() {
65   if (IncludeStack.empty())
66     return std::cerr << "At end of input: ";
67
68   for (unsigned i = 0, e = IncludeStack.size()-1; i != e; ++i)
69     std::cerr << "Included from " << IncludeStack[i].Filename << ":"
70               << IncludeStack[i].LineNo << ":\n";
71   return std::cerr << "Parsing " << IncludeStack.back().Filename << ":"
72                    << Filelineno << ": ";
73 }
74
75
76
77 //
78 // Function: ParseFile()
79 //
80 // Description:
81 //      This function begins the parsing of the specified tablegen file.
82 //
83 // Inputs:
84 //      Filename - A string containing the name of the file to parse.
85 //      IncludeDir - A string containing the directory from which include
86 //                   files can be found.
87 //
88 void ParseFile(const std::string &Filename, const std::string & IncludeDir) {
89   FILE *F = stdin;
90   if (Filename != "-") {
91     F = fopen(Filename.c_str(), "r");
92
93     if (F == 0) {
94       std::cerr << "Could not open input file '" + Filename + "'!\n";
95       exit (1);
96     }
97     IncludeStack.push_back(IncludeRec(Filename, F));
98   } else {
99     IncludeStack.push_back(IncludeRec("<stdin>", stdin));
100   }
101
102   //
103   // Record the location of the include directory so that the lexer can find
104   // it later.
105   //
106   IncludeDirectory = IncludeDir;
107  
108   Filein = F;
109   Filelineno = 1;
110   Fileparse();
111   Filein = stdin;
112 }
113
114 // HandleInclude - This function is called when an include directive is
115 // encountered in the input stream...
116 static void HandleInclude(const char *Buffer) {
117   unsigned Length = yyleng;
118   assert(Buffer[Length-1] == '"');
119   Buffer += strlen("include ");
120   Length -= strlen("include ");
121   while (*Buffer != '"') {
122     ++Buffer;
123     --Length;
124   }
125   assert(Length >= 2 && "Double quotes not found?");
126   std::string Filename(Buffer+1, Buffer+Length-1);
127   //std::cerr << "Filename = '" << Filename << "'\n";
128
129   // Save the line number and lex buffer of the includer...
130   IncludeStack.back().LineNo = Filelineno;
131   IncludeStack.back().Buffer = YY_CURRENT_BUFFER;
132
133   // Open the new input file...
134   yyin = fopen(Filename.c_str(), "r");
135   if (yyin == 0) {
136     //
137     // If we couldn't find the file in the current directory, look for it in
138     // the include directories.
139     //
140     // NOTE:
141     //  Right now, there is only one directory.  We need to eventually add
142     //  support for more.
143     //
144     Filename = IncludeDirectory + "/" + Filename;
145     yyin = fopen(Filename.c_str(), "r");
146     if (yyin == 0) {
147       err() << "Could not find include file '" << Filename << "'!\n";
148       abort();
149     }
150   }
151
152   // Add the file to our include stack...
153   IncludeStack.push_back(IncludeRec(Filename, yyin));
154   Filelineno = 1;  // Reset line numbering...
155   //yyrestart(yyin);    // Start lexing the new file...
156
157   yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
158 }
159
160
161 // yywrap - This is called when the lexer runs out of input in one of the files.
162 // Switch back to an includer if an includee has run out of input.
163 //
164 extern "C"
165 int yywrap() {
166   if (IncludeStack.back().File != stdin)
167     fclose(IncludeStack.back().File);
168   IncludeStack.pop_back();
169   if (IncludeStack.empty()) return 1;  // Top-level file is done.
170
171   // Otherwise, we need to switch back to a file which included the current one.
172   Filelineno = IncludeStack.back().LineNo;  // Restore current line number
173   yy_switch_to_buffer(IncludeStack.back().Buffer);
174   return 0;
175 }
176
177 } // End llvm namespace
178
179 using namespace llvm;
180
181 %}
182
183 Comment      \/\/.*
184
185 Identifier   [a-zA-Z_][0-9a-zA-Z_]*
186 Integer      [-+]?[0-9]+|0x[0-9a-fA-F]+|0b[01]+
187 CodeFragment \[\{([^}]+|\}[^\]])*\}\]
188 StringVal    \"[^"]*\"
189 IncludeStr   include[ \t\n]+\"[^"]*\"
190
191 %%
192
193 {Comment}      { /* Ignore comments */ }
194
195 {IncludeStr}   { HandleInclude(yytext); }
196 {CodeFragment} { Filelval.StrVal = new std::string(yytext+2, yytext+yyleng-2);
197                  return CODEFRAGMENT; }
198
199 int            { return INT; }
200 bit            { return BIT; }
201 bits           { return BITS; }
202 string         { return STRING; }
203 list           { return LIST; }
204 code           { return CODE; }
205 dag            { return DAG; }
206
207 class          { return CLASS; }
208 def            { return DEF; }
209 field          { return FIELD; }
210 let            { return LET; }
211 in             { return IN; }
212
213 {Identifier}   { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
214                  return ID; }
215 ${Identifier}  { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng);
216                  return VARNAME; } 
217
218 {StringVal}    { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng-1);
219                  return STRVAL; }
220
221 {Integer}      { Filelval.IntVal = ParseInt(Filetext); return INTVAL; }
222
223 [ \t\n]+       { /* Ignore whitespace */ }
224
225
226 "/*"                    { BEGIN(comment); CommentDepth++; }
227 <comment>[^*/]*         /* eat anything that's not a '*' or '/' */
228 <comment>"*"+[^*/]*     /* eat up '*'s not followed by '/'s */
229 <comment>"/*"           { ++CommentDepth; }
230 <comment>"/"+[^*]*      /* eat up /'s not followed by *'s */
231 <comment>"*"+"/"        { if (!--CommentDepth) { BEGIN(INITIAL); } }
232 <comment><<EOF>>        { err() << "Unterminated comment!\n"; abort(); }
233
234 .              { return Filetext[0]; }
235
236 %%