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