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