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