]> git.saurik.com Git - bison.git/blame - src/scan-code.l
minor refactoring in user code scanning
[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
AD
447
448 obstack_1grow (&msg_buf, '\0');
c7324354
AD
449 complain_at_indent (id_loc, wflags, &indent, "%s",
450 (char *) obstack_finish (&msg_buf));
cceb7b94 451 obstack_free (&msg_buf, 0);
ce268795
AR
452 }
453}
454
cceb7b94
AD
455static void
456show_sub_messages (const char* cp, bool explicit_bracketing,
457 int midrule_rhs_index, char dollar_or_at,
c7324354 458 warnings wflags, unsigned indent)
cceb7b94
AD
459{
460 unsigned i;
461
462 for (i = 0; i < variant_count; ++i)
463 show_sub_message (cp, explicit_bracketing,
464 midrule_rhs_index, dollar_or_at,
c7324354 465 wflags, indent, &variant_table[i]);
cceb7b94
AD
466}
467
872b52bc
AR
468/* Returned from "parse_ref" when the reference
469 is inappropriate. */
b9f1d9a4 470#define INVALID_REF (INT_MIN)
872b52bc
AR
471
472/* Returned from "parse_ref" when the reference
ce268795 473 points to LHS ($$) of the current rule or midrule. */
b9f1d9a4
AR
474#define LHS_REF (INT_MIN + 1)
475
66381412
AR
476/* Sub-messages indent. */
477#define SUB_INDENT (4)
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 {
6fb8b256 504 complain_at (text_loc, complaint, _("integer out of range: %s"),
ba4184ec 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
6fb8b256
VS
593 complain_at_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;
c7324354
AD
601 complain_at_indent (sym_loc, complaint, &indent,
602 _("syntax error after '%c', expecting integer, "
603 "letter, '_', '[', or '$'"),
6fb8b256 604 dollar_or_at);
5c9efc75
JD
605 }
606 else if (midrule_rhs_index)
c7324354
AD
607 complain_at_indent (rule->location, complaint, &indent,
608 _("symbol not found in production before $%d: "
609 "%.*s"),
610 midrule_rhs_index, len, cp);
f64e406b 611 else
c7324354
AD
612 complain_at_indent (rule->location, complaint, &indent,
613 _("symbol not found in production: %.*s"),
614 len, cp);
f64e406b
AR
615
616 if (variant_count > 0)
676997e5 617 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
c7324354 618 dollar_or_at, complaint, indent);
f64e406b
AR
619 return INVALID_REF;
620 }
ce268795
AR
621 case 1:
622 {
66381412 623 unsigned indent = 0;
ce268795
AR
624 if (variant_count > 1)
625 {
6fb8b256
VS
626 complain_at_indent (text_loc, Wother, &indent,
627 _("misleading reference: %s"), quote (text));
676997e5 628 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
c7324354 629 dollar_or_at, Wother, indent + SUB_INDENT);
ce268795
AR
630 }
631 {
632 unsigned symbol_index =
633 variant_table[valid_variant_index].symbol_index;
634 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
635 }
636 }
637 case 2:
638 default:
66381412
AR
639 {
640 unsigned indent = 0;
6fb8b256
VS
641 complain_at_indent (text_loc, complaint, &indent,
642 _("ambiguous reference: %s"), quote (text));
676997e5 643 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
c7324354 644 dollar_or_at, complaint, indent + SUB_INDENT);
66381412
AR
645 return INVALID_REF;
646 }
b9f1d9a4
AR
647 }
648
ce268795 649 /* Not reachable. */
b9f1d9a4
AR
650 return INVALID_REF;
651}
652
e9071366
AD
653/* Keeps track of the maximum number of semantic values to the left of
654 a handle (those referenced by $0, $-1, etc.) are required by the
655 semantic actions of this grammar. */
656int max_left_semantic_context = 0;
657
658
65a99eca
AD
659/* If CP points to a typename (i.e., <.*?>), set TYPE_NAME to its
660 beginning (i.e., after the opening "<", and return the pointer
661 immediately after it. */
662
663static
664char *
665fetch_type_name (char *cp, char const **type_name,
666 location dollar_loc)
667{
668 if (*cp == '<')
669 {
670 *type_name = ++cp;
671 while (*cp != '>')
4323e0da 672 ++cp;
65a99eca
AD
673
674 /* The '>' symbol will be later replaced by '\0'. Original
4323e0da 675 'text' is needed for error messages. */
65a99eca
AD
676 ++cp;
677 if (untyped_var_seen)
4323e0da
AD
678 complain_at (dollar_loc, complaint,
679 _("explicit type given in untyped grammar"));
65a99eca
AD
680 tag_seen = true;
681 }
682 return cp;
683}
684
e9071366 685/*------------------------------------------------------------------.
ae93e4e4 686| TEXT is pointing to a wannabee semantic value (i.e., a '$'). |
e9071366 687| |
676997e5 688| Possible inputs: $[<TYPENAME>]($|integer) |
e9071366
AD
689| |
690| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
691`------------------------------------------------------------------*/
692
693static void
676997e5 694handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 695{
28e52c0d 696 char const *type_name = NULL;
e9071366 697 char *cp = text + 1;
ffa4ba3a 698 symbol_list *effective_rule;
872b52bc
AR
699 int effective_rule_length;
700 int n;
ffa4ba3a
JD
701
702 if (rule->midrule_parent_rule)
703 {
704 effective_rule = rule->midrule_parent_rule;
705 effective_rule_length = rule->midrule_parent_rhs_index - 1;
706 }
707 else
708 {
709 effective_rule = rule;
710 effective_rule_length = symbol_list_length (rule->next);
711 }
e9071366
AD
712
713 /* Get the type name if explicit. */
65a99eca 714 cp = fetch_type_name (cp, &type_name, dollar_loc);
e9071366 715
872b52bc 716 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 717 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
b9f1d9a4 718
65a99eca
AD
719 /* End type_name. */
720 if (type_name)
721 cp[-1] = '\0';
b9f1d9a4
AR
722
723 switch (n)
e9071366 724 {
b9f1d9a4
AR
725 case INVALID_REF:
726 break;
727
728 case LHS_REF:
e9071366 729 if (!type_name)
e9690142 730 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
731
732 if (!type_name)
e9690142
JD
733 {
734 if (union_seen | tag_seen)
735 {
736 if (rule->midrule_parent_rule)
6fb8b256 737 complain_at (dollar_loc, complaint,
4a9cd8f2 738 _("$$ for the midrule at $%d of %s"
e9690142
JD
739 " has no declared type"),
740 rule->midrule_parent_rhs_index,
4a9cd8f2 741 quote (effective_rule->content.sym->tag));
e9690142 742 else
6fb8b256
VS
743 complain_at (dollar_loc, complaint,
744 _("$$ of %s has no declared type"),
4a9cd8f2 745 quote (rule->content.sym->tag));
e9690142
JD
746 }
747 else
748 untyped_var_seen = true;
e9690142 749 }
ddc8ede1 750
8617d87e
AD
751 obstack_sgrow (&obstack_for_string, "]b4_lhs_value(");
752 obstack_quote (&obstack_for_string, type_name);
753 obstack_sgrow (&obstack_for_string, ")[");
f6857bbf 754 rule->action_props.is_value_used = true;
b9f1d9a4
AR
755 break;
756
757 default:
758 if (max_left_semantic_context < 1 - n)
e9690142 759 max_left_semantic_context = 1 - n;
b9f1d9a4 760 if (!type_name && 0 < n)
e9690142
JD
761 type_name =
762 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
b9f1d9a4 763 if (!type_name)
e9690142
JD
764 {
765 if (union_seen | tag_seen)
6fb8b256
VS
766 complain_at (dollar_loc, complaint,
767 _("$%s of %s has no declared type"), cp,
768 quote (effective_rule->content.sym->tag));
e9690142
JD
769 else
770 untyped_var_seen = true;
e9690142 771 }
b9f1d9a4 772
aaf63e45 773 obstack_printf (&obstack_for_string,
4323e0da 774 "]b4_rhs_value(%d, %d, ", effective_rule_length, n);
8617d87e
AD
775 obstack_quote (&obstack_for_string, type_name);
776 obstack_sgrow (&obstack_for_string, ")[");
b9f1d9a4 777 if (n > 0)
e9690142
JD
778 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
779 true;
b9f1d9a4 780 break;
e9071366
AD
781 }
782}
783
784
785/*------------------------------------------------------.
ae93e4e4 786| TEXT is a location token (i.e., a '@...'). Output to |
e9071366
AD
787| OBSTACK_FOR_STRING a reference to this location. |
788`------------------------------------------------------*/
789
790static void
676997e5 791handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366 792{
676997e5
JD
793 char *cp = text + 1;
794 symbol_list *effective_rule;
872b52bc
AR
795 int effective_rule_length;
796 int n;
b9f1d9a4
AR
797
798 if (rule->midrule_parent_rule)
799 {
800 effective_rule = rule->midrule_parent_rule;
801 effective_rule_length = rule->midrule_parent_rhs_index - 1;
802 }
803 else
804 {
805 effective_rule = rule;
806 effective_rule_length = symbol_list_length (rule->next);
807 }
ffa4ba3a 808
bc0f5737 809 muscle_percent_define_ensure("locations", at_loc, true);
e9071366 810
872b52bc 811 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 812 rule->midrule_parent_rhs_index, text, at_loc, '@');
b9f1d9a4 813 switch (n)
e9071366 814 {
b9f1d9a4
AR
815 case INVALID_REF:
816 break;
e9071366 817
b9f1d9a4
AR
818 case LHS_REF:
819 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
820 break;
821
822 default:
aaf63e45 823 obstack_printf (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
e9690142 824 effective_rule_length, n);
b9f1d9a4 825 break;
e9071366
AD
826 }
827}
828
829
830/*-------------------------.
831| Initialize the scanner. |
832`-------------------------*/
833
28e52c0d 834/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 835 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 836
eb095650 837static char const *
28e52c0d 838translate_action (code_props *self, int sc_context)
e9071366 839{
2ce4ed68 840 char *res;
e9071366
AD
841 static bool initialized = false;
842 if (!initialized)
843 {
844 obstack_init (&obstack_for_string);
e9071366
AD
845 yy_flex_debug = 0;
846 initialized = true;
847 }
848
28e52c0d
JD
849 loc->start = loc->end = self->location.start;
850 yy_switch_to_buffer (yy_scan_string (self->code));
851 res = code_lex (self, sc_context);
e9071366
AD
852 yy_delete_buffer (YY_CURRENT_BUFFER);
853
854 return res;
855}
856
28e52c0d
JD
857/*------------------------------------------------------------------------.
858| Implementation of the public interface as documented in "scan-code.h". |
859`------------------------------------------------------------------------*/
860
861void
862code_props_none_init (code_props *self)
76290368 863{
28e52c0d 864 *self = code_props_none;
76290368
JD
865}
866
70946cff 867code_props code_props_none = CODE_PROPS_NONE_INIT;
28e52c0d
JD
868
869void
872b52bc 870code_props_plain_init (code_props *self, char const *code,
e9690142 871 location code_loc)
76290368 872{
ea9a35c6 873 code_props_none_init (self);
28e52c0d
JD
874 self->kind = CODE_PROPS_PLAIN;
875 self->code = code;
876 self->location = code_loc;
76290368
JD
877}
878
28e52c0d
JD
879void
880code_props_symbol_action_init (code_props *self, char const *code,
881 location code_loc)
e9071366 882{
ea9a35c6 883 code_props_none_init (self);
28e52c0d
JD
884 self->kind = CODE_PROPS_SYMBOL_ACTION;
885 self->code = code;
886 self->location = code_loc;
e9071366
AD
887}
888
28e52c0d
JD
889void
890code_props_rule_action_init (code_props *self, char const *code,
b9f1d9a4 891 location code_loc, symbol_list *rule,
e9690142 892 named_ref *name, bool is_predicate)
28e52c0d 893{
ea9a35c6 894 code_props_none_init (self);
28e52c0d
JD
895 self->kind = CODE_PROPS_RULE_ACTION;
896 self->code = code;
897 self->location = code_loc;
28e52c0d 898 self->rule = rule;
ba4184ec 899 self->named_ref = name;
ca2a6d15 900 self->is_predicate = is_predicate;
28e52c0d
JD
901}
902
903void
904code_props_translate_code (code_props *self)
905{
906 switch (self->kind)
907 {
908 case CODE_PROPS_NONE:
909 break;
910 case CODE_PROPS_PLAIN:
911 self->code = translate_action (self, INITIAL);
912 break;
913 case CODE_PROPS_SYMBOL_ACTION:
914 self->code = translate_action (self, SC_SYMBOL_ACTION);
915 break;
916 case CODE_PROPS_RULE_ACTION:
917 self->code = translate_action (self, SC_RULE_ACTION);
918 break;
919 }
920}
921
922void
923code_scanner_last_string_free (void)
924{
925 STRING_FREE;
926}
e9071366
AD
927
928void
929code_scanner_free (void)
930{
931 obstack_free (&obstack_for_string, 0);
13cdf208
AR
932 variant_table_free ();
933
e9071366 934 /* Reclaim Flex's buffers. */
580b8926 935 yylex_destroy ();
e9071366 936}