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