]> git.saurik.com Git - bison.git/blame - src/scan-code.l
Accept a token number in a %left, %right, or %nonassoc for POSIX
[bison.git] / src / scan-code.l
CommitLineData
e9071366
AD
1/* Bison Action Scanner -*- C -*-
2
28e52c0d 3 Copyright (C) 2006, 2007 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
AD
19
20%option debug nodefault nounput noyywrap never-interactive
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 "}" {
173 bool outer_brace = --braces_level < 0;
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
178 not append one.
179
180 FIXME: Bison should warn if a semicolon seems to be necessary
181 here, and should omit the semicolon if it seems unnecessary
182 (e.g., after ';', '{', or '}', each followed by comments or
183 white space). Such a warning shouldn't depend on --yacc; it
184 should depend on a new --pedantic option, which would cause
185 Bison to warn if it detects an extension to POSIX. --pedantic
186 should also diagnose other Bison extensions like %yacc.
187 Perhaps there should also be a GCC-style --pedantic-errors
188 option, so that such warnings are diagnosed as errors. */
189 if (outer_brace && ! yacc_flag)
190 obstack_1grow (&obstack_for_string, ';');
191
192 STRING_GROW;
193 }
e9071366
AD
194}
195
196<SC_SYMBOL_ACTION>
197{
28e52c0d
JD
198 "$$" {
199 obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
200 self->is_value_used = true;
201 }
e785ccf7
JD
202 "@$" {
203 obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
204 locations_flag = true;
205 }
e9071366
AD
206}
207
208
209 /*-----------------------------------------.
210 | Escape M4 quoting characters in C code. |
211 `-----------------------------------------*/
212
213<*>
214{
215 \$ obstack_sgrow (&obstack_for_string, "$][");
216 \@ obstack_sgrow (&obstack_for_string, "@@");
217 \[ obstack_sgrow (&obstack_for_string, "@{");
218 \] obstack_sgrow (&obstack_for_string, "@}");
219}
220
221 /*-----------------------------------------------------.
222 | By default, grow the string obstack with the input. |
223 `-----------------------------------------------------*/
224
225<*>.|\n STRING_GROW;
226
227 /* End of processing. */
228<*><<EOF>> {
28e52c0d
JD
229 STRING_FINISH;
230 return last_string;
e9071366
AD
231 }
232
233%%
234
235/* Keeps track of the maximum number of semantic values to the left of
236 a handle (those referenced by $0, $-1, etc.) are required by the
237 semantic actions of this grammar. */
238int max_left_semantic_context = 0;
239
240
241/*------------------------------------------------------------------.
242| TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
243| |
244| Possible inputs: $[<TYPENAME>]($|integer) |
245| |
246| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
247`------------------------------------------------------------------*/
248
249static void
4210cd0b 250handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 251{
28e52c0d 252 char const *type_name = NULL;
e9071366 253 char *cp = text + 1;
ffa4ba3a
JD
254 symbol_list *effective_rule;
255 int effective_rule_length;
256
257 if (rule->midrule_parent_rule)
258 {
259 effective_rule = rule->midrule_parent_rule;
260 effective_rule_length = rule->midrule_parent_rhs_index - 1;
261 }
262 else
263 {
264 effective_rule = rule;
265 effective_rule_length = symbol_list_length (rule->next);
266 }
e9071366
AD
267
268 /* Get the type name if explicit. */
269 if (*cp == '<')
270 {
271 type_name = ++cp;
272 while (*cp != '>')
273 ++cp;
274 *cp = '\0';
275 ++cp;
ddc8ede1
PE
276 if (untyped_var_seen)
277 complain_at (dollar_loc, _("explicit type given in untyped grammar"));
278 tag_seen = true;
e9071366
AD
279 }
280
281 if (*cp == '$')
282 {
283 if (!type_name)
4210cd0b 284 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
285
286 if (!type_name)
ad6b1efa 287 {
ddc8ede1
PE
288 if (union_seen | tag_seen)
289 {
290 if (rule->midrule_parent_rule)
291 complain_at (dollar_loc,
292 _("$$ for the midrule at $%d of `%s'"
293 " has no declared type"),
294 rule->midrule_parent_rhs_index,
3be03b13 295 effective_rule->content.sym->tag);
ddc8ede1
PE
296 else
297 complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
3be03b13 298 rule->content.sym->tag);
ddc8ede1 299 }
ad6b1efa 300 else
ddc8ede1
PE
301 untyped_var_seen = true;
302 type_name = "";
ad6b1efa 303 }
ddc8ede1 304
e9071366
AD
305 obstack_fgrow1 (&obstack_for_string,
306 "]b4_lhs_value([%s])[", type_name);
f6857bbf 307 rule->action_props.is_value_used = true;
e9071366
AD
308 }
309 else
310 {
ddc8ede1
PE
311 long int num = strtol (cp, NULL, 10);
312
313 if (1 - INT_MAX + effective_rule_length <= num
314 && num <= effective_rule_length)
e9071366
AD
315 {
316 int n = num;
ddc8ede1
PE
317 if (max_left_semantic_context < 1 - n)
318 max_left_semantic_context = 1 - n;
319 if (!type_name && 0 < n)
0c8e079f 320 type_name =
ffa4ba3a 321 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
e9071366 322 if (!type_name)
ddc8ede1
PE
323 {
324 if (union_seen | tag_seen)
325 complain_at (dollar_loc, _("$%d of `%s' has no declared type"),
3be03b13 326 n, effective_rule->content.sym->tag);
ddc8ede1
PE
327 else
328 untyped_var_seen = true;
329 type_name = "";
330 }
331
e9071366
AD
332 obstack_fgrow3 (&obstack_for_string,
333 "]b4_rhs_value(%d, %d, [%s])[",
ffa4ba3a 334 effective_rule_length, n, type_name);
28e52c0d 335 if (n > 0)
f6857bbf
JD
336 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
337 true;
e9071366
AD
338 }
339 else
0c8e079f 340 complain_at (dollar_loc, _("integer out of range: %s"), quote (text));
e9071366
AD
341 }
342}
343
344
345/*------------------------------------------------------.
346| TEXT is a location token (i.e., a `@...'). Output to |
347| OBSTACK_FOR_STRING a reference to this location. |
348`------------------------------------------------------*/
349
350static void
4210cd0b 351handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366
AD
352{
353 char *cp = text + 1;
4f82b42a
PE
354 int effective_rule_length =
355 (rule->midrule_parent_rule
356 ? rule->midrule_parent_rhs_index - 1
357 : symbol_list_length (rule->next));
ffa4ba3a 358
4f82b42a 359 locations_flag = true;
e9071366
AD
360
361 if (*cp == '$')
362 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
363 else
364 {
ddc8ede1 365 long int num = strtol (cp, NULL, 10);
e9071366 366
ddc8ede1
PE
367 if (1 - INT_MAX + effective_rule_length <= num
368 && num <= effective_rule_length)
e9071366
AD
369 {
370 int n = num;
371 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
ffa4ba3a 372 effective_rule_length, n);
e9071366
AD
373 }
374 else
0c8e079f 375 complain_at (at_loc, _("integer out of range: %s"), quote (text));
e9071366
AD
376 }
377}
378
379
380/*-------------------------.
381| Initialize the scanner. |
382`-------------------------*/
383
28e52c0d 384/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 385 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 386
eb095650 387static char const *
28e52c0d 388translate_action (code_props *self, int sc_context)
e9071366 389{
2ce4ed68 390 char *res;
e9071366
AD
391 static bool initialized = false;
392 if (!initialized)
393 {
394 obstack_init (&obstack_for_string);
e9071366
AD
395 yy_flex_debug = 0;
396 initialized = true;
397 }
398
28e52c0d
JD
399 loc->start = loc->end = self->location.start;
400 yy_switch_to_buffer (yy_scan_string (self->code));
401 res = code_lex (self, sc_context);
e9071366
AD
402 yy_delete_buffer (YY_CURRENT_BUFFER);
403
404 return res;
405}
406
28e52c0d
JD
407/*------------------------------------------------------------------------.
408| Implementation of the public interface as documented in "scan-code.h". |
409`------------------------------------------------------------------------*/
410
411void
412code_props_none_init (code_props *self)
76290368 413{
28e52c0d 414 *self = code_props_none;
76290368
JD
415}
416
28e52c0d
JD
417code_props const code_props_none = CODE_PROPS_NONE_INIT;
418
419void
420code_props_plain_init (code_props *self, char const *code, location code_loc)
76290368 421{
28e52c0d
JD
422 self->kind = CODE_PROPS_PLAIN;
423 self->code = code;
424 self->location = code_loc;
425 self->is_value_used = false;
426 self->rule = NULL;
76290368
JD
427}
428
28e52c0d
JD
429void
430code_props_symbol_action_init (code_props *self, char const *code,
431 location code_loc)
e9071366 432{
28e52c0d
JD
433 self->kind = CODE_PROPS_SYMBOL_ACTION;
434 self->code = code;
435 self->location = code_loc;
436 self->is_value_used = false;
437 self->rule = NULL;
e9071366
AD
438}
439
28e52c0d
JD
440void
441code_props_rule_action_init (code_props *self, char const *code,
442 location code_loc, symbol_list *rule)
443{
444 self->kind = CODE_PROPS_RULE_ACTION;
445 self->code = code;
446 self->location = code_loc;
447 self->is_value_used = false;
448 self->rule = rule;
449}
450
451void
452code_props_translate_code (code_props *self)
453{
454 switch (self->kind)
455 {
456 case CODE_PROPS_NONE:
457 break;
458 case CODE_PROPS_PLAIN:
459 self->code = translate_action (self, INITIAL);
460 break;
461 case CODE_PROPS_SYMBOL_ACTION:
462 self->code = translate_action (self, SC_SYMBOL_ACTION);
463 break;
464 case CODE_PROPS_RULE_ACTION:
465 self->code = translate_action (self, SC_RULE_ACTION);
466 break;
467 }
468}
469
470void
471code_scanner_last_string_free (void)
472{
473 STRING_FREE;
474}
e9071366
AD
475
476void
477code_scanner_free (void)
478{
479 obstack_free (&obstack_for_string, 0);
480 /* Reclaim Flex's buffers. */
580b8926 481 yylex_destroy ();
e9071366 482}