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