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