]> git.saurik.com Git - bison.git/blame - src/scan-code.l
yysyntax_error: test memory management more.
[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;
248 . STRING_GROW; need_semicolon = true;
e9071366
AD
249}
250
251<SC_SYMBOL_ACTION>
252{
28e52c0d
JD
253 "$$" {
254 obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
255 self->is_value_used = true;
256 }
e785ccf7
JD
257 "@$" {
258 obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
259 locations_flag = true;
260 }
e9071366
AD
261}
262
263
264 /*-----------------------------------------.
265 | Escape M4 quoting characters in C code. |
266 `-----------------------------------------*/
267
268<*>
269{
270 \$ obstack_sgrow (&obstack_for_string, "$][");
271 \@ obstack_sgrow (&obstack_for_string, "@@");
272 \[ obstack_sgrow (&obstack_for_string, "@{");
273 \] obstack_sgrow (&obstack_for_string, "@}");
274}
275
276 /*-----------------------------------------------------.
277 | By default, grow the string obstack with the input. |
278 `-----------------------------------------------------*/
279
280<*>.|\n STRING_GROW;
281
282 /* End of processing. */
283<*><<EOF>> {
28e52c0d
JD
284 STRING_FINISH;
285 return last_string;
e9071366
AD
286 }
287
288%%
289
7685e2f7 290static inline bool
d5e8574b 291is_dot_or_dash (char ch)
7685e2f7
AR
292{
293 return ch == '.' || ch == '-';
294}
295
296static inline bool
d5e8574b 297contains_dot_or_dash (const char* p)
7685e2f7 298{
d5e8574b
AR
299 for (; *p; ++p)
300 if (is_dot_or_dash (*p))
301 return true;
302 return false;
7685e2f7
AR
303}
304
d5e8574b 305/* Defines a variant of a symbolic name resolution. */
7685e2f7
AR
306typedef struct
307{
308 /* Index in symbol list. */
1a323c2f 309 unsigned symbol_index;
7685e2f7
AR
310
311 /* Matched symbol id and loc. */
312 uniqstr id;
313 location loc;
314
d5e8574b 315 /* Hiding named reference. */
7685e2f7
AR
316 named_ref* hidden_by;
317
d5e8574b
AR
318 /* Error flags. May contain zero (no errors) or
319 a combination of VARIANT_* values. */
7685e2f7
AR
320 unsigned err;
321} variant;
322
d5e8574b
AR
323/* Set when the variant refers to a symbol hidden
324 by an explicit symbol reference. */
325#define VARIANT_HIDDEN (1 << 0)
326
327/* Set when the variant refers to a symbol containing
328 dots or dashes. Will require explicit bracketing. */
329#define VARIANT_BAD_BRACKETING (1 << 1)
330
331/* Set when the variant refers to a symbol which is
332 not visible from current midrule. */
333#define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2)
334
7685e2f7
AR
335static variant *variant_table = 0;
336static unsigned variant_table_size = 0;
337static unsigned variant_count = 0;
338
339static variant *
992e874a 340variant_table_grow (void)
7685e2f7
AR
341{
342 ++variant_count;
343 if (variant_count > variant_table_size)
344 {
345 while (variant_count > variant_table_size)
346 variant_table_size = 2 * variant_table_size + 3;
347 variant_table = xnrealloc (variant_table, variant_table_size,
348 sizeof *variant_table);
349 }
350 return &variant_table[variant_count - 1];
351}
352
1e20ad11 353static void
992e874a 354variant_table_free (void)
1e20ad11 355{
992e874a 356 free (variant_table);
1e20ad11
AR
357 variant_table = 0;
358 variant_table_size = variant_count = 0;
359}
360
7685e2f7 361static char *
d5e8574b 362find_prefix_end (const char *prefix, char *begin, char *end)
7685e2f7
AR
363{
364 char *ptr = begin;
365
d5e8574b
AR
366 for (; *prefix && ptr != end; ++prefix, ++ptr)
367 if (*prefix != *ptr)
368 return 0;
7685e2f7
AR
369
370 if (*prefix)
371 return 0;
372
373 return ptr;
374}
375
376static variant *
992e874a 377variant_add (uniqstr id, location id_loc, unsigned symbol_index,
14e568d7 378 char *cp, char *cp_end, bool explicit_bracketing)
7685e2f7
AR
379{
380 char *prefix_end;
381
d5e8574b 382 prefix_end = find_prefix_end (id, cp, cp_end);
7685e2f7
AR
383 if (prefix_end &&
384 (prefix_end == cp_end ||
14e568d7 385 (!explicit_bracketing && is_dot_or_dash (*prefix_end))))
7685e2f7 386 {
d5e8574b 387 variant *r = variant_table_grow ();
1a323c2f 388 r->symbol_index = symbol_index;
7685e2f7 389 r->id = id;
992e874a 390 r->loc = id_loc;
7685e2f7
AR
391 r->hidden_by = NULL;
392 r->err = 0;
393 return r;
394 }
395 else
396 return NULL;
397}
398
d5e8574b 399static const char *
992e874a 400get_at_spec(unsigned symbol_index)
d5e8574b
AR
401{
402 static char at_buf[20];
992e874a 403 if (symbol_index == 0)
d5e8574b
AR
404 strcpy (at_buf, "$$");
405 else
992e874a 406 snprintf (at_buf, sizeof at_buf, "$%u", symbol_index);
d5e8574b
AR
407 return at_buf;
408}
409
1a323c2f 410static void
14e568d7 411show_sub_messages (const char* cp, bool explicit_bracketing,
348f5608
AR
412 int midrule_rhs_index, char dollar_or_at,
413 bool is_warning, unsigned indent)
1a323c2f
AR
414{
415 unsigned i;
416
417 for (i = 0; i < variant_count; ++i)
418 {
419 const variant *var = &variant_table[i];
420 const char *at_spec = get_at_spec (var->symbol_index);
421
422 if (var->err == 0)
423 {
424 if (is_warning)
348f5608
AR
425 warn_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
426 dollar_or_at, var->id, at_spec);
1a323c2f 427 else
348f5608
AR
428 complain_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
429 dollar_or_at, var->id, at_spec);
1a323c2f
AR
430 }
431 else
432 {
433 static struct obstack msg_buf;
14e568d7 434 const char *tail = explicit_bracketing ? "" :
1a323c2f
AR
435 cp + strlen (var->id);
436 const char *id = var->hidden_by ? var->hidden_by->id :
437 var->id;
438 location id_loc = var->hidden_by ? var->hidden_by->loc :
439 var->loc;
440
441 /* Create the explanation message. */
442 obstack_init (&msg_buf);
443
348f5608 444 obstack_fgrow1 (&msg_buf, _("possibly meant: %c"), dollar_or_at);
1a323c2f
AR
445 if (contains_dot_or_dash (id))
446 obstack_fgrow1 (&msg_buf, "[%s]", id);
447 else
448 obstack_sgrow (&msg_buf, id);
449 obstack_sgrow (&msg_buf, tail);
450
451 if (var->err & VARIANT_HIDDEN)
452 {
348f5608 453 obstack_fgrow1 (&msg_buf, _(", hiding %c"), dollar_or_at);
1a323c2f
AR
454 if (contains_dot_or_dash (var->id))
455 obstack_fgrow1 (&msg_buf, "[%s]", var->id);
456 else
457 obstack_sgrow (&msg_buf, var->id);
458 obstack_sgrow (&msg_buf, tail);
459 }
460
348f5608 461 obstack_fgrow1 (&msg_buf, _(" at %s"), at_spec);
1a323c2f
AR
462
463 if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
348f5608
AR
464 {
465 const char *format =
466 _(", cannot be accessed from mid-rule action at $%d");
467 obstack_fgrow1 (&msg_buf, format, midrule_rhs_index);
468 }
1a323c2f
AR
469
470 obstack_1grow (&msg_buf, '\0');
471 if (is_warning)
348f5608
AR
472 warn_at_indent (id_loc, &indent, "%s",
473 (char *) obstack_finish (&msg_buf));
1a323c2f 474 else
348f5608
AR
475 complain_at_indent (id_loc, &indent, "%s",
476 (char *) obstack_finish (&msg_buf));
1a323c2f
AR
477 obstack_free (&msg_buf, 0);
478 }
479 }
480}
481
d5e8574b
AR
482/* Returned from "parse_ref" when the reference
483 is inappropriate. */
7685e2f7 484#define INVALID_REF (INT_MIN)
d5e8574b
AR
485
486/* Returned from "parse_ref" when the reference
1a323c2f 487 points to LHS ($$) of the current rule or midrule. */
7685e2f7
AR
488#define LHS_REF (INT_MIN + 1)
489
348f5608
AR
490/* Sub-messages indent. */
491#define SUB_INDENT (4)
492
d5e8574b
AR
493/* Parse named or positional reference. In case of positional
494 references, can return negative values for $-n "deep" stack
495 accesses. */
7685e2f7 496static long int
d5e8574b 497parse_ref (char *cp, symbol_list *rule, int rule_length,
992e874a 498 int midrule_rhs_index, char *text, location text_loc,
d5e8574b 499 char dollar_or_at)
7685e2f7
AR
500{
501 symbol_list *l;
502 char *cp_end;
14e568d7 503 bool explicit_bracketing;
d5e8574b 504 unsigned i;
1a323c2f
AR
505 unsigned valid_variants = 0;
506 unsigned valid_variant_index = 0;
7685e2f7
AR
507
508 if ('$' == *cp)
509 return LHS_REF;
510
d5e8574b 511 if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1))))
7685e2f7
AR
512 {
513 long int num = strtol (cp, &cp, 10);
514 if (1 - INT_MAX + rule_length <= num && num <= rule_length)
515 return num;
516 else
517 {
992e874a
AR
518 complain_at (text_loc, _("integer out of range: %s"),
519 quote (text));
7685e2f7
AR
520 return INVALID_REF;
521 }
522 }
523
524 if ('[' == *cp)
525 {
7685e2f7 526 /* Ignore the brackets. */
d5e8574b
AR
527 char *p;
528 for (p = ++cp; *p != ']'; ++p)
529 continue;
7685e2f7 530 cp_end = p;
d5e8574b 531
14e568d7 532 explicit_bracketing = true;
7685e2f7
AR
533 }
534 else
535 {
7685e2f7 536 /* Take all characters of the name. */
d5e8574b 537 char* p;
7685e2f7 538 for (p = cp; *p; ++p)
d5e8574b 539 if (is_dot_or_dash (*p))
7685e2f7
AR
540 {
541 ref_tail_fields = p;
542 break;
543 }
d5e8574b
AR
544 for (p = cp; *p; ++p)
545 continue;
7685e2f7 546 cp_end = p;
d5e8574b 547
14e568d7 548 explicit_bracketing = false;
7685e2f7
AR
549 }
550
551 /* Add all relevant variants. */
d5e8574b 552 {
992e874a 553 unsigned symbol_index;
d5e8574b 554 variant_count = 0;
992e874a
AR
555 for (symbol_index = 0, l = rule; !symbol_list_null (l);
556 ++symbol_index, l = l->next)
d5e8574b 557 {
992e874a 558 variant *var;
d5e8574b
AR
559 if (l->content_type != SYMLIST_SYMBOL)
560 continue;
7685e2f7 561
992e874a 562 var = variant_add (l->content.sym->tag, l->sym_loc,
14e568d7 563 symbol_index, cp, cp_end, explicit_bracketing);
992e874a
AR
564 if (var && l->named_ref)
565 var->hidden_by = l->named_ref;
7685e2f7 566
d5e8574b 567 if (l->named_ref)
992e874a 568 variant_add (l->named_ref->id, l->named_ref->loc,
14e568d7 569 symbol_index, cp, cp_end, explicit_bracketing);
d5e8574b
AR
570 }
571 }
7685e2f7
AR
572
573 /* Check errors. */
7685e2f7
AR
574 for (i = 0; i < variant_count; ++i)
575 {
992e874a 576 variant *var = &variant_table[i];
1a323c2f 577 unsigned symbol_index = var->symbol_index;
7685e2f7
AR
578
579 /* Check visibility from mid-rule actions. */
d5e8574b 580 if (midrule_rhs_index != 0
992e874a 581 && (symbol_index == 0 || midrule_rhs_index < symbol_index))
1a323c2f 582 var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
7685e2f7
AR
583
584 /* Check correct bracketing. */
14e568d7 585 if (!explicit_bracketing && contains_dot_or_dash (var->id))
1a323c2f 586 var->err |= VARIANT_BAD_BRACKETING;
7685e2f7
AR
587
588 /* Check using of hidden symbols. */
992e874a 589 if (var->hidden_by)
1a323c2f 590 var->err |= VARIANT_HIDDEN;
7685e2f7 591
992e874a 592 if (!var->err)
1a323c2f
AR
593 {
594 valid_variant_index = i;
595 ++valid_variants;
596 }
7685e2f7
AR
597 }
598
1a323c2f 599 switch (valid_variants)
7685e2f7 600 {
1a323c2f 601 case 0:
4c56b131
AR
602 {
603 unsigned len = (explicit_bracketing || !ref_tail_fields) ?
604 cp_end - cp : ref_tail_fields - cp;
348f5608 605 unsigned indent = 0;
4c56b131 606
348f5608
AR
607 complain_at_indent (text_loc, &indent, _("invalid reference: %s"),
608 quote (text));
609 indent += SUB_INDENT;
4c56b131 610 if (midrule_rhs_index)
348f5608
AR
611 {
612 const char *format =
613 _("symbol not found in production before $%d: %.*s");
614 complain_at_indent (rule->location, &indent, format,
615 midrule_rhs_index, len, cp);
616 }
4c56b131 617 else
348f5608
AR
618 {
619 const char *format =
620 _("symbol not found in production: %.*s");
621 complain_at_indent (rule->location, &indent, format,
622 len, cp);
623 }
4c56b131
AR
624
625 if (variant_count > 0)
14e568d7 626 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
348f5608 627 dollar_or_at, false, indent);
4c56b131
AR
628 return INVALID_REF;
629 }
1a323c2f
AR
630 case 1:
631 {
348f5608 632 unsigned indent = 0;
1a323c2f
AR
633 if (variant_count > 1)
634 {
348f5608
AR
635 warn_at_indent (text_loc, &indent, _("misleading reference: %s"),
636 quote (text));
14e568d7 637 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
348f5608 638 dollar_or_at, true, indent + SUB_INDENT);
1a323c2f
AR
639 }
640 {
641 unsigned symbol_index =
642 variant_table[valid_variant_index].symbol_index;
643 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
644 }
645 }
646 case 2:
647 default:
348f5608
AR
648 {
649 unsigned indent = 0;
650 complain_at_indent (text_loc, &indent, _("ambiguous reference: %s"),
651 quote (text));
652 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
653 dollar_or_at, false, indent + SUB_INDENT);
654 return INVALID_REF;
655 }
7685e2f7
AR
656 }
657
1a323c2f 658 /* Not reachable. */
7685e2f7
AR
659 return INVALID_REF;
660}
661
e9071366
AD
662/* Keeps track of the maximum number of semantic values to the left of
663 a handle (those referenced by $0, $-1, etc.) are required by the
664 semantic actions of this grammar. */
665int max_left_semantic_context = 0;
666
667
668/*------------------------------------------------------------------.
669| TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
670| |
671| Possible inputs: $[<TYPENAME>]($|integer) |
672| |
673| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
674`------------------------------------------------------------------*/
675
676static void
4210cd0b 677handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 678{
28e52c0d 679 char const *type_name = NULL;
e9071366 680 char *cp = text + 1;
7685e2f7 681 char *gt_ptr = 0;
ffa4ba3a 682 symbol_list *effective_rule;
d5e8574b
AR
683 int effective_rule_length;
684 int n;
ffa4ba3a
JD
685
686 if (rule->midrule_parent_rule)
687 {
688 effective_rule = rule->midrule_parent_rule;
689 effective_rule_length = rule->midrule_parent_rhs_index - 1;
690 }
691 else
692 {
693 effective_rule = rule;
694 effective_rule_length = symbol_list_length (rule->next);
695 }
e9071366
AD
696
697 /* Get the type name if explicit. */
698 if (*cp == '<')
699 {
700 type_name = ++cp;
701 while (*cp != '>')
702 ++cp;
7685e2f7
AR
703
704 /* The '>' symbol will be later replaced by '\0'. Original
705 'text' is needed for error messages. */
706 gt_ptr = cp;
e9071366 707 ++cp;
ddc8ede1
PE
708 if (untyped_var_seen)
709 complain_at (dollar_loc, _("explicit type given in untyped grammar"));
710 tag_seen = true;
e9071366
AD
711 }
712
d5e8574b
AR
713 n = parse_ref (cp, effective_rule, effective_rule_length,
714 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
7685e2f7
AR
715
716 if (gt_ptr)
717 *gt_ptr = '\0';
718
719 switch (n)
e9071366 720 {
7685e2f7
AR
721 case INVALID_REF:
722 break;
723
724 case LHS_REF:
e9071366 725 if (!type_name)
4210cd0b 726 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
727
728 if (!type_name)
ad6b1efa 729 {
ddc8ede1
PE
730 if (union_seen | tag_seen)
731 {
732 if (rule->midrule_parent_rule)
733 complain_at (dollar_loc,
734 _("$$ for the midrule at $%d of `%s'"
735 " has no declared type"),
736 rule->midrule_parent_rhs_index,
3be03b13 737 effective_rule->content.sym->tag);
ddc8ede1
PE
738 else
739 complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
3be03b13 740 rule->content.sym->tag);
ddc8ede1 741 }
ad6b1efa 742 else
ddc8ede1
PE
743 untyped_var_seen = true;
744 type_name = "";
ad6b1efa 745 }
ddc8ede1 746
e9071366
AD
747 obstack_fgrow1 (&obstack_for_string,
748 "]b4_lhs_value([%s])[", type_name);
f6857bbf 749 rule->action_props.is_value_used = true;
7685e2f7
AR
750 break;
751
752 default:
753 if (max_left_semantic_context < 1 - n)
754 max_left_semantic_context = 1 - n;
755 if (!type_name && 0 < n)
756 type_name =
757 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
758 if (!type_name)
e9071366 759 {
7685e2f7
AR
760 if (union_seen | tag_seen)
761 complain_at (dollar_loc, _("$%s of `%s' has no declared type"),
762 cp, effective_rule->content.sym->tag);
763 else
764 untyped_var_seen = true;
765 type_name = "";
e9071366 766 }
7685e2f7
AR
767
768 obstack_fgrow3 (&obstack_for_string,
769 "]b4_rhs_value(%d, %d, [%s])[",
770 effective_rule_length, n, type_name);
771 if (n > 0)
772 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
773 true;
774 break;
e9071366
AD
775 }
776}
777
778
779/*------------------------------------------------------.
780| TEXT is a location token (i.e., a `@...'). Output to |
781| OBSTACK_FOR_STRING a reference to this location. |
782`------------------------------------------------------*/
783
784static void
4210cd0b 785handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366
AD
786{
787 char *cp = text + 1;
7685e2f7 788 symbol_list *effective_rule;
d5e8574b
AR
789 int effective_rule_length;
790 int n;
7685e2f7
AR
791
792 if (rule->midrule_parent_rule)
793 {
794 effective_rule = rule->midrule_parent_rule;
795 effective_rule_length = rule->midrule_parent_rhs_index - 1;
796 }
797 else
798 {
799 effective_rule = rule;
800 effective_rule_length = symbol_list_length (rule->next);
801 }
ffa4ba3a 802
4f82b42a 803 locations_flag = true;
e9071366 804
d5e8574b 805 n = parse_ref (cp, effective_rule, effective_rule_length,
7685e2f7
AR
806 rule->midrule_parent_rhs_index, text, at_loc, '@');
807 switch (n)
e9071366 808 {
7685e2f7
AR
809 case INVALID_REF:
810 break;
e9071366 811
7685e2f7
AR
812 case LHS_REF:
813 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
814 break;
815
816 default:
817 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
818 effective_rule_length, n);
819 break;
e9071366
AD
820 }
821}
822
823
824/*-------------------------.
825| Initialize the scanner. |
826`-------------------------*/
827
28e52c0d 828/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 829 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 830
eb095650 831static char const *
28e52c0d 832translate_action (code_props *self, int sc_context)
e9071366 833{
2ce4ed68 834 char *res;
e9071366
AD
835 static bool initialized = false;
836 if (!initialized)
837 {
838 obstack_init (&obstack_for_string);
e9071366
AD
839 yy_flex_debug = 0;
840 initialized = true;
841 }
842
28e52c0d
JD
843 loc->start = loc->end = self->location.start;
844 yy_switch_to_buffer (yy_scan_string (self->code));
845 res = code_lex (self, sc_context);
e9071366
AD
846 yy_delete_buffer (YY_CURRENT_BUFFER);
847
848 return res;
849}
850
28e52c0d
JD
851/*------------------------------------------------------------------------.
852| Implementation of the public interface as documented in "scan-code.h". |
853`------------------------------------------------------------------------*/
854
855void
856code_props_none_init (code_props *self)
76290368 857{
28e52c0d 858 *self = code_props_none;
76290368
JD
859}
860
28e52c0d
JD
861code_props const code_props_none = CODE_PROPS_NONE_INIT;
862
863void
d5e8574b
AR
864code_props_plain_init (code_props *self, char const *code,
865 location code_loc)
76290368 866{
28e52c0d
JD
867 self->kind = CODE_PROPS_PLAIN;
868 self->code = code;
869 self->location = code_loc;
870 self->is_value_used = false;
871 self->rule = NULL;
7685e2f7 872 self->named_ref = NULL;
76290368
JD
873}
874
28e52c0d
JD
875void
876code_props_symbol_action_init (code_props *self, char const *code,
877 location code_loc)
e9071366 878{
28e52c0d
JD
879 self->kind = CODE_PROPS_SYMBOL_ACTION;
880 self->code = code;
881 self->location = code_loc;
882 self->is_value_used = false;
883 self->rule = NULL;
7685e2f7 884 self->named_ref = NULL;
e9071366
AD
885}
886
28e52c0d
JD
887void
888code_props_rule_action_init (code_props *self, char const *code,
7685e2f7 889 location code_loc, symbol_list *rule,
992e874a 890 named_ref *name)
28e52c0d
JD
891{
892 self->kind = CODE_PROPS_RULE_ACTION;
893 self->code = code;
894 self->location = code_loc;
895 self->is_value_used = false;
896 self->rule = rule;
992e874a 897 self->named_ref = name;
28e52c0d
JD
898}
899
900void
901code_props_translate_code (code_props *self)
902{
903 switch (self->kind)
904 {
905 case CODE_PROPS_NONE:
906 break;
907 case CODE_PROPS_PLAIN:
908 self->code = translate_action (self, INITIAL);
909 break;
910 case CODE_PROPS_SYMBOL_ACTION:
911 self->code = translate_action (self, SC_SYMBOL_ACTION);
912 break;
913 case CODE_PROPS_RULE_ACTION:
914 self->code = translate_action (self, SC_RULE_ACTION);
915 break;
916 }
917}
918
919void
920code_scanner_last_string_free (void)
921{
922 STRING_FREE;
923}
e9071366
AD
924
925void
926code_scanner_free (void)
927{
928 obstack_free (&obstack_for_string, 0);
1e20ad11
AR
929 variant_table_free ();
930
e9071366 931 /* Reclaim Flex's buffers. */
580b8926 932 yylex_destroy ();
e9071366 933}