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