b6592f28e9ccb5f37d421f0cc40bc8488f9814e1
[vuplus_bitbake] / lib / bb / parse / parse_c / bitbakescanner.l
1 /* bbf.flex 
2
3    written by Marc Singer
4    6 January 2005
5
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19    USA.
20
21    DESCRIPTION
22    -----------
23
24    flex lexer specification for a BitBake input file parser.
25
26    Unfortunately, flex doesn't welcome comments within the rule sets.
27    I say unfortunately because this lexer is unreasonably complex and
28    comments would make the code much easier to comprehend.
29
30    The BitBake grammar is not regular.  In order to interpret all
31    of the available input files, the lexer maintains much state as it
32    parses.  There are places where this lexer will emit tokens that
33    are invalid.  The parser will tend to catch these. 
34
35    The lexer requires C++ at the moment.  The only reason for this has
36    to do with a very small amount of managed state.  Producing a C
37    lexer should be a reasonably easy task as long as the %reentrant
38    option is used.
39
40
41    NOTES
42    -----
43
44    o RVALUES.  There are three kinds of RVALUES.  There are unquoted
45      values, double quote enclosed strings, and single quote 
46      strings.  Quoted strings may contain unescaped quotes (of either
47      type), *and* any type may span more than one line by using a
48      continuation '\' at the end of the line.  This requires us to
49      recognize all types of values with a single expression.
50      Moreover, the only reason to quote a value is to include
51      trailing or leading whitespace.  Whitespace within a value is
52      preserved, ugh.
53
54    o CLASSES.  C_ patterns define classes.  Classes ought not include
55      a repitition operator, instead letting the reference to the class
56      define the repitition count.
57
58      C_SS - symbol start
59      C_SB - symbol body
60      C_SP - whitespace
61
62 */
63
64 %option never-interactive
65 %option yylineno
66 %option noyywrap
67 %option reentrant stack
68
69
70 %{
71
72 #include "token.h"
73 #include "lexer.h"
74 #include "bitbakeparser.h"
75 #include <ctype.h>
76
77 extern void *bbparseAlloc(void *(*mallocProc)(size_t));
78 extern void bbparseFree(void *p, void (*freeProc)(void*));
79 extern void *bbparseAlloc(void *(*mallocProc)(size_t));
80 extern void *bbparse(void*, int, token_t, lex_t*);
81 extern void bbparseTrace(FILE *TraceFILE, char *zTracePrompt);
82
83 //static const char* rgbInput;
84 //static size_t cbInput;
85
86 extern "C" {
87
88 int lineError;
89 int errorParse;
90
91 enum {
92   errorNone = 0,
93   errorUnexpectedInput,
94   errorUnsupportedFeature,
95 };
96
97 }
98
99 #define YY_EXTRA_TYPE lex_t*
100
101         /* Read from buffer */
102 #define YY_INPUT(buf,result,max_size) \
103  { yyextra->input(buf, &result, max_size); }
104
105 //#define YY_DECL static size_t yylex ()
106
107 #define ERROR(e) \
108   do { lineError = yylineno; errorParse = e; yyterminate (); } while (0)
109
110 static const char* fixup_escapes (const char* sz);
111
112 %}
113
114
115 C_SP            [ \t]
116 COMMENT         #.*\n
117 OP_ASSIGN       "="
118 OP_PREDOT       ".="
119 OP_POSTDOT      "=."
120 OP_IMMEDIATE    ":="
121 OP_PREPEND      "=+"
122 OP_APPEND       "+="
123 OP_COND         "?="
124 B_OPEN          "{"
125 B_CLOSE         "}"
126
127 K_ADDTASK       "addtask"
128 K_ADDHANDLER    "addhandler"
129 K_AFTER         "after"
130 K_BEFORE        "before"
131 K_DEF           "def"
132 K_INCLUDE       "include"
133 K_REQUIRE       "require"
134 K_INHERIT       "inherit"
135 K_PYTHON        "python"
136 K_FAKEROOT      "fakeroot"
137 K_EXPORT        "export"
138 K_EXPORT_FUNC   "EXPORT_FUNCTIONS"
139
140 STRING          \"([^\n\r]|"\\\n")*\"
141 SSTRING         \'([^\n\r]|"\\\n")*\'
142 VALUE           ([^'" \t\n])|([^'" \t\n]([^\n]|(\\\n))*[^'" \t\n])
143
144 C_SS            [a-zA-Z_]
145 C_SB            [a-zA-Z0-9_+-./]
146 REF             $\{{C_SS}{C_SB}*\}
147 SYMBOL          {C_SS}{C_SB}*
148 VARIABLE        $?{C_SS}({C_SB}*|{REF})*(\[[a-zA-Z0-9_]*\])?
149 FILENAME        ([a-zA-Z_./]|{REF})(([-+a-zA-Z0-9_./]*)|{REF})*
150
151 PROC            \({C_SP}*\)
152
153 %s S_DEF
154 %s S_DEF_ARGS
155 %s S_DEF_BODY
156 %s S_FUNC
157 %s S_INCLUDE
158 %s S_INHERIT
159 %s S_REQUIRE
160 %s S_PROC
161 %s S_RVALUE
162 %s S_TASK
163
164 %%
165
166 {OP_APPEND}                     { BEGIN S_RVALUE;
167                                   yyextra->accept (T_OP_APPEND); }
168 {OP_PREPEND}                    { BEGIN S_RVALUE;
169                                   yyextra->accept (T_OP_PREPEND); }
170 {OP_IMMEDIATE}                  { BEGIN S_RVALUE;
171                                   yyextra->accept (T_OP_IMMEDIATE); }
172 {OP_ASSIGN}                     { BEGIN S_RVALUE;
173                                   yyextra->accept (T_OP_ASSIGN); }
174 {OP_PREDOT}                     { BEGIN S_RVALUE;
175                                   yyextra->accept (T_OP_PREDOT); }
176 {OP_POSTDOT}                    { BEGIN S_RVALUE;
177                                   yyextra->accept (T_OP_POSTDOT); }
178 {OP_COND}                       { BEGIN S_RVALUE;
179                                   yyextra->accept (T_OP_COND); }
180
181 <S_RVALUE>\\\n{C_SP}*           {  }
182 <S_RVALUE>{STRING}              { BEGIN INITIAL;
183                                   size_t cb = yyleng;
184                                   while (cb && isspace (yytext[cb - 1]))
185                                       --cb;
186                                   yytext[cb - 1] = 0;
187                                   yyextra->accept (T_STRING, yytext + 1); }
188 <S_RVALUE>{SSTRING}             { BEGIN INITIAL;
189                                   size_t cb = yyleng;
190                                   while (cb && isspace (yytext[cb - 1]))
191                                       --cb;
192                                   yytext[cb - 1] = 0;
193                                   yyextra->accept (T_STRING, yytext + 1); }
194
195 <S_RVALUE>{VALUE}               { ERROR (errorUnexpectedInput);  }
196 <S_RVALUE>{C_SP}*\n+            { BEGIN INITIAL;
197                                   yyextra->accept (T_STRING, NULL); }
198
199 {K_INCLUDE}                     { BEGIN S_INCLUDE;
200                                   yyextra->accept (T_INCLUDE); }
201 {K_REQUIRE}                     { BEGIN S_REQUIRE;
202                                   yyextra->accept (T_REQUIRE); }
203 {K_INHERIT}                     { BEGIN S_INHERIT;
204                                   yyextra->accept (T_INHERIT); }
205 {K_ADDTASK}                     { BEGIN S_TASK;
206                                   yyextra->accept (T_ADDTASK); }
207 {K_ADDHANDLER}                  { yyextra->accept (T_ADDHANDLER); }
208 {K_EXPORT_FUNC}                 { BEGIN S_FUNC;
209                                   yyextra->accept (T_EXPORT_FUNC); }
210 <S_TASK>{K_BEFORE}              { yyextra->accept (T_BEFORE); }
211 <S_TASK>{K_AFTER}               { yyextra->accept (T_AFTER); }
212 <INITIAL>{K_EXPORT}             { yyextra->accept (T_EXPORT); }
213
214 <INITIAL>{K_FAKEROOT}           { yyextra->accept (T_FAKEROOT); }
215 <INITIAL>{K_PYTHON}             { yyextra->accept (T_PYTHON); }
216 {PROC}{C_SP}*{B_OPEN}{C_SP}*\n*  { BEGIN S_PROC;
217                                   yyextra->accept (T_PROC_OPEN); }
218 <S_PROC>{B_CLOSE}{C_SP}*\n*      { BEGIN INITIAL;
219                                   yyextra->accept (T_PROC_CLOSE); }
220 <S_PROC>([^}][^\n]*)?\n*        { yyextra->accept (T_PROC_BODY, yytext); }
221
222 {K_DEF}                         { BEGIN S_DEF; }
223 <S_DEF>{SYMBOL}                 { BEGIN S_DEF_ARGS;
224                                   yyextra->accept (T_SYMBOL, yytext); }
225 <S_DEF_ARGS>[^\n:]*:            { yyextra->accept (T_DEF_ARGS, yytext); }
226 <S_DEF_ARGS>{C_SP}*\n           { BEGIN S_DEF_BODY; }
227 <S_DEF_BODY>{C_SP}+[^\n]*\n     { yyextra->accept (T_DEF_BODY, yytext); }
228 <S_DEF_BODY>\n                  { yyextra->accept (T_DEF_BODY, yytext); }
229 <S_DEF_BODY>.                   { BEGIN INITIAL; unput (yytext[0]); }
230
231 {COMMENT}                       { }
232
233 <INITIAL>{SYMBOL}               { yyextra->accept (T_SYMBOL, yytext); }
234 <INITIAL>{VARIABLE}             { yyextra->accept (T_VARIABLE, yytext); }
235
236 <S_TASK>{SYMBOL}                { yyextra->accept (T_TSYMBOL, yytext); }
237 <S_FUNC>{SYMBOL}                { yyextra->accept (T_FSYMBOL, yytext); }
238 <S_INHERIT>{SYMBOL}             { yyextra->accept (T_ISYMBOL, yytext); }
239 <S_INCLUDE>{FILENAME}           { BEGIN INITIAL;
240                                   yyextra->accept (T_ISYMBOL, yytext); }
241 <S_REQUIRE>{FILENAME}           { BEGIN INITIAL;
242                                   yyextra->accept (T_ISYMBOL, yytext); }
243 <S_TASK>\n                      { BEGIN INITIAL; }
244 <S_FUNC>\n                      { BEGIN INITIAL; }
245 <S_INHERIT>\n                   { BEGIN INITIAL; }
246
247 [ \t\r\n]                       /* Insignificant whitespace */
248
249 .                               { ERROR (errorUnexpectedInput); }
250
251                                 /* Check for premature termination */
252 <<EOF>>                         { return T_EOF; }
253
254 %%
255
256 void lex_t::accept (int token, const char* sz) 
257 {
258     token_t t;
259     memset (&t, 0, sizeof (t));
260     t.copyString(sz);
261
262     /* tell lemon to parse the token */
263     parse (parser, token, t, this);
264 }
265
266 void lex_t::input (char *buf, int *result, int max_size)
267 {
268     /* printf("lex_t::input %p %d\n", buf, max_size); */
269     *result = fread(buf, 1, max_size, file);
270     /* printf("lex_t::input result %d\n", *result); */
271 }
272
273 int lex_t::line ()const
274 {
275     /* printf("lex_t::line\n"); */
276     return yyget_lineno (scanner);
277 }
278
279
280 extern "C" {
281
282     void parse (FILE* file, char* name, PyObject* data, int config)
283     {
284         /* printf("parse bbparseAlloc\n"); */
285         void* parser = bbparseAlloc (malloc);
286         yyscan_t scanner;
287         lex_t lex;
288
289         /* printf("parse yylex_init\n"); */
290         yylex_init (&scanner);
291
292         lex.parser = parser;
293         lex.scanner = scanner;
294         lex.file = file;
295         lex.name = name;
296         lex.data = data;
297         lex.config = config;
298         lex.parse = bbparse;
299         /*printf("parse yyset_extra\n"); */
300         yyset_extra (&lex, scanner);
301
302         /* printf("parse yylex\n"); */
303         int result = yylex (scanner);
304
305         /* printf("parse result %d\n", result); */
306
307         lex.accept (0);
308         /* printf("parse lex.accept\n"); */
309         bbparseTrace (NULL, NULL);
310         /* printf("parse bbparseTrace\n"); */
311
312         if (result != T_EOF)
313            printf ("premature end of file\n");
314
315         yylex_destroy (scanner);
316         bbparseFree (parser, free);
317     }
318
319 }