]> git.saurik.com Git - bison.git/blame - src/scan-code.l
Port small part of master's 11707b2b so future ports are easier.
[bison.git] / src / scan-code.l
CommitLineData
e9071366
AD
1/* Bison Action Scanner -*- C -*-
2
38609c34 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
4521fcdf 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 35#include "scan-code.h"
28e52c0d 36#include "symlist.h"
e9071366 37
d5e8574b
AR
38#include <c-ctype.h>
39#include <get-errno.h>
40#include <quote.h>
41
e9071366
AD
42/* The current calling start condition: SC_RULE_ACTION or
43 SC_SYMBOL_ACTION. */
28e52c0d 44# define YY_DECL static char *code_lex (code_props *self, int sc_context)
e9071366
AD
45YY_DECL;
46
47#define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng);
48
4210cd0b
JD
49static void handle_action_dollar (symbol_list *rule, char *cp,
50 location dollar_loc);
51static void handle_action_at (symbol_list *rule, char *cp, location at_loc);
7685e2f7 52
d5e8574b 53/* A string to be pushed to obstack after dollar/at has been handled. */
7685e2f7
AR
54static char *ref_tail_fields;
55
e9071366
AD
56static location the_location;
57static location *loc = &the_location;
ddc8ede1 58
28e52c0d
JD
59/* A string representing the most recent translation. */
60static char *last_string;
61
ddc8ede1
PE
62/* True if an untyped $$ or $n was seen. */
63static bool untyped_var_seen;
7685e2f7 64
e9071366
AD
65%}
66 /* C and C++ comments in code. */
67%x SC_COMMENT SC_LINE_COMMENT
68 /* Strings and characters in code. */
69%x SC_STRING SC_CHARACTER
70 /* Whether in a rule or symbol action. Specifies the translation
71 of $ and @. */
72%x SC_RULE_ACTION SC_SYMBOL_ACTION
73
74
75/* POSIX says that a tag must be both an id and a C union member, but
76 historically almost any character is allowed in a tag. We disallow
77 NUL and newline, as this simplifies our implementation. */
78tag [^\0\n>]+
79
80/* Zero or more instances of backslash-newline. Following GCC, allow
81 white space between the backslash and the newline. */
82splice (\\[ \f\t\v]*\n)*
83
7685e2f7 84/* C style identifier. Must start with letter. Will be used for
d5e8574b
AR
85 named symbol references. Shall be kept synchronized with
86 scan-gram.l "letter" and "id". */
7685e2f7
AR
87letter [-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
88id {letter}({letter}|[0-9])*
89ref -?[0-9]+|{id}|"["{id}"]"|"$"
90
e9071366
AD
91%%
92
93%{
2346344a 94 /* Nesting level of the current code in braces. */
4f82b42a 95 int braces_level = 0;
2346344a 96
42f4393a
DJ
97 /* Whether a semicolon is probably needed.
98 The heuristic is that a semicolon is not needed after `{', `}', `;',
99 or a C preprocessor directive, and that whitespaces and comments
100 do not affect this flag.
101 Note that `{' does not need a semicolon because of `{}'.
102 A semicolon may be needed before a cpp direcive, but don't bother. */
103 bool need_semicolon = false;
104
105 /* Whether in a C preprocessor directive. Don't use a start condition
106 for this because, at the end of strings and comments, we still need
107 to know whether we're in a directive. */
108 bool in_cpp = false;
109
e9071366
AD
110 /* This scanner is special: it is invoked only once, henceforth
111 is expected to return only once. This initialization is
112 therefore done once per action to translate. */
4f82b42a
PE
113 aver (sc_context == SC_SYMBOL_ACTION
114 || sc_context == SC_RULE_ACTION
115 || sc_context == INITIAL);
e9071366
AD
116 BEGIN sc_context;
117%}
118
119 /*------------------------------------------------------------.
120 | Scanning a C comment. The initial `/ *' is already eaten. |
121 `------------------------------------------------------------*/
122
123<SC_COMMENT>
124{
125 "*"{splice}"/" STRING_GROW; BEGIN sc_context;
126}
127
128
129 /*--------------------------------------------------------------.
130 | Scanning a line comment. The initial `//' is already eaten. |
131 `--------------------------------------------------------------*/
132
133<SC_LINE_COMMENT>
134{
135 "\n" STRING_GROW; BEGIN sc_context;
136 {splice} STRING_GROW;
137}
138
139
140 /*--------------------------------------------.
141 | Scanning user-code characters and strings. |
142 `--------------------------------------------*/
143
144<SC_CHARACTER,SC_STRING>
145{
146 {splice}|\\{splice}. STRING_GROW;
147}
148
149<SC_CHARACTER>
150{
151 "'" STRING_GROW; BEGIN sc_context;
152}
153
154<SC_STRING>
155{
156 "\"" STRING_GROW; BEGIN sc_context;
157}
158
159
160<SC_RULE_ACTION,SC_SYMBOL_ACTION>{
161 "'" {
162 STRING_GROW;
163 BEGIN SC_CHARACTER;
42f4393a 164 need_semicolon = true;
e9071366
AD
165 }
166 "\"" {
167 STRING_GROW;
168 BEGIN SC_STRING;
42f4393a 169 need_semicolon = true;
e9071366
AD
170 }
171 "/"{splice}"*" {
172 STRING_GROW;
173 BEGIN SC_COMMENT;
174 }
175 "/"{splice}"/" {
176 STRING_GROW;
177 BEGIN SC_LINE_COMMENT;
178 }
179}
180
181<SC_RULE_ACTION>
182{
7685e2f7
AR
183 "$"("<"{tag}">")?{ref} {
184 ref_tail_fields = 0;
28e52c0d 185 handle_action_dollar (self->rule, yytext, *loc);
d5e8574b 186 if (ref_tail_fields) {
7685e2f7
AR
187 obstack_sgrow (&obstack_for_string, ref_tail_fields);
188 }
42f4393a 189 need_semicolon = true;
28e52c0d 190 }
7685e2f7
AR
191 "@"{ref} {
192 ref_tail_fields = 0;
28e52c0d 193 handle_action_at (self->rule, yytext, *loc);
d5e8574b 194 if (ref_tail_fields) {
7685e2f7
AR
195 obstack_sgrow (&obstack_for_string, ref_tail_fields);
196 }
42f4393a 197 need_semicolon = true;
28e52c0d 198 }
e9071366
AD
199 "$" {
200 warn_at (*loc, _("stray `$'"));
201 obstack_sgrow (&obstack_for_string, "$][");
42f4393a 202 need_semicolon = true;
e9071366
AD
203 }
204 "@" {
205 warn_at (*loc, _("stray `@'"));
206 obstack_sgrow (&obstack_for_string, "@@");
42f4393a
DJ
207 need_semicolon = true;
208 }
209 "[" {
210 obstack_sgrow (&obstack_for_string, "@{");
211 need_semicolon = true;
212 }
213 "]" {
214 obstack_sgrow (&obstack_for_string, "@}");
215 need_semicolon = true;
e9071366 216 }
2346344a 217
42f4393a
DJ
218 ";" STRING_GROW; need_semicolon = false;
219 "{" STRING_GROW; ++braces_level; need_semicolon = false;
2346344a 220 "}" {
14da0cdd 221 bool outer_brace = --braces_level == 0;
2346344a
AD
222
223 /* As an undocumented Bison extension, append `;' before the last
224 brace in braced code, so that the user code can omit trailing
225 `;'. But do not append `;' if emulating Yacc, since Yacc does
42f4393a 226 not append one. */
7ed73f82 227 if (outer_brace && !yacc_flag && language_prio == default_prio
42f4393a
DJ
228 && skeleton_prio == default_prio && need_semicolon && ! in_cpp)
229 {
230 warn_at (*loc, _("a `;' might be needed at the end of action code"));
231 warn_at (*loc, _("future versions of Bison will not add the `;'"));
232 obstack_1grow (&obstack_for_string, ';');
233 }
2346344a
AD
234
235 STRING_GROW;
42f4393a 236 need_semicolon = false;
2346344a 237 }
42f4393a
DJ
238
239 /* Preprocessing directives should only be recognized at the beginning
240 of lines, allowing whitespace including comments, but in C/C++,
241 `#' can only be the start of preprocessor directives or within
242 `#define' directives anyway, so don't bother with begin of line. */
243 "#" STRING_GROW; in_cpp = true;
244
245 {splice} STRING_GROW;
246 [\n\r] STRING_GROW; if (in_cpp) in_cpp = need_semicolon = false;
247 [ \t\f] STRING_GROW;
62efdd2a
JD
248
249 /* YYFAIL is undocumented and was formally deprecated in Bison
250 2.4.2. */
251 YYFAIL {
252 STRING_GROW; need_semicolon = true;
253 warn_at (*loc, _("use of YYFAIL, which is deprecated and will be"
254 " removed"));
255 }
256
257 /* The sole purpose of this is to make sure identifiers that merely
258 contain YYFAIL don't produce the above warning. */
259 [A-Za-z_][0-9A-Za-z_]* STRING_GROW; need_semicolon = true;
260
261 . STRING_GROW; need_semicolon = true;
e9071366
AD
262}
263
264<SC_SYMBOL_ACTION>
265{
28e52c0d
JD
266 "$$" {
267 obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
268 self->is_value_used = true;
269 }
e785ccf7
JD
270 "@$" {
271 obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
272 locations_flag = true;
273 }
e9071366
AD
274}
275
276
277 /*-----------------------------------------.
278 | Escape M4 quoting characters in C code. |
279 `-----------------------------------------*/
280
281<*>
282{
283 \$ obstack_sgrow (&obstack_for_string, "$][");
284 \@ obstack_sgrow (&obstack_for_string, "@@");
285 \[ obstack_sgrow (&obstack_for_string, "@{");
286 \] obstack_sgrow (&obstack_for_string, "@}");
287}
288
289 /*-----------------------------------------------------.
290 | By default, grow the string obstack with the input. |
291 `-----------------------------------------------------*/
292
293<*>.|\n STRING_GROW;
294
295 /* End of processing. */
296<*><<EOF>> {
28e52c0d
JD
297 STRING_FINISH;
298 return last_string;
e9071366
AD
299 }
300
301%%
302
7685e2f7 303static inline bool
d5e8574b 304is_dot_or_dash (char ch)
7685e2f7
AR
305{
306 return ch == '.' || ch == '-';
307}
308
309static inline bool
d5e8574b 310contains_dot_or_dash (const char* p)
7685e2f7 311{
d5e8574b
AR
312 for (; *p; ++p)
313 if (is_dot_or_dash (*p))
314 return true;
315 return false;
7685e2f7
AR
316}
317
d5e8574b 318/* Defines a variant of a symbolic name resolution. */
7685e2f7
AR
319typedef struct
320{
321 /* Index in symbol list. */
1a323c2f 322 unsigned symbol_index;
7685e2f7
AR
323
324 /* Matched symbol id and loc. */
325 uniqstr id;
326 location loc;
327
d5e8574b 328 /* Hiding named reference. */
7685e2f7
AR
329 named_ref* hidden_by;
330
d5e8574b
AR
331 /* Error flags. May contain zero (no errors) or
332 a combination of VARIANT_* values. */
7685e2f7
AR
333 unsigned err;
334} variant;
335
d5e8574b
AR
336/* Set when the variant refers to a symbol hidden
337 by an explicit symbol reference. */
338#define VARIANT_HIDDEN (1 << 0)
339
340/* Set when the variant refers to a symbol containing
341 dots or dashes. Will require explicit bracketing. */
342#define VARIANT_BAD_BRACKETING (1 << 1)
343
344/* Set when the variant refers to a symbol which is
345 not visible from current midrule. */
346#define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2)
347
7685e2f7
AR
348static variant *variant_table = 0;
349static unsigned variant_table_size = 0;
350static unsigned variant_count = 0;
351
352static variant *
992e874a 353variant_table_grow (void)
7685e2f7
AR
354{
355 ++variant_count;
356 if (variant_count > variant_table_size)
357 {
358 while (variant_count > variant_table_size)
359 variant_table_size = 2 * variant_table_size + 3;
360 variant_table = xnrealloc (variant_table, variant_table_size,
361 sizeof *variant_table);
362 }
363 return &variant_table[variant_count - 1];
364}
365
1e20ad11 366static void
992e874a 367variant_table_free (void)
1e20ad11 368{
992e874a 369 free (variant_table);
1e20ad11
AR
370 variant_table = 0;
371 variant_table_size = variant_count = 0;
372}
373
7685e2f7 374static char *
d5e8574b 375find_prefix_end (const char *prefix, char *begin, char *end)
7685e2f7
AR
376{
377 char *ptr = begin;
378
d5e8574b
AR
379 for (; *prefix && ptr != end; ++prefix, ++ptr)
380 if (*prefix != *ptr)
381 return 0;
7685e2f7
AR
382
383 if (*prefix)
384 return 0;
385
386 return ptr;
387}
388
389static variant *
992e874a 390variant_add (uniqstr id, location id_loc, unsigned symbol_index,
14e568d7 391 char *cp, char *cp_end, bool explicit_bracketing)
7685e2f7
AR
392{
393 char *prefix_end;
394
d5e8574b 395 prefix_end = find_prefix_end (id, cp, cp_end);
7685e2f7
AR
396 if (prefix_end &&
397 (prefix_end == cp_end ||
14e568d7 398 (!explicit_bracketing && is_dot_or_dash (*prefix_end))))
7685e2f7 399 {
d5e8574b 400 variant *r = variant_table_grow ();
1a323c2f 401 r->symbol_index = symbol_index;
7685e2f7 402 r->id = id;
992e874a 403 r->loc = id_loc;
7685e2f7
AR
404 r->hidden_by = NULL;
405 r->err = 0;
406 return r;
407 }
408 else
409 return NULL;
410}
411
d5e8574b 412static const char *
992e874a 413get_at_spec(unsigned symbol_index)
d5e8574b
AR
414{
415 static char at_buf[20];
992e874a 416 if (symbol_index == 0)
d5e8574b
AR
417 strcpy (at_buf, "$$");
418 else
992e874a 419 snprintf (at_buf, sizeof at_buf, "$%u", symbol_index);
d5e8574b
AR
420 return at_buf;
421}
422
1a323c2f 423static void
14e568d7 424show_sub_messages (const char* cp, bool explicit_bracketing,
348f5608
AR
425 int midrule_rhs_index, char dollar_or_at,
426 bool is_warning, unsigned indent)
1a323c2f
AR
427{
428 unsigned i;
429
430 for (i = 0; i < variant_count; ++i)
431 {
432 const variant *var = &variant_table[i];
433 const char *at_spec = get_at_spec (var->symbol_index);
434
435 if (var->err == 0)
436 {
437 if (is_warning)
348f5608
AR
438 warn_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
439 dollar_or_at, var->id, at_spec);
1a323c2f 440 else
348f5608
AR
441 complain_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
442 dollar_or_at, var->id, at_spec);
1a323c2f
AR
443 }
444 else
445 {
446 static struct obstack msg_buf;
14e568d7 447 const char *tail = explicit_bracketing ? "" :
1a323c2f
AR
448 cp + strlen (var->id);
449 const char *id = var->hidden_by ? var->hidden_by->id :
450 var->id;
451 location id_loc = var->hidden_by ? var->hidden_by->loc :
452 var->loc;
453
454 /* Create the explanation message. */
455 obstack_init (&msg_buf);
456
348f5608 457 obstack_fgrow1 (&msg_buf, _("possibly meant: %c"), dollar_or_at);
1a323c2f
AR
458 if (contains_dot_or_dash (id))
459 obstack_fgrow1 (&msg_buf, "[%s]", id);
460 else
461 obstack_sgrow (&msg_buf, id);
462 obstack_sgrow (&msg_buf, tail);
463
464 if (var->err & VARIANT_HIDDEN)
465 {
348f5608 466 obstack_fgrow1 (&msg_buf, _(", hiding %c"), dollar_or_at);
1a323c2f
AR
467 if (contains_dot_or_dash (var->id))
468 obstack_fgrow1 (&msg_buf, "[%s]", var->id);
469 else
470 obstack_sgrow (&msg_buf, var->id);
471 obstack_sgrow (&msg_buf, tail);
472 }
473
348f5608 474 obstack_fgrow1 (&msg_buf, _(" at %s"), at_spec);
1a323c2f
AR
475
476 if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
348f5608
AR
477 {
478 const char *format =
479 _(", cannot be accessed from mid-rule action at $%d");
480 obstack_fgrow1 (&msg_buf, format, midrule_rhs_index);
481 }
1a323c2f
AR
482
483 obstack_1grow (&msg_buf, '\0');
484 if (is_warning)
348f5608
AR
485 warn_at_indent (id_loc, &indent, "%s",
486 (char *) obstack_finish (&msg_buf));
1a323c2f 487 else
348f5608
AR
488 complain_at_indent (id_loc, &indent, "%s",
489 (char *) obstack_finish (&msg_buf));
1a323c2f
AR
490 obstack_free (&msg_buf, 0);
491 }
492 }
493}
494
d5e8574b
AR
495/* Returned from "parse_ref" when the reference
496 is inappropriate. */
7685e2f7 497#define INVALID_REF (INT_MIN)
d5e8574b
AR
498
499/* Returned from "parse_ref" when the reference
1a323c2f 500 points to LHS ($$) of the current rule or midrule. */
7685e2f7
AR
501#define LHS_REF (INT_MIN + 1)
502
348f5608
AR
503/* Sub-messages indent. */
504#define SUB_INDENT (4)
505
d5e8574b
AR
506/* Parse named or positional reference. In case of positional
507 references, can return negative values for $-n "deep" stack
508 accesses. */
7685e2f7 509static long int
d5e8574b 510parse_ref (char *cp, symbol_list *rule, int rule_length,
992e874a 511 int midrule_rhs_index, char *text, location text_loc,
d5e8574b 512 char dollar_or_at)
7685e2f7
AR
513{
514 symbol_list *l;
515 char *cp_end;
14e568d7 516 bool explicit_bracketing;
d5e8574b 517 unsigned i;
1a323c2f
AR
518 unsigned valid_variants = 0;
519 unsigned valid_variant_index = 0;
7685e2f7
AR
520
521 if ('$' == *cp)
522 return LHS_REF;
523
d5e8574b 524 if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1))))
7685e2f7
AR
525 {
526 long int num = strtol (cp, &cp, 10);
527 if (1 - INT_MAX + rule_length <= num && num <= rule_length)
528 return num;
529 else
530 {
992e874a
AR
531 complain_at (text_loc, _("integer out of range: %s"),
532 quote (text));
7685e2f7
AR
533 return INVALID_REF;
534 }
535 }
536
537 if ('[' == *cp)
538 {
7685e2f7 539 /* Ignore the brackets. */
d5e8574b
AR
540 char *p;
541 for (p = ++cp; *p != ']'; ++p)
542 continue;
7685e2f7 543 cp_end = p;
d5e8574b 544
14e568d7 545 explicit_bracketing = true;
7685e2f7
AR
546 }
547 else
548 {
7685e2f7 549 /* Take all characters of the name. */
d5e8574b 550 char* p;
7685e2f7 551 for (p = cp; *p; ++p)
d5e8574b 552 if (is_dot_or_dash (*p))
7685e2f7
AR
553 {
554 ref_tail_fields = p;
555 break;
556 }
d5e8574b
AR
557 for (p = cp; *p; ++p)
558 continue;
7685e2f7 559 cp_end = p;
d5e8574b 560
14e568d7 561 explicit_bracketing = false;
7685e2f7
AR
562 }
563
564 /* Add all relevant variants. */
d5e8574b 565 {
992e874a 566 unsigned symbol_index;
d5e8574b 567 variant_count = 0;
992e874a
AR
568 for (symbol_index = 0, l = rule; !symbol_list_null (l);
569 ++symbol_index, l = l->next)
d5e8574b 570 {
992e874a 571 variant *var;
d5e8574b
AR
572 if (l->content_type != SYMLIST_SYMBOL)
573 continue;
7685e2f7 574
992e874a 575 var = variant_add (l->content.sym->tag, l->sym_loc,
14e568d7 576 symbol_index, cp, cp_end, explicit_bracketing);
992e874a
AR
577 if (var && l->named_ref)
578 var->hidden_by = l->named_ref;
7685e2f7 579
d5e8574b 580 if (l->named_ref)
992e874a 581 variant_add (l->named_ref->id, l->named_ref->loc,
14e568d7 582 symbol_index, cp, cp_end, explicit_bracketing);
d5e8574b
AR
583 }
584 }
7685e2f7
AR
585
586 /* Check errors. */
7685e2f7
AR
587 for (i = 0; i < variant_count; ++i)
588 {
992e874a 589 variant *var = &variant_table[i];
1a323c2f 590 unsigned symbol_index = var->symbol_index;
7685e2f7
AR
591
592 /* Check visibility from mid-rule actions. */
d5e8574b 593 if (midrule_rhs_index != 0
992e874a 594 && (symbol_index == 0 || midrule_rhs_index < symbol_index))
1a323c2f 595 var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
7685e2f7
AR
596
597 /* Check correct bracketing. */
14e568d7 598 if (!explicit_bracketing && contains_dot_or_dash (var->id))
1a323c2f 599 var->err |= VARIANT_BAD_BRACKETING;
7685e2f7
AR
600
601 /* Check using of hidden symbols. */
992e874a 602 if (var->hidden_by)
1a323c2f 603 var->err |= VARIANT_HIDDEN;
7685e2f7 604
992e874a 605 if (!var->err)
1a323c2f
AR
606 {
607 valid_variant_index = i;
608 ++valid_variants;
609 }
7685e2f7
AR
610 }
611
1a323c2f 612 switch (valid_variants)
7685e2f7 613 {
1a323c2f 614 case 0:
4c56b131
AR
615 {
616 unsigned len = (explicit_bracketing || !ref_tail_fields) ?
617 cp_end - cp : ref_tail_fields - cp;
348f5608 618 unsigned indent = 0;
4c56b131 619
348f5608
AR
620 complain_at_indent (text_loc, &indent, _("invalid reference: %s"),
621 quote (text));
622 indent += SUB_INDENT;
4c56b131 623 if (midrule_rhs_index)
348f5608
AR
624 {
625 const char *format =
626 _("symbol not found in production before $%d: %.*s");
627 complain_at_indent (rule->location, &indent, format,
628 midrule_rhs_index, len, cp);
629 }
4c56b131 630 else
348f5608
AR
631 {
632 const char *format =
633 _("symbol not found in production: %.*s");
634 complain_at_indent (rule->location, &indent, format,
635 len, cp);
636 }
4c56b131
AR
637
638 if (variant_count > 0)
14e568d7 639 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
348f5608 640 dollar_or_at, false, indent);
4c56b131
AR
641 return INVALID_REF;
642 }
1a323c2f
AR
643 case 1:
644 {
348f5608 645 unsigned indent = 0;
1a323c2f
AR
646 if (variant_count > 1)
647 {
348f5608
AR
648 warn_at_indent (text_loc, &indent, _("misleading reference: %s"),
649 quote (text));
14e568d7 650 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
348f5608 651 dollar_or_at, true, indent + SUB_INDENT);
1a323c2f
AR
652 }
653 {
654 unsigned symbol_index =
655 variant_table[valid_variant_index].symbol_index;
656 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
657 }
658 }
659 case 2:
660 default:
348f5608
AR
661 {
662 unsigned indent = 0;
663 complain_at_indent (text_loc, &indent, _("ambiguous reference: %s"),
664 quote (text));
665 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
666 dollar_or_at, false, indent + SUB_INDENT);
667 return INVALID_REF;
668 }
7685e2f7
AR
669 }
670
1a323c2f 671 /* Not reachable. */
7685e2f7
AR
672 return INVALID_REF;
673}
674
e9071366
AD
675/* Keeps track of the maximum number of semantic values to the left of
676 a handle (those referenced by $0, $-1, etc.) are required by the
677 semantic actions of this grammar. */
678int max_left_semantic_context = 0;
679
680
681/*------------------------------------------------------------------.
682| TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
683| |
684| Possible inputs: $[<TYPENAME>]($|integer) |
685| |
686| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
687`------------------------------------------------------------------*/
688
689static void
4210cd0b 690handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 691{
28e52c0d 692 char const *type_name = NULL;
e9071366 693 char *cp = text + 1;
7685e2f7 694 char *gt_ptr = 0;
ffa4ba3a 695 symbol_list *effective_rule;
d5e8574b
AR
696 int effective_rule_length;
697 int n;
ffa4ba3a
JD
698
699 if (rule->midrule_parent_rule)
700 {
701 effective_rule = rule->midrule_parent_rule;
702 effective_rule_length = rule->midrule_parent_rhs_index - 1;
703 }
704 else
705 {
706 effective_rule = rule;
707 effective_rule_length = symbol_list_length (rule->next);
708 }
e9071366
AD
709
710 /* Get the type name if explicit. */
711 if (*cp == '<')
712 {
713 type_name = ++cp;
714 while (*cp != '>')
715 ++cp;
7685e2f7
AR
716
717 /* The '>' symbol will be later replaced by '\0'. Original
718 'text' is needed for error messages. */
719 gt_ptr = cp;
e9071366 720 ++cp;
ddc8ede1
PE
721 if (untyped_var_seen)
722 complain_at (dollar_loc, _("explicit type given in untyped grammar"));
723 tag_seen = true;
e9071366
AD
724 }
725
d5e8574b
AR
726 n = parse_ref (cp, effective_rule, effective_rule_length,
727 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
7685e2f7
AR
728
729 if (gt_ptr)
730 *gt_ptr = '\0';
731
732 switch (n)
e9071366 733 {
7685e2f7
AR
734 case INVALID_REF:
735 break;
736
737 case LHS_REF:
e9071366 738 if (!type_name)
4210cd0b 739 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
740
741 if (!type_name)
ad6b1efa 742 {
ddc8ede1
PE
743 if (union_seen | tag_seen)
744 {
745 if (rule->midrule_parent_rule)
746 complain_at (dollar_loc,
747 _("$$ for the midrule at $%d of `%s'"
748 " has no declared type"),
749 rule->midrule_parent_rhs_index,
3be03b13 750 effective_rule->content.sym->tag);
ddc8ede1
PE
751 else
752 complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
3be03b13 753 rule->content.sym->tag);
ddc8ede1 754 }
ad6b1efa 755 else
ddc8ede1
PE
756 untyped_var_seen = true;
757 type_name = "";
ad6b1efa 758 }
ddc8ede1 759
e9071366
AD
760 obstack_fgrow1 (&obstack_for_string,
761 "]b4_lhs_value([%s])[", type_name);
f6857bbf 762 rule->action_props.is_value_used = true;
7685e2f7
AR
763 break;
764
765 default:
766 if (max_left_semantic_context < 1 - n)
767 max_left_semantic_context = 1 - n;
768 if (!type_name && 0 < n)
769 type_name =
770 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
771 if (!type_name)
e9071366 772 {
7685e2f7
AR
773 if (union_seen | tag_seen)
774 complain_at (dollar_loc, _("$%s of `%s' has no declared type"),
775 cp, effective_rule->content.sym->tag);
776 else
777 untyped_var_seen = true;
778 type_name = "";
e9071366 779 }
7685e2f7
AR
780
781 obstack_fgrow3 (&obstack_for_string,
782 "]b4_rhs_value(%d, %d, [%s])[",
783 effective_rule_length, n, type_name);
784 if (n > 0)
785 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
786 true;
787 break;
e9071366
AD
788 }
789}
790
791
792/*------------------------------------------------------.
793| TEXT is a location token (i.e., a `@...'). Output to |
794| OBSTACK_FOR_STRING a reference to this location. |
795`------------------------------------------------------*/
796
797static void
4210cd0b 798handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366
AD
799{
800 char *cp = text + 1;
7685e2f7 801 symbol_list *effective_rule;
d5e8574b
AR
802 int effective_rule_length;
803 int n;
7685e2f7
AR
804
805 if (rule->midrule_parent_rule)
806 {
807 effective_rule = rule->midrule_parent_rule;
808 effective_rule_length = rule->midrule_parent_rhs_index - 1;
809 }
810 else
811 {
812 effective_rule = rule;
813 effective_rule_length = symbol_list_length (rule->next);
814 }
ffa4ba3a 815
4f82b42a 816 locations_flag = true;
e9071366 817
d5e8574b 818 n = parse_ref (cp, effective_rule, effective_rule_length,
7685e2f7
AR
819 rule->midrule_parent_rhs_index, text, at_loc, '@');
820 switch (n)
e9071366 821 {
7685e2f7
AR
822 case INVALID_REF:
823 break;
e9071366 824
7685e2f7
AR
825 case LHS_REF:
826 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
827 break;
828
829 default:
830 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
831 effective_rule_length, n);
832 break;
e9071366
AD
833 }
834}
835
836
837/*-------------------------.
838| Initialize the scanner. |
839`-------------------------*/
840
28e52c0d 841/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 842 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 843
eb095650 844static char const *
28e52c0d 845translate_action (code_props *self, int sc_context)
e9071366 846{
2ce4ed68 847 char *res;
e9071366
AD
848 static bool initialized = false;
849 if (!initialized)
850 {
851 obstack_init (&obstack_for_string);
e9071366
AD
852 yy_flex_debug = 0;
853 initialized = true;
854 }
855
28e52c0d
JD
856 loc->start = loc->end = self->location.start;
857 yy_switch_to_buffer (yy_scan_string (self->code));
858 res = code_lex (self, sc_context);
e9071366
AD
859 yy_delete_buffer (YY_CURRENT_BUFFER);
860
861 return res;
862}
863
28e52c0d
JD
864/*------------------------------------------------------------------------.
865| Implementation of the public interface as documented in "scan-code.h". |
866`------------------------------------------------------------------------*/
867
868void
869code_props_none_init (code_props *self)
76290368 870{
28e52c0d 871 *self = code_props_none;
76290368
JD
872}
873
28e52c0d
JD
874code_props const code_props_none = CODE_PROPS_NONE_INIT;
875
876void
d5e8574b
AR
877code_props_plain_init (code_props *self, char const *code,
878 location code_loc)
76290368 879{
28e52c0d
JD
880 self->kind = CODE_PROPS_PLAIN;
881 self->code = code;
882 self->location = code_loc;
883 self->is_value_used = false;
884 self->rule = NULL;
7685e2f7 885 self->named_ref = NULL;
76290368
JD
886}
887
28e52c0d
JD
888void
889code_props_symbol_action_init (code_props *self, char const *code,
890 location code_loc)
e9071366 891{
28e52c0d
JD
892 self->kind = CODE_PROPS_SYMBOL_ACTION;
893 self->code = code;
894 self->location = code_loc;
895 self->is_value_used = false;
896 self->rule = NULL;
7685e2f7 897 self->named_ref = NULL;
e9071366
AD
898}
899
28e52c0d
JD
900void
901code_props_rule_action_init (code_props *self, char const *code,
7685e2f7 902 location code_loc, symbol_list *rule,
992e874a 903 named_ref *name)
28e52c0d
JD
904{
905 self->kind = CODE_PROPS_RULE_ACTION;
906 self->code = code;
907 self->location = code_loc;
908 self->is_value_used = false;
909 self->rule = rule;
992e874a 910 self->named_ref = name;
28e52c0d
JD
911}
912
913void
914code_props_translate_code (code_props *self)
915{
916 switch (self->kind)
917 {
918 case CODE_PROPS_NONE:
919 break;
920 case CODE_PROPS_PLAIN:
921 self->code = translate_action (self, INITIAL);
922 break;
923 case CODE_PROPS_SYMBOL_ACTION:
924 self->code = translate_action (self, SC_SYMBOL_ACTION);
925 break;
926 case CODE_PROPS_RULE_ACTION:
927 self->code = translate_action (self, SC_RULE_ACTION);
928 break;
929 }
930}
931
932void
933code_scanner_last_string_free (void)
934{
935 STRING_FREE;
936}
e9071366
AD
937
938void
939code_scanner_free (void)
940{
941 obstack_free (&obstack_for_string, 0);
1e20ad11
AR
942 variant_table_free ();
943
e9071366 944 /* Reclaim Flex's buffers. */
580b8926 945 yylex_destroy ();
e9071366 946}