]> git.saurik.com Git - bison.git/blame - src/scan-code.l
maint: s/strncpy/memcpy/, when equivalent
[bison.git] / src / scan-code.l
CommitLineData
e9071366
AD
1/* Bison Action Scanner -*- C -*-
2
c932d613 3 Copyright (C) 2006-2012 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". */
d236ad94 87letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
eb8c66bb 88id {letter}({letter}|[-0-9])*
7685e2f7
AR
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 97 /* Whether a semicolon is probably needed.
9874f80b 98 The heuristic is that a semicolon is not needed after '{', '}', ';',
42f4393a
DJ
99 or a C preprocessor directive, and that whitespaces and comments
100 do not affect this flag.
9874f80b 101 Note that '{' does not need a semicolon because of '{}'.
42f4393a
DJ
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 /*------------------------------------------------------------.
9874f80b 120 | Scanning a C comment. The initial '/ *' is already eaten. |
e9071366
AD
121 `------------------------------------------------------------*/
122
123<SC_COMMENT>
124{
125 "*"{splice}"/" STRING_GROW; BEGIN sc_context;
126}
127
128
129 /*--------------------------------------------------------------.
9874f80b 130 | Scanning a line comment. The initial '//' is already eaten. |
e9071366
AD
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 199 "$" {
9874f80b 200 warn_at (*loc, _("stray '$'"));
e9071366 201 obstack_sgrow (&obstack_for_string, "$][");
42f4393a 202 need_semicolon = true;
e9071366
AD
203 }
204 "@" {
9874f80b 205 warn_at (*loc, _("stray '@'"));
e9071366 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 222
9874f80b 223 /* As an undocumented Bison extension, append ';' before the last
2346344a 224 brace in braced code, so that the user code can omit trailing
9874f80b 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 {
9874f80b
JM
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, ';');
42f4393a 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++,
9874f80b
JM
241 '#' can only be the start of preprocessor directives or within
242 '#define' directives anyway, so don't bother with begin of line. */
42f4393a
DJ
243 "#" STRING_GROW; in_cpp = true;
244
245 {splice} STRING_GROW;
e6070f22 246 [\n\r] STRING_GROW; if (in_cpp) in_cpp = need_semicolon = false;
42f4393a 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;
8cbbf178
JD
623 if (len == 0)
624 {
625 location sym_loc = text_loc;
626 sym_loc.start.column += 1;
627 sym_loc.end = sym_loc.start;
628 const char *format =
9874f80b
JM
629 _("syntax error after '%c', expecting integer, letter,"
630 " '_', '[', or '$'");
8cbbf178
JD
631 complain_at_indent (sym_loc, &indent, format, dollar_or_at);
632 }
633 else if (midrule_rhs_index)
348f5608
AR
634 {
635 const char *format =
636 _("symbol not found in production before $%d: %.*s");
637 complain_at_indent (rule->location, &indent, format,
638 midrule_rhs_index, len, cp);
639 }
4c56b131 640 else
348f5608
AR
641 {
642 const char *format =
643 _("symbol not found in production: %.*s");
644 complain_at_indent (rule->location, &indent, format,
645 len, cp);
646 }
4c56b131
AR
647
648 if (variant_count > 0)
14e568d7 649 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
348f5608 650 dollar_or_at, false, indent);
4c56b131
AR
651 return INVALID_REF;
652 }
1a323c2f
AR
653 case 1:
654 {
348f5608 655 unsigned indent = 0;
1a323c2f
AR
656 if (variant_count > 1)
657 {
348f5608
AR
658 warn_at_indent (text_loc, &indent, _("misleading reference: %s"),
659 quote (text));
14e568d7 660 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
348f5608 661 dollar_or_at, true, indent + SUB_INDENT);
1a323c2f
AR
662 }
663 {
664 unsigned symbol_index =
665 variant_table[valid_variant_index].symbol_index;
666 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
667 }
668 }
669 case 2:
670 default:
348f5608
AR
671 {
672 unsigned indent = 0;
673 complain_at_indent (text_loc, &indent, _("ambiguous reference: %s"),
674 quote (text));
675 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
676 dollar_or_at, false, indent + SUB_INDENT);
677 return INVALID_REF;
678 }
7685e2f7
AR
679 }
680
1a323c2f 681 /* Not reachable. */
7685e2f7
AR
682 return INVALID_REF;
683}
684
e9071366
AD
685/* Keeps track of the maximum number of semantic values to the left of
686 a handle (those referenced by $0, $-1, etc.) are required by the
687 semantic actions of this grammar. */
688int max_left_semantic_context = 0;
689
690
691/*------------------------------------------------------------------.
9874f80b 692| TEXT is pointing to a wannabee semantic value (i.e., a '$'). |
e9071366
AD
693| |
694| Possible inputs: $[<TYPENAME>]($|integer) |
695| |
696| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
697`------------------------------------------------------------------*/
698
699static void
4210cd0b 700handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 701{
28e52c0d 702 char const *type_name = NULL;
e9071366 703 char *cp = text + 1;
7685e2f7 704 char *gt_ptr = 0;
ffa4ba3a 705 symbol_list *effective_rule;
d5e8574b
AR
706 int effective_rule_length;
707 int n;
ffa4ba3a
JD
708
709 if (rule->midrule_parent_rule)
710 {
711 effective_rule = rule->midrule_parent_rule;
712 effective_rule_length = rule->midrule_parent_rhs_index - 1;
713 }
714 else
715 {
716 effective_rule = rule;
717 effective_rule_length = symbol_list_length (rule->next);
718 }
e9071366
AD
719
720 /* Get the type name if explicit. */
721 if (*cp == '<')
722 {
723 type_name = ++cp;
724 while (*cp != '>')
725 ++cp;
7685e2f7
AR
726
727 /* The '>' symbol will be later replaced by '\0'. Original
728 'text' is needed for error messages. */
729 gt_ptr = cp;
e9071366 730 ++cp;
ddc8ede1
PE
731 if (untyped_var_seen)
732 complain_at (dollar_loc, _("explicit type given in untyped grammar"));
733 tag_seen = true;
e9071366
AD
734 }
735
d5e8574b
AR
736 n = parse_ref (cp, effective_rule, effective_rule_length,
737 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
7685e2f7
AR
738
739 if (gt_ptr)
740 *gt_ptr = '\0';
741
742 switch (n)
e9071366 743 {
7685e2f7
AR
744 case INVALID_REF:
745 break;
746
747 case LHS_REF:
e9071366 748 if (!type_name)
4210cd0b 749 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
750
751 if (!type_name)
9874f80b
JM
752 {
753 if (union_seen | tag_seen)
754 {
755 if (rule->midrule_parent_rule)
756 complain_at (dollar_loc,
4c787a31 757 _("$$ for the midrule at $%d of %s"
9874f80b
JM
758 " has no declared type"),
759 rule->midrule_parent_rhs_index,
4c787a31 760 quote (effective_rule->content.sym->tag));
9874f80b 761 else
4c787a31
AD
762 complain_at (dollar_loc, _("$$ of %s has no declared type"),
763 quote (rule->content.sym->tag));
9874f80b
JM
764 }
765 else
766 untyped_var_seen = true;
767 type_name = "";
768 }
ddc8ede1 769
e9071366
AD
770 obstack_fgrow1 (&obstack_for_string,
771 "]b4_lhs_value([%s])[", type_name);
f6857bbf 772 rule->action_props.is_value_used = true;
7685e2f7
AR
773 break;
774
775 default:
776 if (max_left_semantic_context < 1 - n)
777 max_left_semantic_context = 1 - n;
778 if (!type_name && 0 < n)
779 type_name =
780 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
781 if (!type_name)
9874f80b
JM
782 {
783 if (union_seen | tag_seen)
4c787a31
AD
784 complain_at (dollar_loc, _("$%s of %s has no declared type"),
785 cp, quote (effective_rule->content.sym->tag));
9874f80b
JM
786 else
787 untyped_var_seen = true;
788 type_name = "";
789 }
7685e2f7
AR
790
791 obstack_fgrow3 (&obstack_for_string,
792 "]b4_rhs_value(%d, %d, [%s])[",
793 effective_rule_length, n, type_name);
794 if (n > 0)
795 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
796 true;
797 break;
e9071366
AD
798 }
799}
800
801
802/*------------------------------------------------------.
9874f80b 803| TEXT is a location token (i.e., a '@...'). Output to |
e9071366
AD
804| OBSTACK_FOR_STRING a reference to this location. |
805`------------------------------------------------------*/
806
807static void
4210cd0b 808handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366
AD
809{
810 char *cp = text + 1;
7685e2f7 811 symbol_list *effective_rule;
d5e8574b
AR
812 int effective_rule_length;
813 int n;
7685e2f7
AR
814
815 if (rule->midrule_parent_rule)
816 {
817 effective_rule = rule->midrule_parent_rule;
818 effective_rule_length = rule->midrule_parent_rhs_index - 1;
819 }
820 else
821 {
822 effective_rule = rule;
823 effective_rule_length = symbol_list_length (rule->next);
824 }
ffa4ba3a 825
4f82b42a 826 locations_flag = true;
e9071366 827
d5e8574b 828 n = parse_ref (cp, effective_rule, effective_rule_length,
7685e2f7
AR
829 rule->midrule_parent_rhs_index, text, at_loc, '@');
830 switch (n)
e9071366 831 {
7685e2f7
AR
832 case INVALID_REF:
833 break;
e9071366 834
7685e2f7
AR
835 case LHS_REF:
836 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
837 break;
838
839 default:
840 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
841 effective_rule_length, n);
842 break;
e9071366
AD
843 }
844}
845
846
847/*-------------------------.
848| Initialize the scanner. |
849`-------------------------*/
850
28e52c0d 851/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 852 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 853
eb095650 854static char const *
28e52c0d 855translate_action (code_props *self, int sc_context)
e9071366 856{
2ce4ed68 857 char *res;
e9071366
AD
858 static bool initialized = false;
859 if (!initialized)
860 {
861 obstack_init (&obstack_for_string);
e9071366
AD
862 yy_flex_debug = 0;
863 initialized = true;
864 }
865
28e52c0d
JD
866 loc->start = loc->end = self->location.start;
867 yy_switch_to_buffer (yy_scan_string (self->code));
868 res = code_lex (self, sc_context);
e9071366
AD
869 yy_delete_buffer (YY_CURRENT_BUFFER);
870
871 return res;
872}
873
28e52c0d
JD
874/*------------------------------------------------------------------------.
875| Implementation of the public interface as documented in "scan-code.h". |
876`------------------------------------------------------------------------*/
877
878void
879code_props_none_init (code_props *self)
76290368 880{
28e52c0d 881 *self = code_props_none;
76290368
JD
882}
883
28e52c0d
JD
884code_props const code_props_none = CODE_PROPS_NONE_INIT;
885
886void
d5e8574b
AR
887code_props_plain_init (code_props *self, char const *code,
888 location code_loc)
76290368 889{
28e52c0d
JD
890 self->kind = CODE_PROPS_PLAIN;
891 self->code = code;
892 self->location = code_loc;
893 self->is_value_used = false;
894 self->rule = NULL;
7685e2f7 895 self->named_ref = NULL;
76290368
JD
896}
897
28e52c0d
JD
898void
899code_props_symbol_action_init (code_props *self, char const *code,
900 location code_loc)
e9071366 901{
28e52c0d
JD
902 self->kind = CODE_PROPS_SYMBOL_ACTION;
903 self->code = code;
904 self->location = code_loc;
905 self->is_value_used = false;
906 self->rule = NULL;
7685e2f7 907 self->named_ref = NULL;
e9071366
AD
908}
909
28e52c0d
JD
910void
911code_props_rule_action_init (code_props *self, char const *code,
7685e2f7 912 location code_loc, symbol_list *rule,
992e874a 913 named_ref *name)
28e52c0d
JD
914{
915 self->kind = CODE_PROPS_RULE_ACTION;
916 self->code = code;
917 self->location = code_loc;
918 self->is_value_used = false;
919 self->rule = rule;
992e874a 920 self->named_ref = name;
28e52c0d
JD
921}
922
923void
924code_props_translate_code (code_props *self)
925{
926 switch (self->kind)
927 {
928 case CODE_PROPS_NONE:
929 break;
930 case CODE_PROPS_PLAIN:
931 self->code = translate_action (self, INITIAL);
932 break;
933 case CODE_PROPS_SYMBOL_ACTION:
934 self->code = translate_action (self, SC_SYMBOL_ACTION);
935 break;
936 case CODE_PROPS_RULE_ACTION:
937 self->code = translate_action (self, SC_RULE_ACTION);
938 break;
939 }
940}
941
942void
943code_scanner_last_string_free (void)
944{
945 STRING_FREE;
946}
e9071366
AD
947
948void
949code_scanner_free (void)
950{
951 obstack_free (&obstack_for_string, 0);
1e20ad11
AR
952 variant_table_free ();
953
e9071366 954 /* Reclaim Flex's buffers. */
580b8926 955 yylex_destroy ();
e9071366 956}