summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/parse/parse_c/bitbakescanner.l
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/parse/parse_c/bitbakescanner.l')
-rw-r--r--bitbake/lib/bb/parse/parse_c/bitbakescanner.l288
1 files changed, 288 insertions, 0 deletions
diff --git a/bitbake/lib/bb/parse/parse_c/bitbakescanner.l b/bitbake/lib/bb/parse/parse_c/bitbakescanner.l
new file mode 100644
index 0000000000..782bc57a0f
--- /dev/null
+++ b/bitbake/lib/bb/parse/parse_c/bitbakescanner.l
@@ -0,0 +1,288 @@
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
77extern void *bbparseAlloc(void *(*mallocProc)(size_t));
78extern void bbparseFree(void *p, void (*freeProc)(void*));
79extern void *bbparseAlloc(void *(*mallocProc)(size_t));
80extern void *bbparse(void*, int, token_t, lex_t*);
81extern void bbparseTrace(FILE *TraceFILE, char *zTracePrompt);
82
83//static const char* rgbInput;
84//static size_t cbInput;
85
86
87int lineError;
88int errorParse;
89
90enum {
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
107static const char* fixup_escapes (const char* sz);
108
109%}
110
111
112C_SP [ \t]
113COMMENT #.*\n
114OP_ASSIGN "="
115OP_IMMEDIATE ":="
116OP_PREPEND "=+"
117OP_APPEND "+="
118OP_COND "?="
119B_OPEN "{"
120B_CLOSE "}"
121
122K_ADDTASK "addtask"
123K_ADDHANDLER "addhandler"
124K_AFTER "after"
125K_BEFORE "before"
126K_DEF "def"
127K_INCLUDE "include"
128K_REQUIRE "require"
129K_INHERIT "inherit"
130K_PYTHON "python"
131K_FAKEROOT "fakeroot"
132K_EXPORT "export"
133K_EXPORT_FUNC "EXPORT_FUNCTIONS"
134
135STRING \"([^\n\r]|"\\\n")*\"
136SSTRING \'([^\n\r]|"\\\n")*\'
137VALUE ([^'" \t\n])|([^'" \t\n]([^\n]|(\\\n))*[^'" \t\n])
138
139C_SS [a-zA-Z_]
140C_SB [a-zA-Z0-9_+-.]
141REF $\{{C_SS}{C_SB}*\}
142SYMBOL {C_SS}{C_SB}*
143VARIABLE $?{C_SS}({C_SB}*|{REF})*(\[[a-zA-Z0-9_]*\])?
144FILENAME ([a-zA-Z_./]|{REF})(([-+a-zA-Z0-9_./]*)|{REF})*
145
146PROC \({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
247void 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
257int lex_t::line ()const
258{
259 return yyget_lineno (scanner);
260}
261
262void parse (FILE* file, PyObject* data)
263{
264 void* parser = bbparseAlloc (malloc);
265 yyscan_t scanner;
266 lex_t lex;
267
268 yylex_init (&scanner);
269
270 lex.parser = parser;
271 lex.scanner = scanner;
272 lex.file = file;
273 lex.data = data;
274 lex.parse = bbparse;
275 yyset_extra (&lex, scanner);
276
277
278 int result = yylex (scanner);
279
280 lex.accept (0);
281 bbparseTrace (NULL, NULL);
282
283 if (result != T_EOF)
284 printf ("premature end of file\n");
285
286 yylex_destroy (scanner);
287 bbparseFree (parser, free);
288}