]> git.saurik.com Git - bison.git/blame - src/scan-code.l
* HACKING (Release Procedure): Recommend a secure automake.
[bison.git] / src / scan-code.l
CommitLineData
e9071366
AD
1/* Bison Action Scanner -*- C -*-
2
98744608 3 Copyright (C) 2006, 2007, 2008-2009 Free Software Foundation, Inc.
e9071366
AD
4
5 This file is part of Bison, the GNU Compiler Compiler.
6
f16b0819 7 This program is free software: you can redistribute it and/or modify
e9071366 8 it under the terms of the GNU General Public License as published by
f16b0819 9 the Free Software Foundation, either version 3 of the License, or
e9071366
AD
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
f16b0819 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
e9071366 19
42f8609b 20%option debug nodefault noinput nounput noyywrap never-interactive
e9071366
AD
21%option prefix="code_" outfile="lex.yy.c"
22
23%{
24/* Work around a bug in flex 2.5.31. See Debian bug 333231
25 <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */
26#undef code_wrap
27#define code_wrap() 1
28
29#define FLEX_PREFIX(Id) code_ ## Id
30#include "flex-scanner.h"
f9bfc42a
JD
31
32#include "complain.h"
e9071366
AD
33#include "reader.h"
34#include "getargs.h"
e9071366
AD
35#include <get-errno.h>
36#include <quote.h>
37
38#include "scan-code.h"
28e52c0d 39#include "symlist.h"
e9071366
AD
40
41/* The current calling start condition: SC_RULE_ACTION or
42 SC_SYMBOL_ACTION. */
28e52c0d 43# define YY_DECL static char *code_lex (code_props *self, int sc_context)
e9071366
AD
44YY_DECL;
45
46#define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng);
47
4210cd0b
JD
48static void handle_action_dollar (symbol_list *rule, char *cp,
49 location dollar_loc);
50static void handle_action_at (symbol_list *rule, char *cp, location at_loc);
e9071366
AD
51static location the_location;
52static location *loc = &the_location;
ddc8ede1 53
28e52c0d
JD
54/* A string representing the most recent translation. */
55static char *last_string;
56
ddc8ede1
PE
57/* True if an untyped $$ or $n was seen. */
58static bool untyped_var_seen;
e9071366
AD
59%}
60 /* C and C++ comments in code. */
61%x SC_COMMENT SC_LINE_COMMENT
62 /* Strings and characters in code. */
63%x SC_STRING SC_CHARACTER
64 /* Whether in a rule or symbol action. Specifies the translation
65 of $ and @. */
66%x SC_RULE_ACTION SC_SYMBOL_ACTION
67
68
69/* POSIX says that a tag must be both an id and a C union member, but
70 historically almost any character is allowed in a tag. We disallow
71 NUL and newline, as this simplifies our implementation. */
72tag [^\0\n>]+
73
74/* Zero or more instances of backslash-newline. Following GCC, allow
75 white space between the backslash and the newline. */
76splice (\\[ \f\t\v]*\n)*
77
78%%
79
80%{
2346344a 81 /* Nesting level of the current code in braces. */
4f82b42a 82 int braces_level = 0;
2346344a 83
e9071366
AD
84 /* This scanner is special: it is invoked only once, henceforth
85 is expected to return only once. This initialization is
86 therefore done once per action to translate. */
4f82b42a
PE
87 aver (sc_context == SC_SYMBOL_ACTION
88 || sc_context == SC_RULE_ACTION
89 || sc_context == INITIAL);
e9071366
AD
90 BEGIN sc_context;
91%}
92
93 /*------------------------------------------------------------.
94 | Scanning a C comment. The initial `/ *' is already eaten. |
95 `------------------------------------------------------------*/
96
97<SC_COMMENT>
98{
99 "*"{splice}"/" STRING_GROW; BEGIN sc_context;
100}
101
102
103 /*--------------------------------------------------------------.
104 | Scanning a line comment. The initial `//' is already eaten. |
105 `--------------------------------------------------------------*/
106
107<SC_LINE_COMMENT>
108{
109 "\n" STRING_GROW; BEGIN sc_context;
110 {splice} STRING_GROW;
111}
112
113
114 /*--------------------------------------------.
115 | Scanning user-code characters and strings. |
116 `--------------------------------------------*/
117
118<SC_CHARACTER,SC_STRING>
119{
120 {splice}|\\{splice}. STRING_GROW;
121}
122
123<SC_CHARACTER>
124{
125 "'" STRING_GROW; BEGIN sc_context;
126}
127
128<SC_STRING>
129{
130 "\"" STRING_GROW; BEGIN sc_context;
131}
132
133
134<SC_RULE_ACTION,SC_SYMBOL_ACTION>{
135 "'" {
136 STRING_GROW;
137 BEGIN SC_CHARACTER;
138 }
139 "\"" {
140 STRING_GROW;
141 BEGIN SC_STRING;
142 }
143 "/"{splice}"*" {
144 STRING_GROW;
145 BEGIN SC_COMMENT;
146 }
147 "/"{splice}"/" {
148 STRING_GROW;
149 BEGIN SC_LINE_COMMENT;
150 }
151}
152
153<SC_RULE_ACTION>
154{
28e52c0d
JD
155 "$"("<"{tag}">")?(-?[0-9]+|"$") {
156 handle_action_dollar (self->rule, yytext, *loc);
157 }
158 "@"(-?[0-9]+|"$") {
159 handle_action_at (self->rule, yytext, *loc);
160 }
e9071366
AD
161
162 "$" {
163 warn_at (*loc, _("stray `$'"));
164 obstack_sgrow (&obstack_for_string, "$][");
165 }
166 "@" {
167 warn_at (*loc, _("stray `@'"));
168 obstack_sgrow (&obstack_for_string, "@@");
169 }
2346344a
AD
170
171 "{" STRING_GROW; ++braces_level;
172 "}" {
14da0cdd 173 bool outer_brace = --braces_level == 0;
2346344a
AD
174
175 /* As an undocumented Bison extension, append `;' before the last
176 brace in braced code, so that the user code can omit trailing
177 `;'. But do not append `;' if emulating Yacc, since Yacc does
7ed73f82
JD
178 not append one. Also, some output languages (like Java) do not
179 accept an extra semicolon, so don't append if the user specified
180 a skeleton or language.
2346344a
AD
181
182 FIXME: Bison should warn if a semicolon seems to be necessary
183 here, and should omit the semicolon if it seems unnecessary
184 (e.g., after ';', '{', or '}', each followed by comments or
185 white space). Such a warning shouldn't depend on --yacc; it
186 should depend on a new --pedantic option, which would cause
187 Bison to warn if it detects an extension to POSIX. --pedantic
188 should also diagnose other Bison extensions like %yacc.
189 Perhaps there should also be a GCC-style --pedantic-errors
190 option, so that such warnings are diagnosed as errors. */
7ed73f82
JD
191 if (outer_brace && !yacc_flag && language_prio == default_prio
192 && skeleton_prio == default_prio)
2346344a
AD
193 obstack_1grow (&obstack_for_string, ';');
194
195 STRING_GROW;
196 }
e9071366
AD
197}
198
199<SC_SYMBOL_ACTION>
200{
28e52c0d
JD
201 "$$" {
202 obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
203 self->is_value_used = true;
204 }
e785ccf7
JD
205 "@$" {
206 obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
207 locations_flag = true;
208 }
e9071366
AD
209}
210
211
212 /*-----------------------------------------.
213 | Escape M4 quoting characters in C code. |
214 `-----------------------------------------*/
215
216<*>
217{
218 \$ obstack_sgrow (&obstack_for_string, "$][");
219 \@ obstack_sgrow (&obstack_for_string, "@@");
220 \[ obstack_sgrow (&obstack_for_string, "@{");
221 \] obstack_sgrow (&obstack_for_string, "@}");
222}
223
224 /*-----------------------------------------------------.
225 | By default, grow the string obstack with the input. |
226 `-----------------------------------------------------*/
227
228<*>.|\n STRING_GROW;
229
230 /* End of processing. */
231<*><<EOF>> {
28e52c0d
JD
232 STRING_FINISH;
233 return last_string;
e9071366
AD
234 }
235
236%%
237
238/* Keeps track of the maximum number of semantic values to the left of
239 a handle (those referenced by $0, $-1, etc.) are required by the
240 semantic actions of this grammar. */
241int max_left_semantic_context = 0;
242
243
244/*------------------------------------------------------------------.
245| TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
246| |
247| Possible inputs: $[<TYPENAME>]($|integer) |
248| |
249| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
250`------------------------------------------------------------------*/
251
252static void
4210cd0b 253handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 254{
28e52c0d 255 char const *type_name = NULL;
e9071366 256 char *cp = text + 1;
ffa4ba3a
JD
257 symbol_list *effective_rule;
258 int effective_rule_length;
259
260 if (rule->midrule_parent_rule)
261 {
262 effective_rule = rule->midrule_parent_rule;
263 effective_rule_length = rule->midrule_parent_rhs_index - 1;
264 }
265 else
266 {
267 effective_rule = rule;
268 effective_rule_length = symbol_list_length (rule->next);
269 }
e9071366
AD
270
271 /* Get the type name if explicit. */
272 if (*cp == '<')
273 {
274 type_name = ++cp;
275 while (*cp != '>')
276 ++cp;
277 *cp = '\0';
278 ++cp;
ddc8ede1
PE
279 if (untyped_var_seen)
280 complain_at (dollar_loc, _("explicit type given in untyped grammar"));
281 tag_seen = true;
e9071366
AD
282 }
283
284 if (*cp == '$')
285 {
286 if (!type_name)
4210cd0b 287 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
288
289 if (!type_name)
ad6b1efa 290 {
ddc8ede1
PE
291 if (union_seen | tag_seen)
292 {
293 if (rule->midrule_parent_rule)
294 complain_at (dollar_loc,
295 _("$$ for the midrule at $%d of `%s'"
296 " has no declared type"),
297 rule->midrule_parent_rhs_index,
3be03b13 298 effective_rule->content.sym->tag);
ddc8ede1
PE
299 else
300 complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
3be03b13 301 rule->content.sym->tag);
ddc8ede1 302 }
ad6b1efa 303 else
ddc8ede1
PE
304 untyped_var_seen = true;
305 type_name = "";
ad6b1efa 306 }
ddc8ede1 307
e9071366
AD
308 obstack_fgrow1 (&obstack_for_string,
309 "]b4_lhs_value([%s])[", type_name);
f6857bbf 310 rule->action_props.is_value_used = true;
e9071366
AD
311 }
312 else
313 {
ddc8ede1
PE
314 long int num = strtol (cp, NULL, 10);
315
316 if (1 - INT_MAX + effective_rule_length <= num
317 && num <= effective_rule_length)
e9071366
AD
318 {
319 int n = num;
ddc8ede1
PE
320 if (max_left_semantic_context < 1 - n)
321 max_left_semantic_context = 1 - n;
322 if (!type_name && 0 < n)
0c8e079f 323 type_name =
ffa4ba3a 324 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
e9071366 325 if (!type_name)
ddc8ede1
PE
326 {
327 if (union_seen | tag_seen)
328 complain_at (dollar_loc, _("$%d of `%s' has no declared type"),
3be03b13 329 n, effective_rule->content.sym->tag);
ddc8ede1
PE
330 else
331 untyped_var_seen = true;
332 type_name = "";
333 }
334
e9071366
AD
335 obstack_fgrow3 (&obstack_for_string,
336 "]b4_rhs_value(%d, %d, [%s])[",
ffa4ba3a 337 effective_rule_length, n, type_name);
28e52c0d 338 if (n > 0)
f6857bbf
JD
339 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
340 true;
e9071366
AD
341 }
342 else
0c8e079f 343 complain_at (dollar_loc, _("integer out of range: %s"), quote (text));
e9071366
AD
344 }
345}
346
347
348/*------------------------------------------------------.
349| TEXT is a location token (i.e., a `@...'). Output to |
350| OBSTACK_FOR_STRING a reference to this location. |
351`------------------------------------------------------*/
352
353static void
4210cd0b 354handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366
AD
355{
356 char *cp = text + 1;
4f82b42a
PE
357 int effective_rule_length =
358 (rule->midrule_parent_rule
359 ? rule->midrule_parent_rhs_index - 1
360 : symbol_list_length (rule->next));
ffa4ba3a 361
4f82b42a 362 locations_flag = true;
e9071366
AD
363
364 if (*cp == '$')
365 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
366 else
367 {
ddc8ede1 368 long int num = strtol (cp, NULL, 10);
e9071366 369
ddc8ede1
PE
370 if (1 - INT_MAX + effective_rule_length <= num
371 && num <= effective_rule_length)
e9071366
AD
372 {
373 int n = num;
374 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
ffa4ba3a 375 effective_rule_length, n);
e9071366
AD
376 }
377 else
0c8e079f 378 complain_at (at_loc, _("integer out of range: %s"), quote (text));
e9071366
AD
379 }
380}
381
382
383/*-------------------------.
384| Initialize the scanner. |
385`-------------------------*/
386
28e52c0d 387/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 388 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 389
eb095650 390static char const *
28e52c0d 391translate_action (code_props *self, int sc_context)
e9071366 392{
2ce4ed68 393 char *res;
e9071366
AD
394 static bool initialized = false;
395 if (!initialized)
396 {
397 obstack_init (&obstack_for_string);
e9071366
AD
398 yy_flex_debug = 0;
399 initialized = true;
400 }
401
28e52c0d
JD
402 loc->start = loc->end = self->location.start;
403 yy_switch_to_buffer (yy_scan_string (self->code));
404 res = code_lex (self, sc_context);
e9071366
AD
405 yy_delete_buffer (YY_CURRENT_BUFFER);
406
407 return res;
408}
409
28e52c0d
JD
410/*------------------------------------------------------------------------.
411| Implementation of the public interface as documented in "scan-code.h". |
412`------------------------------------------------------------------------*/
413
414void
415code_props_none_init (code_props *self)
76290368 416{
28e52c0d 417 *self = code_props_none;
76290368
JD
418}
419
28e52c0d
JD
420code_props const code_props_none = CODE_PROPS_NONE_INIT;
421
422void
423code_props_plain_init (code_props *self, char const *code, location code_loc)
76290368 424{
28e52c0d
JD
425 self->kind = CODE_PROPS_PLAIN;
426 self->code = code;
427 self->location = code_loc;
428 self->is_value_used = false;
429 self->rule = NULL;
76290368
JD
430}
431
28e52c0d
JD
432void
433code_props_symbol_action_init (code_props *self, char const *code,
434 location code_loc)
e9071366 435{
28e52c0d
JD
436 self->kind = CODE_PROPS_SYMBOL_ACTION;
437 self->code = code;
438 self->location = code_loc;
439 self->is_value_used = false;
440 self->rule = NULL;
e9071366
AD
441}
442
28e52c0d
JD
443void
444code_props_rule_action_init (code_props *self, char const *code,
445 location code_loc, symbol_list *rule)
446{
447 self->kind = CODE_PROPS_RULE_ACTION;
448 self->code = code;
449 self->location = code_loc;
450 self->is_value_used = false;
451 self->rule = rule;
452}
453
454void
455code_props_translate_code (code_props *self)
456{
457 switch (self->kind)
458 {
459 case CODE_PROPS_NONE:
460 break;
461 case CODE_PROPS_PLAIN:
462 self->code = translate_action (self, INITIAL);
463 break;
464 case CODE_PROPS_SYMBOL_ACTION:
465 self->code = translate_action (self, SC_SYMBOL_ACTION);
466 break;
467 case CODE_PROPS_RULE_ACTION:
468 self->code = translate_action (self, SC_RULE_ACTION);
469 break;
470 }
471}
472
473void
474code_scanner_last_string_free (void)
475{
476 STRING_FREE;
477}
e9071366
AD
478
479void
480code_scanner_free (void)
481{
482 obstack_free (&obstack_for_string, 0);
483 /* Reclaim Flex's buffers. */
580b8926 484 yylex_destroy ();
e9071366 485}