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