]> git.saurik.com Git - bison.git/blame - src/scan-code.l
maint: minor simplification
[bison.git] / src / scan-code.l
CommitLineData
e9071366
AD
1/* Bison Action Scanner -*- C -*-
2
34136e65 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
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
676997e5 50static void handle_action_dollar (symbol_list *rule, char *cp,
e9690142 51 location dollar_loc);
676997e5
JD
52static void handle_action_at (symbol_list *rule, char *cp, location at_loc);
53
54/* A string to be pushed to obstack after dollar/at has been handled. */
55static char *ref_tail_fields;
b9f1d9a4 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. */
e9690142 79tag [^\0\n>]+
e9071366
AD
80
81/* Zero or more instances of backslash-newline. Following GCC, allow
82 white space between the backslash and the newline. */
e9690142 83splice (\\[ \f\t\v]*\n)*
e9071366 84
676997e5
JD
85/* C style identifier. Must start with letter. Will be used for
86 named symbol references. Shall be kept synchronized with
87 scan-gram.l "letter" and "id". */
e9690142
JD
88letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
89id {letter}({letter}|[-0-9])*
676997e5 90ref -?[0-9]+|{id}|"["{id}"]"|"$"
b9f1d9a4 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 98 /* Whether a semicolon is probably needed.
ae93e4e4 99 The heuristic is that a semicolon is not needed after '{', '}', ';',
e8cd1ad6
DJ
100 or a C preprocessor directive, and that whitespaces and comments
101 do not affect this flag.
ae93e4e4 102 Note that '{' does not need a semicolon because of '{}'.
e8cd1ad6
DJ
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 114 aver (sc_context == SC_SYMBOL_ACTION
e9690142
JD
115 || sc_context == SC_RULE_ACTION
116 || sc_context == INITIAL);
e9071366
AD
117 BEGIN sc_context;
118%}
119
120 /*------------------------------------------------------------.
ae93e4e4 121 | Scanning a C comment. The initial '/ *' is already eaten. |
e9071366
AD
122 `------------------------------------------------------------*/
123
124<SC_COMMENT>
125{
126 "*"{splice}"/" STRING_GROW; BEGIN sc_context;
127}
128
129
130 /*--------------------------------------------------------------.
ae93e4e4 131 | Scanning a line comment. The initial '//' is already eaten. |
e9071366
AD
132 `--------------------------------------------------------------*/
133
134<SC_LINE_COMMENT>
135{
e9690142
JD
136 "\n" STRING_GROW; BEGIN sc_context;
137 {splice} STRING_GROW;
e9071366
AD
138}
139
140
141 /*--------------------------------------------.
142 | Scanning user-code characters and strings. |
143 `--------------------------------------------*/
144
145<SC_CHARACTER,SC_STRING>
146{
e9690142 147 {splice}|\\{splice}. STRING_GROW;
e9071366
AD
148}
149
150<SC_CHARACTER>
151{
e9690142 152 "'" STRING_GROW; BEGIN sc_context;
e9071366
AD
153}
154
155<SC_STRING>
156{
e9690142 157 "\"" STRING_GROW; BEGIN sc_context;
e9071366
AD
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 184 "$"("<"{tag}">")?{ref} {
676997e5
JD
185 ref_tail_fields = 0;
186 handle_action_dollar (self->rule, yytext, *loc);
187 if (ref_tail_fields) {
188 obstack_sgrow (&obstack_for_string, ref_tail_fields);
189 }
e8cd1ad6 190 need_semicolon = true;
28e52c0d 191 }
b9f1d9a4 192 "@"{ref} {
676997e5
JD
193 ref_tail_fields = 0;
194 handle_action_at (self->rule, yytext, *loc);
195 if (ref_tail_fields) {
196 obstack_sgrow (&obstack_for_string, ref_tail_fields);
197 }
e8cd1ad6 198 need_semicolon = true;
28e52c0d 199 }
e9071366 200 "$" {
ae93e4e4 201 warn_at (*loc, _("stray '$'"));
e9071366 202 obstack_sgrow (&obstack_for_string, "$][");
e8cd1ad6 203 need_semicolon = true;
e9071366
AD
204 }
205 "@" {
ae93e4e4 206 warn_at (*loc, _("stray '@'"));
e9071366 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 223
ae93e4e4 224 /* As an undocumented Bison extension, append ';' before the last
2346344a 225 brace in braced code, so that the user code can omit trailing
ae93e4e4 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 {
ae93e4e4
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 ';'"));
e9690142 233 obstack_1grow (&obstack_for_string, ';');
e8cd1ad6 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++,
ae93e4e4
JM
242 '#' can only be the start of preprocessor directives or within
243 '#define' directives anyway, so don't bother with begin of line. */
e8cd1ad6
DJ
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{
e9690142
JD
284 \$ obstack_sgrow (&obstack_for_string, "$][");
285 \@ obstack_sgrow (&obstack_for_string, "@@");
286 \[ obstack_sgrow (&obstack_for_string, "@{");
287 \] obstack_sgrow (&obstack_for_string, "@}");
e9071366
AD
288}
289
290 /*-----------------------------------------------------.
291 | By default, grow the string obstack with the input. |
292 `-----------------------------------------------------*/
293
e9690142 294<*>.|\n STRING_GROW;
e9071366
AD
295
296 /* End of processing. */
e9690142 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
676997e5
JD
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
872b52bc
AR
345/* Set when the variant refers to a symbol which is
346 not visible from current midrule. */
676997e5 347#define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2)
872b52bc 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)
e9690142 360 variant_table_size = 2 * variant_table_size + 3;
b9f1d9a4 361 variant_table = xnrealloc (variant_table, variant_table_size,
e9690142 362 sizeof *variant_table);
b9f1d9a4
AR
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
676997e5
JD
375static char *
376find_prefix_end (const char *prefix, char *begin, char *end)
b9f1d9a4 377{
676997e5
JD
378 char *ptr = begin;
379
380 for (; *prefix && ptr != end; ++prefix, ++ptr)
381 if (*prefix != *ptr)
382 return 0;
383
384 if (*prefix)
385 return 0;
386
387 return ptr;
b9f1d9a4
AR
388}
389
390static variant *
ba4184ec 391variant_add (uniqstr id, location id_loc, unsigned symbol_index,
e9690142 392 char *cp, char *cp_end, bool explicit_bracketing)
b9f1d9a4 393{
676997e5
JD
394 char *prefix_end;
395
396 prefix_end = find_prefix_end (id, cp, cp_end);
397 if (prefix_end &&
398 (prefix_end == cp_end ||
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
676997e5
JD
425show_sub_messages (const char* cp, bool explicit_bracketing,
426 int midrule_rhs_index, char dollar_or_at,
66381412 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
e9690142
JD
446 {
447 static struct obstack msg_buf;
448 const char *tail = explicit_bracketing ? "" :
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
458 obstack_fgrow1 (&msg_buf, _("possibly meant: %c"), dollar_or_at);
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 {
467 obstack_fgrow1 (&msg_buf, _(", hiding %c"), dollar_or_at);
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
475 obstack_fgrow1 (&msg_buf, _(" at %s"), at_spec);
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 483
e9690142 484 obstack_1grow (&msg_buf, '\0');
ce268795 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));
e9690142
JD
491 obstack_free (&msg_buf, 0);
492 }
ce268795
AR
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
676997e5
JD
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
676997e5 511parse_ref (char *cp, symbol_list *rule, int rule_length,
e9690142
JD
512 int midrule_rhs_index, char *text, location text_loc,
513 char dollar_or_at)
b9f1d9a4 514{
676997e5
JD
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
676997e5 525 if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1))))
b9f1d9a4 526 {
676997e5 527 long int num = strtol (cp, &cp, 10);
b9f1d9a4 528 if (1 - INT_MAX + rule_length <= num && num <= rule_length)
e9690142 529 return num;
b9f1d9a4 530 else
e9690142
JD
531 {
532 complain_at (text_loc, _("integer out of range: %s"),
ba4184ec 533 quote (text));
e9690142
JD
534 return INVALID_REF;
535 }
b9f1d9a4
AR
536 }
537
676997e5
JD
538 if ('[' == *cp)
539 {
540 /* Ignore the brackets. */
541 char *p;
542 for (p = ++cp; *p != ']'; ++p)
e9690142 543 continue;
676997e5
JD
544 cp_end = p;
545
546 explicit_bracketing = true;
547 }
548 else
549 {
550 /* Take all characters of the name. */
551 char* p;
552 for (p = cp; *p; ++p)
e9690142
JD
553 if (is_dot_or_dash (*p))
554 {
555 ref_tail_fields = p;
556 break;
557 }
676997e5 558 for (p = cp; *p; ++p)
e9690142 559 continue;
676997e5
JD
560 cp_end = p;
561
562 explicit_bracketing = false;
563 }
b9f1d9a4
AR
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 {
e9690142
JD
572 variant *var;
573 if (l->content_type != SYMLIST_SYMBOL)
574 continue;
b9f1d9a4 575
e9690142 576 var = variant_add (l->content.sym->tag, l->sym_loc,
676997e5 577 symbol_index, cp, cp_end, explicit_bracketing);
e9690142
JD
578 if (var && l->named_ref)
579 var->hidden_by = l->named_ref;
b9f1d9a4 580
e9690142
JD
581 if (l->named_ref)
582 variant_add (l->named_ref->id, l->named_ref->loc,
676997e5 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
e9690142 595 && (symbol_index == 0 || midrule_rhs_index < symbol_index))
ce268795 596 var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
b9f1d9a4 597
676997e5
JD
598 /* Check correct bracketing. */
599 if (!explicit_bracketing && contains_dot_or_dash (var->id))
600 var->err |= VARIANT_BAD_BRACKETING;
601
b9f1d9a4 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 616 {
676997e5
JD
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;
5c9efc75
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 =
ae93e4e4
JM
630 _("syntax error after '%c', expecting integer, letter,"
631 " '_', '[', or '$'");
676997e5 632 complain_at_indent (sym_loc, &indent, format, dollar_or_at);
5c9efc75
JD
633 }
634 else if (midrule_rhs_index)
66381412
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 }
f64e406b 641 else
66381412
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 }
f64e406b
AR
648
649 if (variant_count > 0)
676997e5
JD
650 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
651 dollar_or_at, false, indent);
f64e406b
AR
652 return INVALID_REF;
653 }
ce268795
AR
654 case 1:
655 {
66381412 656 unsigned indent = 0;
ce268795
AR
657 if (variant_count > 1)
658 {
66381412
AR
659 warn_at_indent (text_loc, &indent, _("misleading reference: %s"),
660 quote (text));
676997e5
JD
661 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
662 dollar_or_at, true, indent + SUB_INDENT);
ce268795
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:
66381412
AR
672 {
673 unsigned indent = 0;
674 complain_at_indent (text_loc, &indent, _("ambiguous reference: %s"),
675 quote (text));
676997e5
JD
676 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
677 dollar_or_at, false, indent + SUB_INDENT);
66381412
AR
678 return INVALID_REF;
679 }
b9f1d9a4
AR
680 }
681
ce268795 682 /* Not reachable. */
b9f1d9a4
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
692/*------------------------------------------------------------------.
ae93e4e4 693| TEXT is pointing to a wannabee semantic value (i.e., a '$'). |
e9071366 694| |
676997e5 695| Possible inputs: $[<TYPENAME>]($|integer) |
e9071366
AD
696| |
697| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
698`------------------------------------------------------------------*/
699
700static void
676997e5 701handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 702{
28e52c0d 703 char const *type_name = NULL;
e9071366 704 char *cp = text + 1;
b9f1d9a4 705 char *gt_ptr = 0;
ffa4ba3a 706 symbol_list *effective_rule;
872b52bc
AR
707 int effective_rule_length;
708 int n;
ffa4ba3a
JD
709
710 if (rule->midrule_parent_rule)
711 {
712 effective_rule = rule->midrule_parent_rule;
713 effective_rule_length = rule->midrule_parent_rhs_index - 1;
714 }
715 else
716 {
717 effective_rule = rule;
718 effective_rule_length = symbol_list_length (rule->next);
719 }
e9071366
AD
720
721 /* Get the type name if explicit. */
722 if (*cp == '<')
723 {
724 type_name = ++cp;
725 while (*cp != '>')
e9690142 726 ++cp;
b9f1d9a4
AR
727
728 /* The '>' symbol will be later replaced by '\0'. Original
e9690142 729 'text' is needed for error messages. */
b9f1d9a4 730 gt_ptr = cp;
e9071366 731 ++cp;
ddc8ede1 732 if (untyped_var_seen)
e9690142 733 complain_at (dollar_loc, _("explicit type given in untyped grammar"));
ddc8ede1 734 tag_seen = true;
e9071366
AD
735 }
736
872b52bc 737 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 738 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
b9f1d9a4
AR
739
740 if (gt_ptr)
741 *gt_ptr = '\0';
742
743 switch (n)
e9071366 744 {
b9f1d9a4
AR
745 case INVALID_REF:
746 break;
747
748 case LHS_REF:
e9071366 749 if (!type_name)
e9690142 750 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
751
752 if (!type_name)
e9690142
JD
753 {
754 if (union_seen | tag_seen)
755 {
756 if (rule->midrule_parent_rule)
757 complain_at (dollar_loc,
4a9cd8f2 758 _("$$ for the midrule at $%d of %s"
e9690142
JD
759 " has no declared type"),
760 rule->midrule_parent_rhs_index,
4a9cd8f2 761 quote (effective_rule->content.sym->tag));
e9690142 762 else
4a9cd8f2
AD
763 complain_at (dollar_loc, _("$$ of %s has no declared type"),
764 quote (rule->content.sym->tag));
e9690142
JD
765 }
766 else
767 untyped_var_seen = true;
768 type_name = "";
769 }
ddc8ede1 770
e9071366 771 obstack_fgrow1 (&obstack_for_string,
e9690142 772 "]b4_lhs_value([%s])[", type_name);
f6857bbf 773 rule->action_props.is_value_used = true;
b9f1d9a4
AR
774 break;
775
776 default:
777 if (max_left_semantic_context < 1 - n)
e9690142 778 max_left_semantic_context = 1 - n;
b9f1d9a4 779 if (!type_name && 0 < n)
e9690142
JD
780 type_name =
781 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
b9f1d9a4 782 if (!type_name)
e9690142
JD
783 {
784 if (union_seen | tag_seen)
4a9cd8f2
AD
785 complain_at (dollar_loc, _("$%s of %s has no declared type"),
786 cp, quote (effective_rule->content.sym->tag));
e9690142
JD
787 else
788 untyped_var_seen = true;
789 type_name = "";
790 }
b9f1d9a4
AR
791
792 obstack_fgrow3 (&obstack_for_string,
e9690142
JD
793 "]b4_rhs_value(%d, %d, [%s])[",
794 effective_rule_length, n, type_name);
b9f1d9a4 795 if (n > 0)
e9690142
JD
796 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
797 true;
b9f1d9a4 798 break;
e9071366
AD
799 }
800}
801
802
803/*------------------------------------------------------.
ae93e4e4 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
676997e5 809handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366 810{
676997e5
JD
811 char *cp = text + 1;
812 symbol_list *effective_rule;
872b52bc
AR
813 int effective_rule_length;
814 int n;
b9f1d9a4
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
bc0f5737 827 muscle_percent_define_ensure("locations", at_loc, true);
e9071366 828
872b52bc 829 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 830 rule->midrule_parent_rhs_index, text, at_loc, '@');
b9f1d9a4 831 switch (n)
e9071366 832 {
b9f1d9a4
AR
833 case INVALID_REF:
834 break;
e9071366 835
b9f1d9a4
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)[",
e9690142 842 effective_rule_length, n);
b9f1d9a4 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
872b52bc 888code_props_plain_init (code_props *self, char const *code,
e9690142 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;
b9f1d9a4 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;
b9f1d9a4 908 self->named_ref = NULL;
e9071366
AD
909}
910
28e52c0d
JD
911void
912code_props_rule_action_init (code_props *self, char const *code,
b9f1d9a4 913 location code_loc, symbol_list *rule,
e9690142 914 named_ref *name, bool is_predicate)
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;
ba4184ec 921 self->named_ref = name;
ca2a6d15 922 self->is_predicate = is_predicate;
28e52c0d
JD
923}
924
925void
926code_props_translate_code (code_props *self)
927{
928 switch (self->kind)
929 {
930 case CODE_PROPS_NONE:
931 break;
932 case CODE_PROPS_PLAIN:
933 self->code = translate_action (self, INITIAL);
934 break;
935 case CODE_PROPS_SYMBOL_ACTION:
936 self->code = translate_action (self, SC_SYMBOL_ACTION);
937 break;
938 case CODE_PROPS_RULE_ACTION:
939 self->code = translate_action (self, SC_RULE_ACTION);
940 break;
941 }
942}
943
944void
945code_scanner_last_string_free (void)
946{
947 STRING_FREE;
948}
e9071366
AD
949
950void
951code_scanner_free (void)
952{
953 obstack_free (&obstack_for_string, 0);
13cdf208
AR
954 variant_table_free ();
955
e9071366 956 /* Reclaim Flex's buffers. */
580b8926 957 yylex_destroy ();
e9071366 958}