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