bitbake/lib/bb/parse/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_INHERIT       "inherit"
129 K_PYTHON        "python"
130 K_FAKEROOT      "fakeroot"
131 K_EXPORT        "export"
132 K_EXPORT_FUNC   "EXPORT_FUNCTIONS"
133
134 STRING          \"([^\n\r]|"\\\n")*\"
135 SSTRING         \'([^\n\r]|"\\\n")*\'
136 VALUE           ([^'" \t\n])|([^'" \t\n]([^\n]|(\\\n))*[^'" \t\n])
137
138 C_SS            [a-zA-Z_]
139 C_SB            [a-zA-Z0-9_+-.]
140 REF             $\{{C_SS}{C_SB}*\}
141 SYMBOL          {C_SS}{C_SB}*
142 VARIABLE        $?{C_SS}({C_SB}*|{REF})*(\[[a-zA-Z0-9_]*\])?
143 FILENAME        ([a-zA-Z_./]|{REF})(([-+a-zA-Z0-9_./]*)|{REF})*
144
145 PROC            \({C_SP}*\)
146
147 %s S_DEF
148 %s S_DEF_ARGS
149 %s S_DEF_BODY
150 %s S_FUNC
151 %s S_INCLUDE
152 %s S_INHERIT
153 %s S_PROC
154 %s S_RVALUE
155 %s S_TASK
156
157 %%
158
159 {OP_APPEND}                     { BEGIN S_RVALUE;
160                                   yyextra->accept (T_OP_APPEND); }
161 {OP_PREPEND}                    { BEGIN S_RVALUE;
162                                   yyextra->accept (T_OP_PREPEND); }
163 {OP_IMMEDIATE}                  { BEGIN S_RVALUE;
164                                   yyextra->accept (T_OP_IMMEDIATE); }
165 {OP_ASSIGN}                     { BEGIN S_RVALUE;
166                                   yyextra->accept (T_OP_ASSIGN); }
167 {OP_COND}                       { BEGIN S_RVALUE;
168                                   yyextra->accept (T_OP_COND); }
169
170 <S_RVALUE>\\\n{C_SP}*           {  }
171 <S_RVALUE>{STRING}              { BEGIN INITIAL;
172                                   size_t cb = yyleng;
173                                   while (cb && isspace (yytext[cb - 1]))
174                                       --cb;
175                                   yytext[cb - 1] = 0;
176                                   yyextra->accept (T_STRING, yytext + 1); }
177 <S_RVALUE>{SSTRING}             { BEGIN INITIAL;
178                                   size_t cb = yyleng;
179                                   while (cb && isspace (yytext[cb - 1]))
180                                       --cb;
181                                   yytext[cb - 1] = 0;
182                                   yyextra->accept (T_STRING, yytext + 1); }
183
184 <S_RVALUE>{VALUE}               { ERROR (errorUnexpectedInput);  }
185 <S_RVALUE>{C_SP}*\n+            { BEGIN INITIAL;
186                                   yyextra->accept (T_STRING, NULL); }
187
188 {K_INCLUDE}                     { BEGIN S_INCLUDE;
189                                   yyextra->accept (T_INCLUDE); }
190 {K_INHERIT}                     { BEGIN S_INHERIT;
191                                   yyextra->accept (T_INHERIT); }
192 {K_ADDTASK}                     { BEGIN S_TASK;
193                                   yyextra->accept (T_ADDTASK); }
194 {K_ADDHANDLER}                  { yyextra->accept (T_ADDHANDLER); }
195 {K_EXPORT_FUNC}                 { BEGIN S_FUNC;
196                                   yyextra->accept (T_EXPORT_FUNC); }
197 <S_TASK>{K_BEFORE}              { yyextra->accept (T_BEFORE); }
198 <S_TASK>{K_AFTER}               { yyextra->accept (T_AFTER); }
199 <INITIAL>{K_EXPORT}             { yyextra->accept (T_EXPORT); }
200
201 <INITIAL>{K_FAKEROOT}           { yyextra->accept (T_FAKEROOT); }
202 <INITIAL>{K_PYTHON}             { yyextra->accept (T_PYTHON); }
203 {PROC}{C_SP}*{B_OPEN}{C_SP}*\n*  { BEGIN S_PROC;
204                                   yyextra->accept (T_PROC_OPEN); }
205 <S_PROC>{B_CLOSE}{C_SP}*\n*      { BEGIN INITIAL;
206                                   yyextra->accept (T_PROC_CLOSE); }
207 <S_PROC>([^}][^\n]*)?\n*        { yyextra->accept (T_PROC_BODY, yytext); }
208
209 {K_DEF}                         { BEGIN S_DEF; }
210 <S_DEF>{SYMBOL}                 { BEGIN S_DEF_ARGS;
211                                   yyextra->accept (T_SYMBOL, yytext); }
212 <S_DEF_ARGS>[^\n:]*:            { yyextra->accept (T_DEF_ARGS, yytext); }
213 <S_DEF_ARGS>{C_SP}*\n           { BEGIN S_DEF_BODY; }
214 <S_DEF_BODY>{C_SP}+[^\n]*\n     { yyextra->accept (T_DEF_BODY, yytext); }
215 <S_DEF_BODY>\n                  { yyextra->accept (T_DEF_BODY, yytext); }
216 <S_DEF_BODY>.                   { BEGIN INITIAL; unput (yytext[0]); }
217
218 {COMMENT}                       { }
219
220 <INITIAL>{SYMBOL}               { yyextra->accept (T_SYMBOL, yytext); }
221 <INITIAL>{VARIABLE}             { yyextra->accept (T_VARIABLE, yytext); }
222
223 <S_TASK>{SYMBOL}                { yyextra->accept (T_TSYMBOL, yytext); }
224 <S_FUNC>{SYMBOL}                { yyextra->accept (T_FSYMBOL, yytext); }
225 <S_INHERIT>{SYMBOL}             { yyextra->accept (T_ISYMBOL, yytext); }
226 <S_INCLUDE>{FILENAME}           { BEGIN INITIAL;
227                                   yyextra->accept (T_ISYMBOL, yytext); }
228
229 <S_TASK>\n                      { BEGIN INITIAL; }
230 <S_FUNC>\n                      { BEGIN INITIAL; }
231 <S_INHERIT>\n                   { BEGIN INITIAL; }
232
233 [ \t\r\n]                       /* Insignificant whitespace */
234
235 .                               { ERROR (errorUnexpectedInput); }
236
237                                 /* Check for premature termination */
238 <<EOF>>                         { return T_EOF; }
239
240 %%
241
242 void lex_t::accept (int token, const char* sz) 
243 {
244     token_t t;
245     memset (&t, 0, sizeof (t));
246     t.copyString(sz);
247
248     /* tell lemon to parse the token */
249     parse (parser, token, t, this);
250 }
251
252 int lex_t::line ()const
253 {
254     return yyget_lineno (scanner);
255 }
256
257 const char* lex_t::filename ()const
258 {
259     return m_fileName;
260 }
261
262 void parse (MappedFile* mf)
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.mf = mf;
273     lex.rgbInput = mf->m_rgb;
274     lex.cbInput = mf->m_cb;
275     lex.parse = bbparse;
276     yyset_extra (&lex, scanner);
277
278
279     int result = yylex (scanner);
280
281     lex.accept (0);
282     bbparseTrace (NULL, NULL);
283
284     if (result != T_EOF)
285         WARNING ("premature end of file\n");
286
287     yylex_destroy (scanner);
288     bbparseFree (parser, free);
289 }