Start transitioning towards using 'let X = y in' statements, instead of 'set X =...
[oota-llvm.git] / utils / TableGen / FileLexer.l
1 /*===-- FileLexer.l - Scanner for TableGen Files ----------------*- C++ -*-===//
2 //
3 //
4 //===------------------------------------------------------------------------=*/
5
6 %option prefix="File"
7 %option yylineno
8 %option nostdinit
9 %option never-interactive
10 %option batch
11 %option nodefault
12 %option 8bit
13 %option outfile="Lexer.cpp"
14 %option ecs
15 %option noreject
16 %option noyymore
17
18 %x comment
19
20 %{
21 #include "Record.h"
22 typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy;
23 #include "FileParser.h"
24
25 // ParseInt - This has to handle the special case of binary numbers 0b0101
26 static int ParseInt(const char *Str) {
27   if (Str[0] == '0' && Str[1] == 'b')
28     return strtol(Str+2, 0, 2);
29   return strtol(Str, 0, 0); 
30 }
31
32 static int CommentDepth = 0;
33
34 struct IncludeRec {
35   std::string Filename;
36   FILE *File;
37   unsigned LineNo;
38   YY_BUFFER_STATE Buffer;
39
40   IncludeRec(const std::string &FN, FILE *F)
41     : Filename(FN), File(F), LineNo(0){
42   }
43 };
44
45 static std::vector<IncludeRec> IncludeStack;
46
47
48 std::ostream &err() {
49   if (IncludeStack.empty())
50     return std::cerr << "At end of input: ";
51
52   for (unsigned i = 0, e = IncludeStack.size()-1; i != e; ++i)
53     std::cerr << "Included from " << IncludeStack[i].Filename << ":"
54               << IncludeStack[i].LineNo << ":\n";
55   return std::cerr << "Parsing " << IncludeStack.back().Filename << ":"
56                    << Filelineno << ": ";
57 }
58
59
60 int Fileparse();
61
62 void ParseFile(const std::string &Filename) {
63   FILE *F = stdin;
64   if (Filename != "-") {
65     F = fopen(Filename.c_str(), "r");
66
67     if (F == 0) {
68       std::cerr << "Could not open input file '" + Filename + "'!\n";
69       abort();
70     }
71     IncludeStack.push_back(IncludeRec(Filename, F));
72   } else {
73     IncludeStack.push_back(IncludeRec("<stdin>", stdin));
74   }
75
76   Filein = F;
77   Filelineno = 1;
78   Fileparse();
79   Filein = stdin;
80 }
81
82 // HandleInclude - This function is called when an include directive is
83 // encountered in the input stream...
84 static void HandleInclude(const char *Buffer) {
85   unsigned Length = yyleng;
86   assert(Buffer[Length-1] == '"');
87   Buffer += strlen("include ");
88   Length -= strlen("include ");
89   while (*Buffer != '"') {
90     ++Buffer;
91     --Length;
92   }
93   assert(Length >= 2 && "Double quotes not found?");
94   std::string Filename(Buffer+1, Buffer+Length-1);
95   //std::cerr << "Filename = '" << Filename << "'\n";
96
97   // Save the line number and lex buffer of the includer...
98   IncludeStack.back().LineNo = Filelineno;
99   IncludeStack.back().Buffer = YY_CURRENT_BUFFER;
100
101   // Open the new input file...
102   yyin = fopen(Filename.c_str(), "r");
103   if (yyin == 0) {
104     err() << "Could not find include file '" << Filename << "'!\n";
105     abort();
106   }
107
108   // Add the file to our include stack...
109   IncludeStack.push_back(IncludeRec(Filename, yyin));
110   Filelineno = 1;  // Reset line numbering...
111   //yyrestart(yyin);    // Start lexing the new file...
112
113   yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
114 }
115
116
117 // yywrap - This is called when the lexer runs out of input in one of the files.
118 // Switch back to an includer if an includee has run out of input.
119 //
120 extern "C"
121 int yywrap() {
122   if (IncludeStack.back().File != stdin)
123     fclose(IncludeStack.back().File);
124   IncludeStack.pop_back();
125   if (IncludeStack.empty()) return 1;  // Top-level file is done.
126
127   // Otherwise, we need to switch back to a file which included the current one.
128   Filelineno = IncludeStack.back().LineNo;  // Restore current line number
129   yy_switch_to_buffer(IncludeStack.back().Buffer);
130   return 0;
131 }
132
133 %}
134
135 Comment      \/\/.*
136
137 Identifier   [a-zA-Z_][0-9a-zA-Z_]*
138 Integer      [-+]?[0-9]+|0x[0-9a-fA-F]+|0b[01]+
139 CodeFragment \[\{([^}]+|\}[^\]])*\}\]
140 StringVal    \"[^"]*\"
141 IncludeStr   include[ \t\n]+\"[^"]*\"
142
143 %%
144
145 {Comment}      { /* Ignore comments */ }
146
147 {IncludeStr}   { HandleInclude(yytext); }
148 {CodeFragment} { Filelval.StrVal = new std::string(yytext+2, yytext+yyleng-2);
149                  return CODEFRAGMENT; }
150
151 int            { return INT; }
152 bit            { return BIT; }
153 bits           { return BITS; }
154 string         { return STRING; }
155 list           { return LIST; }
156 code           { return CODE; }
157 dag            { return DAG; }
158
159 class          { return CLASS; }
160 def            { return DEF; }
161 field          { return FIELD; }
162 let            { return LET; }
163 set            { return LET; }
164 in             { return IN; }
165
166 {Identifier}   { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
167                  return ID; }
168
169 {StringVal}    { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng-1);
170                  return STRVAL; }
171
172 {Integer}      { Filelval.IntVal = ParseInt(Filetext); return INTVAL; }
173
174 [ \t\n]+       { /* Ignore whitespace */ }
175
176
177 "/*"                    { BEGIN(comment); CommentDepth++; }
178 <comment>[^*/]*         /* eat anything that's not a '*' or '/' */
179 <comment>"*"+[^*/]*     /* eat up '*'s not followed by '/'s */
180 <comment>"/*"           { ++CommentDepth; }
181 <comment>"/"+[^*]*      /* eat up /'s not followed by *'s */
182 <comment>"*"+"/"        { if (!--CommentDepth) { BEGIN(INITIAL); } }
183 <comment><<EOF>>        { err() << "Unterminated comment!\n"; abort(); }
184
185 .              { return Filetext[0]; }
186
187 %%