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