]> git.saurik.com Git - bison.git/blame - src/scan-code.l
obstacks: simplifications
[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 {
6fb8b256
VS
228 complain_at (*loc, Wother,
229 _("a ';' might be needed at the end of action code"));
230 complain_at (*loc, Wother,
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,
c7324354 405 warnings wflags, unsigned indent,
cceb7b94 406 const variant *var)
ce268795 407{
cceb7b94 408 const char *at_spec = get_at_spec (var->symbol_index);
ce268795 409
cceb7b94 410 if (var->err == 0)
c7324354
AD
411 complain_at_indent (var->loc, wflags, &indent,
412 _("refers to: %c%s at %s"), dollar_or_at,
413 var->id, at_spec);
cceb7b94
AD
414 else
415 {
416 static struct obstack msg_buf;
417 const char *tail = explicit_bracketing ? "" : cp + strlen (var->id);
418 const char *id = var->hidden_by ? var->hidden_by->id : var->id;
419 location id_loc = var->hidden_by ? var->hidden_by->loc : var->loc;
ce268795 420
cceb7b94
AD
421 /* Create the explanation message. */
422 obstack_init (&msg_buf);
423
424 obstack_printf (&msg_buf, _("possibly meant: %c"), dollar_or_at);
425 if (contains_dot_or_dash (id))
426 obstack_printf (&msg_buf, "[%s]", id);
ce268795 427 else
cceb7b94
AD
428 obstack_sgrow (&msg_buf, id);
429 obstack_sgrow (&msg_buf, tail);
430
431 if (var->err & VARIANT_HIDDEN)
e9690142 432 {
cceb7b94
AD
433 obstack_printf (&msg_buf, _(", hiding %c"), dollar_or_at);
434 if (contains_dot_or_dash (var->id))
435 obstack_printf (&msg_buf, "[%s]", var->id);
e9690142 436 else
cceb7b94 437 obstack_sgrow (&msg_buf, var->id);
e9690142 438 obstack_sgrow (&msg_buf, tail);
cceb7b94 439 }
e9690142 440
cceb7b94
AD
441 obstack_printf (&msg_buf, _(" at %s"), at_spec);
442
443 if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
c7324354
AD
444 obstack_printf (&msg_buf,
445 _(", cannot be accessed from mid-rule action at $%d"),
446 midrule_rhs_index);
cceb7b94 447
c7324354 448 complain_at_indent (id_loc, wflags, &indent, "%s",
6fbe73b6 449 obstack_finish0 (&msg_buf));
cceb7b94 450 obstack_free (&msg_buf, 0);
ce268795
AR
451 }
452}
453
cceb7b94
AD
454static void
455show_sub_messages (const char* cp, bool explicit_bracketing,
456 int midrule_rhs_index, char dollar_or_at,
c7324354 457 warnings wflags, unsigned indent)
cceb7b94
AD
458{
459 unsigned i;
460
461 for (i = 0; i < variant_count; ++i)
462 show_sub_message (cp, explicit_bracketing,
463 midrule_rhs_index, dollar_or_at,
c7324354 464 wflags, indent, &variant_table[i]);
cceb7b94
AD
465}
466
872b52bc
AR
467/* Returned from "parse_ref" when the reference
468 is inappropriate. */
b9f1d9a4 469#define INVALID_REF (INT_MIN)
872b52bc
AR
470
471/* Returned from "parse_ref" when the reference
ce268795 472 points to LHS ($$) of the current rule or midrule. */
b9f1d9a4
AR
473#define LHS_REF (INT_MIN + 1)
474
66381412
AR
475/* Sub-messages indent. */
476#define SUB_INDENT (4)
477
676997e5
JD
478/* Parse named or positional reference. In case of positional
479 references, can return negative values for $-n "deep" stack
480 accesses. */
b9f1d9a4 481static long int
676997e5 482parse_ref (char *cp, symbol_list *rule, int rule_length,
e9690142
JD
483 int midrule_rhs_index, char *text, location text_loc,
484 char dollar_or_at)
b9f1d9a4 485{
676997e5
JD
486 symbol_list *l;
487 char *cp_end;
61bc57e5 488 bool explicit_bracketing;
872b52bc 489 unsigned i;
ce268795
AR
490 unsigned valid_variants = 0;
491 unsigned valid_variant_index = 0;
b9f1d9a4
AR
492
493 if ('$' == *cp)
494 return LHS_REF;
495
676997e5 496 if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1))))
b9f1d9a4 497 {
676997e5 498 long int num = strtol (cp, &cp, 10);
b9f1d9a4 499 if (1 - INT_MAX + rule_length <= num && num <= rule_length)
e9690142 500 return num;
b9f1d9a4 501 else
e9690142 502 {
6fb8b256 503 complain_at (text_loc, complaint, _("integer out of range: %s"),
ba4184ec 504 quote (text));
e9690142
JD
505 return INVALID_REF;
506 }
b9f1d9a4
AR
507 }
508
676997e5
JD
509 if ('[' == *cp)
510 {
511 /* Ignore the brackets. */
512 char *p;
513 for (p = ++cp; *p != ']'; ++p)
e9690142 514 continue;
676997e5
JD
515 cp_end = p;
516
517 explicit_bracketing = true;
518 }
519 else
520 {
521 /* Take all characters of the name. */
522 char* p;
523 for (p = cp; *p; ++p)
e9690142
JD
524 if (is_dot_or_dash (*p))
525 {
526 ref_tail_fields = p;
527 break;
528 }
676997e5 529 for (p = cp; *p; ++p)
e9690142 530 continue;
676997e5
JD
531 cp_end = p;
532
533 explicit_bracketing = false;
534 }
b9f1d9a4
AR
535
536 /* Add all relevant variants. */
872b52bc 537 {
ba4184ec 538 unsigned symbol_index;
872b52bc 539 variant_count = 0;
ba4184ec
AR
540 for (symbol_index = 0, l = rule; !symbol_list_null (l);
541 ++symbol_index, l = l->next)
872b52bc 542 {
e9690142
JD
543 variant *var;
544 if (l->content_type != SYMLIST_SYMBOL)
545 continue;
b9f1d9a4 546
e9690142 547 var = variant_add (l->content.sym->tag, l->sym_loc,
676997e5 548 symbol_index, cp, cp_end, explicit_bracketing);
e9690142
JD
549 if (var && l->named_ref)
550 var->hidden_by = l->named_ref;
b9f1d9a4 551
e9690142
JD
552 if (l->named_ref)
553 variant_add (l->named_ref->id, l->named_ref->loc,
676997e5 554 symbol_index, cp, cp_end, explicit_bracketing);
872b52bc
AR
555 }
556 }
b9f1d9a4
AR
557
558 /* Check errors. */
b9f1d9a4
AR
559 for (i = 0; i < variant_count; ++i)
560 {
ba4184ec 561 variant *var = &variant_table[i];
ce268795 562 unsigned symbol_index = var->symbol_index;
b9f1d9a4
AR
563
564 /* Check visibility from mid-rule actions. */
872b52bc 565 if (midrule_rhs_index != 0
e9690142 566 && (symbol_index == 0 || midrule_rhs_index < symbol_index))
ce268795 567 var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
b9f1d9a4 568
676997e5
JD
569 /* Check correct bracketing. */
570 if (!explicit_bracketing && contains_dot_or_dash (var->id))
571 var->err |= VARIANT_BAD_BRACKETING;
572
b9f1d9a4 573 /* Check using of hidden symbols. */
ba4184ec 574 if (var->hidden_by)
ce268795 575 var->err |= VARIANT_HIDDEN;
b9f1d9a4 576
ba4184ec 577 if (!var->err)
ce268795
AR
578 {
579 valid_variant_index = i;
580 ++valid_variants;
581 }
b9f1d9a4
AR
582 }
583
ce268795 584 switch (valid_variants)
b9f1d9a4 585 {
ce268795 586 case 0:
f64e406b 587 {
676997e5
JD
588 unsigned len = (explicit_bracketing || !ref_tail_fields) ?
589 cp_end - cp : ref_tail_fields - cp;
66381412 590 unsigned indent = 0;
f64e406b 591
6fb8b256
VS
592 complain_at_indent (text_loc, complaint, &indent,
593 _("invalid reference: %s"), quote (text));
66381412 594 indent += SUB_INDENT;
5c9efc75
JD
595 if (len == 0)
596 {
597 location sym_loc = text_loc;
598 sym_loc.start.column += 1;
599 sym_loc.end = sym_loc.start;
c7324354
AD
600 complain_at_indent (sym_loc, complaint, &indent,
601 _("syntax error after '%c', expecting integer, "
602 "letter, '_', '[', or '$'"),
6fb8b256 603 dollar_or_at);
5c9efc75
JD
604 }
605 else if (midrule_rhs_index)
c7324354
AD
606 complain_at_indent (rule->location, complaint, &indent,
607 _("symbol not found in production before $%d: "
608 "%.*s"),
609 midrule_rhs_index, len, cp);
f64e406b 610 else
c7324354
AD
611 complain_at_indent (rule->location, complaint, &indent,
612 _("symbol not found in production: %.*s"),
613 len, cp);
f64e406b
AR
614
615 if (variant_count > 0)
676997e5 616 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
c7324354 617 dollar_or_at, complaint, indent);
f64e406b
AR
618 return INVALID_REF;
619 }
ce268795
AR
620 case 1:
621 {
66381412 622 unsigned indent = 0;
ce268795
AR
623 if (variant_count > 1)
624 {
6fb8b256
VS
625 complain_at_indent (text_loc, Wother, &indent,
626 _("misleading reference: %s"), quote (text));
676997e5 627 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
c7324354 628 dollar_or_at, Wother, indent + SUB_INDENT);
ce268795
AR
629 }
630 {
631 unsigned symbol_index =
632 variant_table[valid_variant_index].symbol_index;
633 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
634 }
635 }
636 case 2:
637 default:
66381412
AR
638 {
639 unsigned indent = 0;
6fb8b256
VS
640 complain_at_indent (text_loc, complaint, &indent,
641 _("ambiguous reference: %s"), quote (text));
676997e5 642 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
c7324354 643 dollar_or_at, complaint, indent + SUB_INDENT);
66381412
AR
644 return INVALID_REF;
645 }
b9f1d9a4
AR
646 }
647
ce268795 648 /* Not reachable. */
b9f1d9a4
AR
649 return INVALID_REF;
650}
651
e9071366
AD
652/* Keeps track of the maximum number of semantic values to the left of
653 a handle (those referenced by $0, $-1, etc.) are required by the
654 semantic actions of this grammar. */
655int max_left_semantic_context = 0;
656
657
65a99eca
AD
658/* If CP points to a typename (i.e., <.*?>), set TYPE_NAME to its
659 beginning (i.e., after the opening "<", and return the pointer
660 immediately after it. */
661
662static
663char *
664fetch_type_name (char *cp, char const **type_name,
665 location dollar_loc)
666{
667 if (*cp == '<')
668 {
669 *type_name = ++cp;
670 while (*cp != '>')
4323e0da 671 ++cp;
65a99eca
AD
672
673 /* The '>' symbol will be later replaced by '\0'. Original
4323e0da 674 'text' is needed for error messages. */
65a99eca
AD
675 ++cp;
676 if (untyped_var_seen)
4323e0da
AD
677 complain_at (dollar_loc, complaint,
678 _("explicit type given in untyped grammar"));
65a99eca
AD
679 tag_seen = true;
680 }
681 return cp;
682}
683
e9071366 684/*------------------------------------------------------------------.
ae93e4e4 685| TEXT is pointing to a wannabee semantic value (i.e., a '$'). |
e9071366 686| |
676997e5 687| Possible inputs: $[<TYPENAME>]($|integer) |
e9071366
AD
688| |
689| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
690`------------------------------------------------------------------*/
691
692static void
676997e5 693handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 694{
28e52c0d 695 char const *type_name = NULL;
e9071366 696 char *cp = text + 1;
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. */
65a99eca 713 cp = fetch_type_name (cp, &type_name, dollar_loc);
e9071366 714
872b52bc 715 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 716 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
b9f1d9a4 717
65a99eca
AD
718 /* End type_name. */
719 if (type_name)
720 cp[-1] = '\0';
b9f1d9a4
AR
721
722 switch (n)
e9071366 723 {
b9f1d9a4
AR
724 case INVALID_REF:
725 break;
726
727 case LHS_REF:
e9071366 728 if (!type_name)
e9690142 729 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
730
731 if (!type_name)
e9690142
JD
732 {
733 if (union_seen | tag_seen)
734 {
735 if (rule->midrule_parent_rule)
6fb8b256 736 complain_at (dollar_loc, complaint,
4a9cd8f2 737 _("$$ for the midrule at $%d of %s"
e9690142
JD
738 " has no declared type"),
739 rule->midrule_parent_rhs_index,
4a9cd8f2 740 quote (effective_rule->content.sym->tag));
e9690142 741 else
6fb8b256
VS
742 complain_at (dollar_loc, complaint,
743 _("$$ of %s has no declared type"),
4a9cd8f2 744 quote (rule->content.sym->tag));
e9690142
JD
745 }
746 else
747 untyped_var_seen = true;
e9690142 748 }
ddc8ede1 749
8617d87e
AD
750 obstack_sgrow (&obstack_for_string, "]b4_lhs_value(");
751 obstack_quote (&obstack_for_string, type_name);
752 obstack_sgrow (&obstack_for_string, ")[");
f6857bbf 753 rule->action_props.is_value_used = true;
b9f1d9a4
AR
754 break;
755
756 default:
757 if (max_left_semantic_context < 1 - n)
e9690142 758 max_left_semantic_context = 1 - n;
b9f1d9a4 759 if (!type_name && 0 < n)
e9690142
JD
760 type_name =
761 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
b9f1d9a4 762 if (!type_name)
e9690142
JD
763 {
764 if (union_seen | tag_seen)
6fb8b256
VS
765 complain_at (dollar_loc, complaint,
766 _("$%s of %s has no declared type"), cp,
767 quote (effective_rule->content.sym->tag));
e9690142
JD
768 else
769 untyped_var_seen = true;
e9690142 770 }
b9f1d9a4 771
aaf63e45 772 obstack_printf (&obstack_for_string,
4323e0da 773 "]b4_rhs_value(%d, %d, ", effective_rule_length, n);
8617d87e
AD
774 obstack_quote (&obstack_for_string, type_name);
775 obstack_sgrow (&obstack_for_string, ")[");
b9f1d9a4 776 if (n > 0)
e9690142
JD
777 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
778 true;
b9f1d9a4 779 break;
e9071366
AD
780 }
781}
782
783
784/*------------------------------------------------------.
ae93e4e4 785| TEXT is a location token (i.e., a '@...'). Output to |
e9071366
AD
786| OBSTACK_FOR_STRING a reference to this location. |
787`------------------------------------------------------*/
788
789static void
676997e5 790handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366 791{
676997e5
JD
792 char *cp = text + 1;
793 symbol_list *effective_rule;
872b52bc
AR
794 int effective_rule_length;
795 int n;
b9f1d9a4
AR
796
797 if (rule->midrule_parent_rule)
798 {
799 effective_rule = rule->midrule_parent_rule;
800 effective_rule_length = rule->midrule_parent_rhs_index - 1;
801 }
802 else
803 {
804 effective_rule = rule;
805 effective_rule_length = symbol_list_length (rule->next);
806 }
ffa4ba3a 807
bc0f5737 808 muscle_percent_define_ensure("locations", at_loc, true);
e9071366 809
872b52bc 810 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 811 rule->midrule_parent_rhs_index, text, at_loc, '@');
b9f1d9a4 812 switch (n)
e9071366 813 {
b9f1d9a4
AR
814 case INVALID_REF:
815 break;
e9071366 816
b9f1d9a4
AR
817 case LHS_REF:
818 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
819 break;
820
821 default:
aaf63e45 822 obstack_printf (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
e9690142 823 effective_rule_length, n);
b9f1d9a4 824 break;
e9071366
AD
825 }
826}
827
828
829/*-------------------------.
830| Initialize the scanner. |
831`-------------------------*/
832
28e52c0d 833/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 834 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 835
eb095650 836static char const *
28e52c0d 837translate_action (code_props *self, int sc_context)
e9071366 838{
2ce4ed68 839 char *res;
e9071366
AD
840 static bool initialized = false;
841 if (!initialized)
842 {
843 obstack_init (&obstack_for_string);
e9071366
AD
844 yy_flex_debug = 0;
845 initialized = true;
846 }
847
28e52c0d
JD
848 loc->start = loc->end = self->location.start;
849 yy_switch_to_buffer (yy_scan_string (self->code));
850 res = code_lex (self, sc_context);
e9071366
AD
851 yy_delete_buffer (YY_CURRENT_BUFFER);
852
853 return res;
854}
855
28e52c0d
JD
856/*------------------------------------------------------------------------.
857| Implementation of the public interface as documented in "scan-code.h". |
858`------------------------------------------------------------------------*/
859
860void
861code_props_none_init (code_props *self)
76290368 862{
28e52c0d 863 *self = code_props_none;
76290368
JD
864}
865
70946cff 866code_props code_props_none = CODE_PROPS_NONE_INIT;
28e52c0d
JD
867
868void
872b52bc 869code_props_plain_init (code_props *self, char const *code,
e9690142 870 location code_loc)
76290368 871{
ea9a35c6 872 code_props_none_init (self);
28e52c0d
JD
873 self->kind = CODE_PROPS_PLAIN;
874 self->code = code;
875 self->location = code_loc;
76290368
JD
876}
877
28e52c0d
JD
878void
879code_props_symbol_action_init (code_props *self, char const *code,
880 location code_loc)
e9071366 881{
ea9a35c6 882 code_props_none_init (self);
28e52c0d
JD
883 self->kind = CODE_PROPS_SYMBOL_ACTION;
884 self->code = code;
885 self->location = code_loc;
e9071366
AD
886}
887
28e52c0d
JD
888void
889code_props_rule_action_init (code_props *self, char const *code,
b9f1d9a4 890 location code_loc, symbol_list *rule,
e9690142 891 named_ref *name, bool is_predicate)
28e52c0d 892{
ea9a35c6 893 code_props_none_init (self);
28e52c0d
JD
894 self->kind = CODE_PROPS_RULE_ACTION;
895 self->code = code;
896 self->location = code_loc;
28e52c0d 897 self->rule = rule;
ba4184ec 898 self->named_ref = name;
ca2a6d15 899 self->is_predicate = is_predicate;
28e52c0d
JD
900}
901
902void
903code_props_translate_code (code_props *self)
904{
905 switch (self->kind)
906 {
907 case CODE_PROPS_NONE:
908 break;
909 case CODE_PROPS_PLAIN:
910 self->code = translate_action (self, INITIAL);
911 break;
912 case CODE_PROPS_SYMBOL_ACTION:
913 self->code = translate_action (self, SC_SYMBOL_ACTION);
914 break;
915 case CODE_PROPS_RULE_ACTION:
916 self->code = translate_action (self, SC_RULE_ACTION);
917 break;
918 }
919}
920
921void
922code_scanner_last_string_free (void)
923{
924 STRING_FREE;
925}
e9071366
AD
926
927void
928code_scanner_free (void)
929{
930 obstack_free (&obstack_for_string, 0);
13cdf208
AR
931 variant_table_free ();
932
e9071366 933 /* Reclaim Flex's buffers. */
580b8926 934 yylex_destroy ();
e9071366 935}