parse_c:
[bitbake.git] / 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
87 int lineError;
88 int errorParse;
89
90 enum {
91   errorNone = 0,
92   errorUnexpectedInput,
93   errorUnsupportedFeature, 
94 };
95
96 #define YY_EXTRA_TYPE lex_t*
97
98         /* Read from buffer */
99 #define YY_INPUT(buf,result,max_size) \
100  { yyextra->input(buf, &result, max_size); }
101
102 //#define YY_DECL static size_t yylex ()
103
104 #define ERROR(e) \
105   do { lineError = yylineno; errorParse = e; yyterminate (); } while (0)
106
107 static const char* fixup_escapes (const char* sz);
108
109 %}
110
111
112 C_SP            [ \t]
113 COMMENT         #.*\n
114 OP_ASSIGN       "="
115 OP_IMMEDIATE    ":="
116 OP_PREPEND      "=+"
117 OP_APPEND       "+="
118 OP_COND         "?="
119 B_OPEN          "{"
120 B_CLOSE         "}"
121
122 K_ADDTASK       "addtask"
123 K_ADDHANDLER    "addhandler"
124 K_AFTER         "after"
125 K_BEFORE        "before"
126 K_DEF           "def"
127 K_INCLUDE       "include"
128 K_REQUIRE       "require"
129 K_INHERIT       "inherit"
130 K_PYTHON        "python"
131 K_FAKEROOT      "fakeroot"
132 K_EXPORT        "export"
133 K_EXPORT_FUNC   "EXPORT_FUNCTIONS"
134
135 STRING          \"([^\n\r]|"\\\n")*\"
136 SSTRING         \'([^\n\r]|"\\\n")*\'
137 VALUE           ([^'" \t\n])|([^'" \t\n]([^\n]|(\\\n))*[^'" \t\n])
138
139 C_SS            [a-zA-Z_]
140 C_SB            [a-zA-Z0-9_+-.]
141 REF             $\{{C_SS}{C_SB}*\}
142 SYMBOL          {C_SS}{C_SB}*
143 VARIABLE        $?{C_SS}({C_SB}*|{REF})*(\[[a-zA-Z0-9_]*\])?
144 FILENAME        ([a-zA-Z_./]|{REF})(([-+a-zA-Z0-9_./]*)|{REF})*
145
146 PROC            \({C_SP}*\)
147
148 %s S_DEF
149 %s S_DEF_ARGS
150 %s S_DEF_BODY
151 %s S_FUNC
152 %s S_INCLUDE
153 %s S_INHERIT
154 %s S_REQUIRE
155 %s S_PROC
156 %s S_RVALUE
157 %s S_TASK
158
159 %%
160
161 {OP_APPEND}                     { BEGIN S_RVALUE;
162                                   yyextra->accept (T_OP_APPEND); }
163 {OP_PREPEND}                    { BEGIN S_RVALUE;
164                                   yyextra->accept (T_OP_PREPEND); }
165 {OP_IMMEDIATE}                  { BEGIN S_RVALUE;
166                                   yyextra->accept (T_OP_IMMEDIATE); }
167 {OP_ASSIGN}                     { BEGIN S_RVALUE;
168                                   yyextra->accept (T_OP_ASSIGN); }
169 {OP_COND}                       { BEGIN S_RVALUE;
170                                   yyextra->accept (T_OP_COND); }
171
172 <S_RVALUE>\\\n{C_SP}*           {  }
173 <S_RVALUE>{STRING}              { BEGIN INITIAL;
174                                   size_t cb = yyleng;
175                                   while (cb && isspace (yytext[cb - 1]))
176                                       --cb;
177                                   yytext[cb - 1] = 0;
178                                   yyextra->accept (T_STRING, yytext + 1); }
179 <S_RVALUE>{SSTRING}             { BEGIN INITIAL;
180                                   size_t cb = yyleng;
181                                   while (cb && isspace (yytext[cb - 1]))
182                                       --cb;
183                                   yytext[cb - 1] = 0;
184                                   yyextra->accept (T_STRING, yytext + 1); }
185
186 <S_RVALUE>{VALUE}               { ERROR (errorUnexpectedInput);  }
187 <S_RVALUE>{C_SP}*\n+            { BEGIN INITIAL;
188                                   yyextra->accept (T_STRING, NULL); }
189
190 {K_INCLUDE}                     { BEGIN S_INCLUDE;
191                                   yyextra->accept (T_INCLUDE); }
192 {K_REQUIRE}                     { BEGIN S_REQUIRE;
193                                   yyextra->accept (T_REQUIRE); }
194 {K_INHERIT}                     { BEGIN S_INHERIT;
195                                   yyextra->accept (T_INHERIT); }
196 {K_ADDTASK}                     { BEGIN S_TASK;
197                                   yyextra->accept (T_ADDTASK); }
198 {K_ADDHANDLER}                  { yyextra->accept (T_ADDHANDLER); }
199 {K_EXPORT_FUNC}                 { BEGIN S_FUNC;
200                                   yyextra->accept (T_EXPORT_FUNC); }
201 <S_TASK>{K_BEFORE}              { yyextra->accept (T_BEFORE); }
202 <S_TASK>{K_AFTER}               { yyextra->accept (T_AFTER); }
203 <INITIAL>{K_EXPORT}             { yyextra->accept (T_EXPORT); }
204
205 <INITIAL>{K_FAKEROOT}           { yyextra->accept (T_FAKEROOT); }
206 <INITIAL>{K_PYTHON}             { yyextra->accept (T_PYTHON); }
207 {PROC}{C_SP}*{B_OPEN}{C_SP}*\n*  { BEGIN S_PROC;
208                                   yyextra->accept (T_PROC_OPEN); }
209 <S_PROC>{B_CLOSE}{C_SP}*\n*      { BEGIN INITIAL;
210                                   yyextra->accept (T_PROC_CLOSE); }
211 <S_PROC>([^}][^\n]*)?\n*        { yyextra->accept (T_PROC_BODY, yytext); }
212
213 {K_DEF}                         { BEGIN S_DEF; }
214 <S_DEF>{SYMBOL}                 { BEGIN S_DEF_ARGS;
215                                   yyextra->accept (T_SYMBOL, yytext); }
216 <S_DEF_ARGS>[^\n:]*:            { yyextra->accept (T_DEF_ARGS, yytext); }
217 <S_DEF_ARGS>{C_SP}*\n           { BEGIN S_DEF_BODY; }
218 <S_DEF_BODY>{C_SP}+[^\n]*\n     { yyextra->accept (T_DEF_BODY, yytext); }
219 <S_DEF_BODY>\n                  { yyextra->accept (T_DEF_BODY, yytext); }
220 <S_DEF_BODY>.                   { BEGIN INITIAL; unput (yytext[0]); }
221
222 {COMMENT}                       { }
223
224 <INITIAL>{SYMBOL}               { yyextra->accept (T_SYMBOL, yytext); }
225 <INITIAL>{VARIABLE}             { yyextra->accept (T_VARIABLE, yytext); }
226
227 <S_TASK>{SYMBOL}                { yyextra->accept (T_TSYMBOL, yytext); }
228 <S_FUNC>{SYMBOL}                { yyextra->accept (T_FSYMBOL, yytext); }
229 <S_INHERIT>{SYMBOL}             { yyextra->accept (T_ISYMBOL, yytext); }
230 <S_INCLUDE>{FILENAME}           { BEGIN INITIAL;
231                                   yyextra->accept (T_ISYMBOL, yytext); }
232 <S_REQUIRE>{FILENAME}           { BEGIN INITIAL;
233                                   yyextra->accept (T_ISYMBOL, yytext); }
234 <S_TASK>\n                      { BEGIN INITIAL; }
235 <S_FUNC>\n                      { BEGIN INITIAL; }
236 <S_INHERIT>\n                   { BEGIN INITIAL; }
237
238 [ \t\r\n]                       /* Insignificant whitespace */
239
240 .                               { ERROR (errorUnexpectedInput); }
241
242                                 /* Check for premature termination */
243 <<EOF>>                         { return T_EOF; }
244
245 %%
246
247 void lex_t::accept (int token, const char* sz) 
248 {
249     token_t t;
250     memset (&t, 0, sizeof (t));
251     t.copyString(sz);
252
253     /* tell lemon to parse the token */
254     parse (parser, token, t, this);
255 }
256
257 int lex_t::line ()const
258 {
259     return yyget_lineno (scanner);
260 }
261
262 const char* lex_t::filename ()const
263 {
264     return m_fileName;
265 }
266
267 void parse (MappedFile* mf)
268 {
269     void* parser = bbparseAlloc (malloc);
270     yyscan_t scanner;
271     lex_t lex;
272
273     yylex_init (&scanner);
274
275     lex.parser = parser;
276     lex.scanner = scanner;
277     lex.mf = mf;
278     lex.rgbInput = mf->m_rgb;
279     lex.cbInput = mf->m_cb;
280     lex.parse = bbparse;
281     yyset_extra (&lex, scanner);
282
283
284     int result = yylex (scanner);
285
286     lex.accept (0);
287     bbparseTrace (NULL, NULL);
288
289     if (result != T_EOF)
290         WARNING ("premature end of file\n");
291
292     yylex_destroy (scanner);
293     bbparseFree (parser, free);
294 }