blob: 48070b34a144124027ae9ca1818070eab46d06f5 [file] [log] [blame]
Chris Lattnere62c1182002-12-02 01:23:04 +00001/*===-- FileLexer.l - Scanner for TableGen Files ----------------*- C++ -*-===//
John Criswellaefb6662003-10-21 15:29:18 +00002//
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//===----------------------------------------------------------------------===//
Chris Lattnere62c1182002-12-02 01:23:04 +00009//
Chris Lattner13854f22003-08-04 20:08:28 +000010// This file defines a simple flex scanner for TableGen files. This is pretty
11// straight-forward, except for the magic to handle file inclusion.
Chris Lattnere62c1182002-12-02 01:23:04 +000012//
Chris Lattner13854f22003-08-04 20:08:28 +000013//===----------------------------------------------------------------------===*/
Chris Lattnere62c1182002-12-02 01:23:04 +000014
15%option prefix="File"
16%option yylineno
17%option nostdinit
18%option never-interactive
19%option batch
Chris Lattnere62c1182002-12-02 01:23:04 +000020%option nodefault
21%option 8bit
22%option outfile="Lexer.cpp"
23%option ecs
24%option noreject
25%option noyymore
26
Chris Lattnerd33b8db2003-07-30 19:39:36 +000027%x comment
Chris Lattnere62c1182002-12-02 01:23:04 +000028
29%{
30#include "Record.h"
Brian Gaeked0fde302003-11-11 22:41:34 +000031typedef std::pair<llvm::Record*, std::vector<llvm::Init*>*> SubClassRefTy;
Chris Lattnere62c1182002-12-02 01:23:04 +000032#include "FileParser.h"
33
Brian Gaeked0fde302003-11-11 22:41:34 +000034int Fileparse();
35
36namespace llvm {
37
John Criswell96b4bed2003-08-27 13:41:57 +000038// Global variable recording the location of the include directory
39std::string IncludeDirectory;
40
Chris Lattnere62c1182002-12-02 01:23:04 +000041// ParseInt - This has to handle the special case of binary numbers 0b0101
42static 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
Chris Lattnerd33b8db2003-07-30 19:39:36 +000048static int CommentDepth = 0;
49
Chris Lattner7dff0532003-07-30 20:56:47 +000050struct 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
61static std::vector<IncludeRec> IncludeStack;
62
63
64std::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)
Chris Lattnerbc1f0dc2003-08-03 18:12:59 +000069 std::cerr << "Included from " << IncludeStack[i].Filename << ":"
Chris Lattner7dff0532003-07-30 20:56:47 +000070 << IncludeStack[i].LineNo << ":\n";
71 return std::cerr << "Parsing " << IncludeStack.back().Filename << ":"
72 << Filelineno << ": ";
73}
74
75
Chris Lattnere623fe32003-07-30 19:55:10 +000076
John Criswell96b4bed2003-08-27 13:41:57 +000077//
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//
88void ParseFile(const std::string &Filename, const std::string & IncludeDir) {
Chris Lattnere623fe32003-07-30 19:55:10 +000089 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";
John Criswell2d930032003-09-09 14:37:48 +000095 exit (1);
Chris Lattnere623fe32003-07-30 19:55:10 +000096 }
Chris Lattner7dff0532003-07-30 20:56:47 +000097 IncludeStack.push_back(IncludeRec(Filename, F));
98 } else {
99 IncludeStack.push_back(IncludeRec("<stdin>", stdin));
Chris Lattnere623fe32003-07-30 19:55:10 +0000100 }
101
John Criswell96b4bed2003-08-27 13:41:57 +0000102 //
103 // Record the location of the include directory so that the lexer can find
104 // it later.
105 //
106 IncludeDirectory = IncludeDir;
107
Chris Lattnere623fe32003-07-30 19:55:10 +0000108 Filein = F;
109 Filelineno = 1;
110 Fileparse();
Chris Lattnere623fe32003-07-30 19:55:10 +0000111 Filein = stdin;
112}
113
Chris Lattner7dff0532003-07-30 20:56:47 +0000114// HandleInclude - This function is called when an include directive is
115// encountered in the input stream...
116static 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) {
John Criswell96b4bed2003-08-27 13:41:57 +0000136 //
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 }
Chris Lattner7dff0532003-07-30 20:56:47 +0000150 }
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//
164extern "C"
165int 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
Brian Gaeked0fde302003-11-11 22:41:34 +0000177} // End llvm namespace
178
179using namespace llvm;
180
Chris Lattnere62c1182002-12-02 01:23:04 +0000181%}
182
Chris Lattnere3a1d052003-07-30 22:15:58 +0000183Comment \/\/.*
Chris Lattnere62c1182002-12-02 01:23:04 +0000184
Chris Lattnere3a1d052003-07-30 22:15:58 +0000185Identifier [a-zA-Z_][0-9a-zA-Z_]*
186Integer [-+]?[0-9]+|0x[0-9a-fA-F]+|0b[01]+
187CodeFragment \[\{([^}]+|\}[^\]])*\}\]
188StringVal \"[^"]*\"
189IncludeStr include[ \t\n]+\"[^"]*\"
Chris Lattnere62c1182002-12-02 01:23:04 +0000190
191%%
192
193{Comment} { /* Ignore comments */ }
194
Chris Lattner7dff0532003-07-30 20:56:47 +0000195{IncludeStr} { HandleInclude(yytext); }
Chris Lattnere3a1d052003-07-30 22:15:58 +0000196{CodeFragment} { Filelval.StrVal = new std::string(yytext+2, yytext+yyleng-2);
197 return CODEFRAGMENT; }
Chris Lattner7dff0532003-07-30 20:56:47 +0000198
Chris Lattnere62c1182002-12-02 01:23:04 +0000199int { return INT; }
200bit { return BIT; }
201bits { return BITS; }
202string { return STRING; }
203list { return LIST; }
Chris Lattnerf05760d2003-07-30 21:47:42 +0000204code { return CODE; }
Chris Lattner40f71132003-08-04 04:50:57 +0000205dag { return DAG; }
Chris Lattnere62c1182002-12-02 01:23:04 +0000206
207class { return CLASS; }
208def { return DEF; }
209field { return FIELD; }
Chris Lattner42aa89e2003-08-04 04:56:53 +0000210let { return LET; }
Chris Lattnere62c1182002-12-02 01:23:04 +0000211in { return IN; }
212
213{Identifier} { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
214 return ID; }
Chris Lattnerfb9ea582003-08-10 22:04:25 +0000215${Identifier} { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng);
216 return VARNAME; }
Chris Lattnere62c1182002-12-02 01:23:04 +0000217
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 */ }
Chris Lattnerd33b8db2003-07-30 19:39:36 +0000224
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); } }
Chris Lattner7dff0532003-07-30 20:56:47 +0000232<comment><<EOF>> { err() << "Unterminated comment!\n"; abort(); }
233
234. { return Filetext[0]; }
Chris Lattnerd33b8db2003-07-30 19:39:36 +0000235
Chris Lattnere62c1182002-12-02 01:23:04 +0000236%%