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