]> git.saurik.com Git - bison.git/blame - src/scan-code.l
YYFAIL: remove.
[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
676997e5 50static void handle_action_dollar (symbol_list *rule, char *cp,
e9690142 51 location dollar_loc);
676997e5
JD
52static void handle_action_at (symbol_list *rule, char *cp, location at_loc);
53
54/* A string to be pushed to obstack after dollar/at has been handled. */
55static char *ref_tail_fields;
b9f1d9a4 56
e9071366
AD
57static location the_location;
58static location *loc = &the_location;
ddc8ede1 59
28e52c0d
JD
60/* A string representing the most recent translation. */
61static char *last_string;
62
ddc8ede1
PE
63/* True if an untyped $$ or $n was seen. */
64static bool untyped_var_seen;
b9f1d9a4 65
e9071366
AD
66%}
67 /* C and C++ comments in code. */
68%x SC_COMMENT SC_LINE_COMMENT
69 /* Strings and characters in code. */
70%x SC_STRING SC_CHARACTER
71 /* Whether in a rule or symbol action. Specifies the translation
72 of $ and @. */
73%x SC_RULE_ACTION SC_SYMBOL_ACTION
74
75
76/* POSIX says that a tag must be both an id and a C union member, but
77 historically almost any character is allowed in a tag. We disallow
78 NUL and newline, as this simplifies our implementation. */
e9690142 79tag [^\0\n>]+
e9071366
AD
80
81/* Zero or more instances of backslash-newline. Following GCC, allow
82 white space between the backslash and the newline. */
e9690142 83splice (\\[ \f\t\v]*\n)*
e9071366 84
676997e5
JD
85/* C style identifier. Must start with letter. Will be used for
86 named symbol references. Shall be kept synchronized with
87 scan-gram.l "letter" and "id". */
e9690142
JD
88letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
89id {letter}({letter}|[-0-9])*
676997e5 90ref -?[0-9]+|{id}|"["{id}"]"|"$"
b9f1d9a4 91
e9071366
AD
92%%
93
94%{
2346344a 95 /* Nesting level of the current code in braces. */
4f82b42a 96 int braces_level = 0;
2346344a 97
e8cd1ad6 98 /* Whether a semicolon is probably needed.
ae93e4e4 99 The heuristic is that a semicolon is not needed after '{', '}', ';',
e8cd1ad6
DJ
100 or a C preprocessor directive, and that whitespaces and comments
101 do not affect this flag.
ae93e4e4 102 Note that '{' does not need a semicolon because of '{}'.
e8cd1ad6
DJ
103 A semicolon may be needed before a cpp direcive, but don't bother. */
104 bool need_semicolon = false;
105
106 /* Whether in a C preprocessor directive. Don't use a start condition
107 for this because, at the end of strings and comments, we still need
108 to know whether we're in a directive. */
109 bool in_cpp = false;
110
e9071366
AD
111 /* This scanner is special: it is invoked only once, henceforth
112 is expected to return only once. This initialization is
113 therefore done once per action to translate. */
4f82b42a 114 aver (sc_context == SC_SYMBOL_ACTION
e9690142
JD
115 || sc_context == SC_RULE_ACTION
116 || sc_context == INITIAL);
e9071366
AD
117 BEGIN sc_context;
118%}
119
120 /*------------------------------------------------------------.
ae93e4e4 121 | Scanning a C comment. The initial '/ *' is already eaten. |
e9071366
AD
122 `------------------------------------------------------------*/
123
124<SC_COMMENT>
125{
126 "*"{splice}"/" STRING_GROW; BEGIN sc_context;
127}
128
129
130 /*--------------------------------------------------------------.
ae93e4e4 131 | Scanning a line comment. The initial '//' is already eaten. |
e9071366
AD
132 `--------------------------------------------------------------*/
133
134<SC_LINE_COMMENT>
135{
e9690142
JD
136 "\n" STRING_GROW; BEGIN sc_context;
137 {splice} STRING_GROW;
e9071366
AD
138}
139
140
141 /*--------------------------------------------.
142 | Scanning user-code characters and strings. |
143 `--------------------------------------------*/
144
145<SC_CHARACTER,SC_STRING>
146{
e9690142 147 {splice}|\\{splice}. STRING_GROW;
e9071366
AD
148}
149
150<SC_CHARACTER>
151{
e9690142 152 "'" STRING_GROW; BEGIN sc_context;
e9071366
AD
153}
154
155<SC_STRING>
156{
e9690142 157 "\"" STRING_GROW; BEGIN sc_context;
e9071366
AD
158}
159
160
161<SC_RULE_ACTION,SC_SYMBOL_ACTION>{
162 "'" {
163 STRING_GROW;
164 BEGIN SC_CHARACTER;
e8cd1ad6 165 need_semicolon = true;
e9071366
AD
166 }
167 "\"" {
168 STRING_GROW;
169 BEGIN SC_STRING;
e8cd1ad6 170 need_semicolon = true;
e9071366
AD
171 }
172 "/"{splice}"*" {
173 STRING_GROW;
174 BEGIN SC_COMMENT;
175 }
176 "/"{splice}"/" {
177 STRING_GROW;
178 BEGIN SC_LINE_COMMENT;
179 }
180}
181
182<SC_RULE_ACTION>
183{
b9f1d9a4 184 "$"("<"{tag}">")?{ref} {
676997e5
JD
185 ref_tail_fields = 0;
186 handle_action_dollar (self->rule, yytext, *loc);
187 if (ref_tail_fields) {
188 obstack_sgrow (&obstack_for_string, ref_tail_fields);
189 }
e8cd1ad6 190 need_semicolon = true;
28e52c0d 191 }
b9f1d9a4 192 "@"{ref} {
676997e5
JD
193 ref_tail_fields = 0;
194 handle_action_at (self->rule, yytext, *loc);
195 if (ref_tail_fields) {
196 obstack_sgrow (&obstack_for_string, ref_tail_fields);
197 }
e8cd1ad6 198 need_semicolon = true;
28e52c0d 199 }
e9071366 200 "$" {
6fb8b256 201 complain_at (*loc, Wother, _("stray '$'"));
e9071366 202 obstack_sgrow (&obstack_for_string, "$][");
e8cd1ad6 203 need_semicolon = true;
e9071366
AD
204 }
205 "@" {
6fb8b256 206 complain_at (*loc, Wother, _("stray '@'"));
e9071366 207 obstack_sgrow (&obstack_for_string, "@@");
e8cd1ad6
DJ
208 need_semicolon = true;
209 }
210 "[" {
211 obstack_sgrow (&obstack_for_string, "@{");
212 need_semicolon = true;
213 }
214 "]" {
215 obstack_sgrow (&obstack_for_string, "@}");
216 need_semicolon = true;
e9071366 217 }
2346344a 218
e8cd1ad6
DJ
219 ";" STRING_GROW; need_semicolon = false;
220 "{" STRING_GROW; ++braces_level; need_semicolon = false;
2346344a 221 "}" {
58bd33b7 222 bool outer_brace = --braces_level == 0;
2346344a 223
ae93e4e4 224 /* As an undocumented Bison extension, append ';' before the last
2346344a 225 brace in braced code, so that the user code can omit trailing
ae93e4e4 226 ';'. But do not append ';' if emulating Yacc, since Yacc does
e8cd1ad6 227 not append one. */
d9a9b96b 228 if (outer_brace && !yacc_flag && language_prio == default_prio
e8cd1ad6
DJ
229 && skeleton_prio == default_prio && need_semicolon && ! in_cpp)
230 {
6fb8b256
VS
231 complain_at (*loc, Wother,
232 _("a ';' might be needed at the end of action code"));
233 complain_at (*loc, Wother,
234 _("future versions of Bison will not add the ';'"));
e9690142 235 obstack_1grow (&obstack_for_string, ';');
e8cd1ad6 236 }
2346344a
AD
237
238 STRING_GROW;
e8cd1ad6 239 need_semicolon = false;
2346344a 240 }
e8cd1ad6
DJ
241
242 /* Preprocessing directives should only be recognized at the beginning
243 of lines, allowing whitespace including comments, but in C/C++,
ae93e4e4
JM
244 '#' can only be the start of preprocessor directives or within
245 '#define' directives anyway, so don't bother with begin of line. */
e8cd1ad6
DJ
246 "#" STRING_GROW; in_cpp = true;
247
248 {splice} STRING_GROW;
bc0f5737 249 [\n\r] STRING_GROW; if (in_cpp) in_cpp = need_semicolon = false;
e8cd1ad6 250 [ \t\f] STRING_GROW;
47db7ed1 251 . STRING_GROW; need_semicolon = true;
e9071366
AD
252}
253
254<SC_SYMBOL_ACTION>
255{
28e52c0d
JD
256 "$$" {
257 obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
258 self->is_value_used = true;
259 }
e785ccf7
JD
260 "@$" {
261 obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
bc0f5737 262 muscle_percent_define_ensure("locations", the_location, true);
e785ccf7 263 }
e9071366
AD
264}
265
266
267 /*-----------------------------------------.
268 | Escape M4 quoting characters in C code. |
269 `-----------------------------------------*/
270
271<*>
272{
e9690142
JD
273 \$ obstack_sgrow (&obstack_for_string, "$][");
274 \@ obstack_sgrow (&obstack_for_string, "@@");
275 \[ obstack_sgrow (&obstack_for_string, "@{");
276 \] obstack_sgrow (&obstack_for_string, "@}");
e9071366
AD
277}
278
279 /*-----------------------------------------------------.
280 | By default, grow the string obstack with the input. |
281 `-----------------------------------------------------*/
282
e9690142 283<*>.|\n STRING_GROW;
e9071366
AD
284
285 /* End of processing. */
e9690142 286<*><<EOF>> {
28e52c0d
JD
287 STRING_FINISH;
288 return last_string;
e9071366
AD
289 }
290
291%%
292
b9f1d9a4 293static inline bool
872b52bc 294is_dot_or_dash (char ch)
b9f1d9a4
AR
295{
296 return ch == '.' || ch == '-';
297}
298
299static inline bool
872b52bc 300contains_dot_or_dash (const char* p)
b9f1d9a4 301{
872b52bc
AR
302 for (; *p; ++p)
303 if (is_dot_or_dash (*p))
304 return true;
305 return false;
b9f1d9a4
AR
306}
307
872b52bc 308/* Defines a variant of a symbolic name resolution. */
b9f1d9a4
AR
309typedef struct
310{
311 /* Index in symbol list. */
ce268795 312 unsigned symbol_index;
b9f1d9a4
AR
313
314 /* Matched symbol id and loc. */
315 uniqstr id;
316 location loc;
317
872b52bc 318 /* Hiding named reference. */
b9f1d9a4
AR
319 named_ref* hidden_by;
320
872b52bc
AR
321 /* Error flags. May contain zero (no errors) or
322 a combination of VARIANT_* values. */
b9f1d9a4
AR
323 unsigned err;
324} variant;
325
872b52bc
AR
326/* Set when the variant refers to a symbol hidden
327 by an explicit symbol reference. */
328#define VARIANT_HIDDEN (1 << 0)
329
676997e5
JD
330/* Set when the variant refers to a symbol containing
331 dots or dashes. Will require explicit bracketing. */
332#define VARIANT_BAD_BRACKETING (1 << 1)
333
872b52bc
AR
334/* Set when the variant refers to a symbol which is
335 not visible from current midrule. */
676997e5 336#define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2)
872b52bc 337
b9f1d9a4
AR
338static variant *variant_table = 0;
339static unsigned variant_table_size = 0;
340static unsigned variant_count = 0;
341
342static variant *
ba4184ec 343variant_table_grow (void)
b9f1d9a4
AR
344{
345 ++variant_count;
346 if (variant_count > variant_table_size)
347 {
348 while (variant_count > variant_table_size)
e9690142 349 variant_table_size = 2 * variant_table_size + 3;
b9f1d9a4 350 variant_table = xnrealloc (variant_table, variant_table_size,
e9690142 351 sizeof *variant_table);
b9f1d9a4
AR
352 }
353 return &variant_table[variant_count - 1];
354}
355
13cdf208 356static void
ba4184ec 357variant_table_free (void)
13cdf208 358{
ba4184ec 359 free (variant_table);
13cdf208
AR
360 variant_table = 0;
361 variant_table_size = variant_count = 0;
362}
363
676997e5
JD
364static char *
365find_prefix_end (const char *prefix, char *begin, char *end)
b9f1d9a4 366{
676997e5
JD
367 char *ptr = begin;
368
369 for (; *prefix && ptr != end; ++prefix, ++ptr)
370 if (*prefix != *ptr)
371 return 0;
372
373 if (*prefix)
374 return 0;
375
376 return ptr;
b9f1d9a4
AR
377}
378
379static variant *
ba4184ec 380variant_add (uniqstr id, location id_loc, unsigned symbol_index,
e9690142 381 char *cp, char *cp_end, bool explicit_bracketing)
b9f1d9a4 382{
676997e5
JD
383 char *prefix_end;
384
385 prefix_end = find_prefix_end (id, cp, cp_end);
386 if (prefix_end &&
387 (prefix_end == cp_end ||
388 (!explicit_bracketing && is_dot_or_dash (*prefix_end))))
b9f1d9a4 389 {
872b52bc 390 variant *r = variant_table_grow ();
ce268795 391 r->symbol_index = symbol_index;
b9f1d9a4 392 r->id = id;
ba4184ec 393 r->loc = id_loc;
b9f1d9a4
AR
394 r->hidden_by = NULL;
395 r->err = 0;
396 return r;
397 }
398 else
399 return NULL;
400}
401
872b52bc 402static const char *
ba4184ec 403get_at_spec(unsigned symbol_index)
872b52bc
AR
404{
405 static char at_buf[20];
ba4184ec 406 if (symbol_index == 0)
872b52bc
AR
407 strcpy (at_buf, "$$");
408 else
ba4184ec 409 snprintf (at_buf, sizeof at_buf, "$%u", symbol_index);
872b52bc
AR
410 return at_buf;
411}
412
ce268795 413static void
676997e5
JD
414show_sub_messages (const char* cp, bool explicit_bracketing,
415 int midrule_rhs_index, char dollar_or_at,
66381412 416 bool is_warning, unsigned indent)
ce268795
AR
417{
418 unsigned i;
419
420 for (i = 0; i < variant_count; ++i)
421 {
422 const variant *var = &variant_table[i];
423 const char *at_spec = get_at_spec (var->symbol_index);
424
425 if (var->err == 0)
426 {
427 if (is_warning)
6fb8b256
VS
428 complain_at_indent (var->loc, Wother, &indent,
429 _("refers to: %c%s at %s"), dollar_or_at,
430 var->id, at_spec);
ce268795 431 else
6fb8b256
VS
432 complain_at_indent (var->loc, complaint, &indent,
433 _("refers to: %c%s at %s"), dollar_or_at,
434 var->id, at_spec);
ce268795
AR
435 }
436 else
e9690142
JD
437 {
438 static struct obstack msg_buf;
439 const char *tail = explicit_bracketing ? "" :
440 cp + strlen (var->id);
441 const char *id = var->hidden_by ? var->hidden_by->id :
442 var->id;
443 location id_loc = var->hidden_by ? var->hidden_by->loc :
444 var->loc;
445
446 /* Create the explanation message. */
447 obstack_init (&msg_buf);
448
449 obstack_fgrow1 (&msg_buf, _("possibly meant: %c"), dollar_or_at);
450 if (contains_dot_or_dash (id))
451 obstack_fgrow1 (&msg_buf, "[%s]", id);
452 else
453 obstack_sgrow (&msg_buf, id);
454 obstack_sgrow (&msg_buf, tail);
455
456 if (var->err & VARIANT_HIDDEN)
457 {
458 obstack_fgrow1 (&msg_buf, _(", hiding %c"), dollar_or_at);
459 if (contains_dot_or_dash (var->id))
460 obstack_fgrow1 (&msg_buf, "[%s]", var->id);
461 else
462 obstack_sgrow (&msg_buf, var->id);
463 obstack_sgrow (&msg_buf, tail);
464 }
465
466 obstack_fgrow1 (&msg_buf, _(" at %s"), at_spec);
467
468 if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
66381412
AR
469 {
470 const char *format =
471 _(", cannot be accessed from mid-rule action at $%d");
472 obstack_fgrow1 (&msg_buf, format, midrule_rhs_index);
473 }
ce268795 474
e9690142 475 obstack_1grow (&msg_buf, '\0');
ce268795 476 if (is_warning)
6fb8b256
VS
477 complain_at_indent (id_loc, Wother, &indent, "%s",
478 (char *) obstack_finish (&msg_buf));
ce268795 479 else
6fb8b256 480 complain_at_indent (id_loc, complaint, &indent, "%s",
66381412 481 (char *) obstack_finish (&msg_buf));
e9690142
JD
482 obstack_free (&msg_buf, 0);
483 }
ce268795
AR
484 }
485}
486
872b52bc
AR
487/* Returned from "parse_ref" when the reference
488 is inappropriate. */
b9f1d9a4 489#define INVALID_REF (INT_MIN)
872b52bc
AR
490
491/* Returned from "parse_ref" when the reference
ce268795 492 points to LHS ($$) of the current rule or midrule. */
b9f1d9a4
AR
493#define LHS_REF (INT_MIN + 1)
494
66381412
AR
495/* Sub-messages indent. */
496#define SUB_INDENT (4)
497
676997e5
JD
498/* Parse named or positional reference. In case of positional
499 references, can return negative values for $-n "deep" stack
500 accesses. */
b9f1d9a4 501static long int
676997e5 502parse_ref (char *cp, symbol_list *rule, int rule_length,
e9690142
JD
503 int midrule_rhs_index, char *text, location text_loc,
504 char dollar_or_at)
b9f1d9a4 505{
676997e5
JD
506 symbol_list *l;
507 char *cp_end;
61bc57e5 508 bool explicit_bracketing;
872b52bc 509 unsigned i;
ce268795
AR
510 unsigned valid_variants = 0;
511 unsigned valid_variant_index = 0;
b9f1d9a4
AR
512
513 if ('$' == *cp)
514 return LHS_REF;
515
676997e5 516 if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1))))
b9f1d9a4 517 {
676997e5 518 long int num = strtol (cp, &cp, 10);
b9f1d9a4 519 if (1 - INT_MAX + rule_length <= num && num <= rule_length)
e9690142 520 return num;
b9f1d9a4 521 else
e9690142 522 {
6fb8b256 523 complain_at (text_loc, complaint, _("integer out of range: %s"),
ba4184ec 524 quote (text));
e9690142
JD
525 return INVALID_REF;
526 }
b9f1d9a4
AR
527 }
528
676997e5
JD
529 if ('[' == *cp)
530 {
531 /* Ignore the brackets. */
532 char *p;
533 for (p = ++cp; *p != ']'; ++p)
e9690142 534 continue;
676997e5
JD
535 cp_end = p;
536
537 explicit_bracketing = true;
538 }
539 else
540 {
541 /* Take all characters of the name. */
542 char* p;
543 for (p = cp; *p; ++p)
e9690142
JD
544 if (is_dot_or_dash (*p))
545 {
546 ref_tail_fields = p;
547 break;
548 }
676997e5 549 for (p = cp; *p; ++p)
e9690142 550 continue;
676997e5
JD
551 cp_end = p;
552
553 explicit_bracketing = false;
554 }
b9f1d9a4
AR
555
556 /* Add all relevant variants. */
872b52bc 557 {
ba4184ec 558 unsigned symbol_index;
872b52bc 559 variant_count = 0;
ba4184ec
AR
560 for (symbol_index = 0, l = rule; !symbol_list_null (l);
561 ++symbol_index, l = l->next)
872b52bc 562 {
e9690142
JD
563 variant *var;
564 if (l->content_type != SYMLIST_SYMBOL)
565 continue;
b9f1d9a4 566
e9690142 567 var = variant_add (l->content.sym->tag, l->sym_loc,
676997e5 568 symbol_index, cp, cp_end, explicit_bracketing);
e9690142
JD
569 if (var && l->named_ref)
570 var->hidden_by = l->named_ref;
b9f1d9a4 571
e9690142
JD
572 if (l->named_ref)
573 variant_add (l->named_ref->id, l->named_ref->loc,
676997e5 574 symbol_index, cp, cp_end, explicit_bracketing);
872b52bc
AR
575 }
576 }
b9f1d9a4
AR
577
578 /* Check errors. */
b9f1d9a4
AR
579 for (i = 0; i < variant_count; ++i)
580 {
ba4184ec 581 variant *var = &variant_table[i];
ce268795 582 unsigned symbol_index = var->symbol_index;
b9f1d9a4
AR
583
584 /* Check visibility from mid-rule actions. */
872b52bc 585 if (midrule_rhs_index != 0
e9690142 586 && (symbol_index == 0 || midrule_rhs_index < symbol_index))
ce268795 587 var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
b9f1d9a4 588
676997e5
JD
589 /* Check correct bracketing. */
590 if (!explicit_bracketing && contains_dot_or_dash (var->id))
591 var->err |= VARIANT_BAD_BRACKETING;
592
b9f1d9a4 593 /* Check using of hidden symbols. */
ba4184ec 594 if (var->hidden_by)
ce268795 595 var->err |= VARIANT_HIDDEN;
b9f1d9a4 596
ba4184ec 597 if (!var->err)
ce268795
AR
598 {
599 valid_variant_index = i;
600 ++valid_variants;
601 }
b9f1d9a4
AR
602 }
603
ce268795 604 switch (valid_variants)
b9f1d9a4 605 {
ce268795 606 case 0:
f64e406b 607 {
676997e5
JD
608 unsigned len = (explicit_bracketing || !ref_tail_fields) ?
609 cp_end - cp : ref_tail_fields - cp;
66381412 610 unsigned indent = 0;
f64e406b 611
6fb8b256
VS
612 complain_at_indent (text_loc, complaint, &indent,
613 _("invalid reference: %s"), quote (text));
66381412 614 indent += SUB_INDENT;
5c9efc75
JD
615 if (len == 0)
616 {
617 location sym_loc = text_loc;
618 sym_loc.start.column += 1;
619 sym_loc.end = sym_loc.start;
620 const char *format =
ae93e4e4
JM
621 _("syntax error after '%c', expecting integer, letter,"
622 " '_', '[', or '$'");
6fb8b256
VS
623 complain_at_indent (sym_loc, complaint, &indent, format,
624 dollar_or_at);
5c9efc75
JD
625 }
626 else if (midrule_rhs_index)
66381412
AR
627 {
628 const char *format =
629 _("symbol not found in production before $%d: %.*s");
6fb8b256 630 complain_at_indent (rule->location, complaint, &indent, format,
66381412
AR
631 midrule_rhs_index, len, cp);
632 }
f64e406b 633 else
66381412
AR
634 {
635 const char *format =
636 _("symbol not found in production: %.*s");
6fb8b256 637 complain_at_indent (rule->location, complaint, &indent, format,
66381412
AR
638 len, cp);
639 }
f64e406b
AR
640
641 if (variant_count > 0)
676997e5
JD
642 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
643 dollar_or_at, false, indent);
f64e406b
AR
644 return INVALID_REF;
645 }
ce268795
AR
646 case 1:
647 {
66381412 648 unsigned indent = 0;
ce268795
AR
649 if (variant_count > 1)
650 {
6fb8b256
VS
651 complain_at_indent (text_loc, Wother, &indent,
652 _("misleading reference: %s"), quote (text));
676997e5
JD
653 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
654 dollar_or_at, true, indent + SUB_INDENT);
ce268795
AR
655 }
656 {
657 unsigned symbol_index =
658 variant_table[valid_variant_index].symbol_index;
659 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
660 }
661 }
662 case 2:
663 default:
66381412
AR
664 {
665 unsigned indent = 0;
6fb8b256
VS
666 complain_at_indent (text_loc, complaint, &indent,
667 _("ambiguous reference: %s"), quote (text));
676997e5
JD
668 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
669 dollar_or_at, false, indent + SUB_INDENT);
66381412
AR
670 return INVALID_REF;
671 }
b9f1d9a4
AR
672 }
673
ce268795 674 /* Not reachable. */
b9f1d9a4
AR
675 return INVALID_REF;
676}
677
e9071366
AD
678/* Keeps track of the maximum number of semantic values to the left of
679 a handle (those referenced by $0, $-1, etc.) are required by the
680 semantic actions of this grammar. */
681int max_left_semantic_context = 0;
682
683
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;
b9f1d9a4 697 char *gt_ptr = 0;
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. */
714 if (*cp == '<')
715 {
716 type_name = ++cp;
717 while (*cp != '>')
e9690142 718 ++cp;
b9f1d9a4
AR
719
720 /* The '>' symbol will be later replaced by '\0'. Original
e9690142 721 'text' is needed for error messages. */
b9f1d9a4 722 gt_ptr = cp;
e9071366 723 ++cp;
ddc8ede1 724 if (untyped_var_seen)
6fb8b256
VS
725 complain_at (dollar_loc, complaint,
726 _("explicit type given in untyped grammar"));
ddc8ede1 727 tag_seen = true;
e9071366
AD
728 }
729
872b52bc 730 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 731 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
b9f1d9a4
AR
732
733 if (gt_ptr)
734 *gt_ptr = '\0';
735
736 switch (n)
e9071366 737 {
b9f1d9a4
AR
738 case INVALID_REF:
739 break;
740
741 case LHS_REF:
e9071366 742 if (!type_name)
e9690142 743 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
744
745 if (!type_name)
e9690142
JD
746 {
747 if (union_seen | tag_seen)
748 {
749 if (rule->midrule_parent_rule)
6fb8b256 750 complain_at (dollar_loc, complaint,
4a9cd8f2 751 _("$$ for the midrule at $%d of %s"
e9690142
JD
752 " has no declared type"),
753 rule->midrule_parent_rhs_index,
4a9cd8f2 754 quote (effective_rule->content.sym->tag));
e9690142 755 else
6fb8b256
VS
756 complain_at (dollar_loc, complaint,
757 _("$$ of %s has no declared type"),
4a9cd8f2 758 quote (rule->content.sym->tag));
e9690142
JD
759 }
760 else
761 untyped_var_seen = true;
762 type_name = "";
763 }
ddc8ede1 764
e9071366 765 obstack_fgrow1 (&obstack_for_string,
e9690142 766 "]b4_lhs_value([%s])[", type_name);
f6857bbf 767 rule->action_props.is_value_used = true;
b9f1d9a4
AR
768 break;
769
770 default:
771 if (max_left_semantic_context < 1 - n)
e9690142 772 max_left_semantic_context = 1 - n;
b9f1d9a4 773 if (!type_name && 0 < n)
e9690142
JD
774 type_name =
775 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
b9f1d9a4 776 if (!type_name)
e9690142
JD
777 {
778 if (union_seen | tag_seen)
6fb8b256
VS
779 complain_at (dollar_loc, complaint,
780 _("$%s of %s has no declared type"), cp,
781 quote (effective_rule->content.sym->tag));
e9690142
JD
782 else
783 untyped_var_seen = true;
784 type_name = "";
785 }
b9f1d9a4
AR
786
787 obstack_fgrow3 (&obstack_for_string,
e9690142
JD
788 "]b4_rhs_value(%d, %d, [%s])[",
789 effective_rule_length, n, type_name);
b9f1d9a4 790 if (n > 0)
e9690142
JD
791 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
792 true;
b9f1d9a4 793 break;
e9071366
AD
794 }
795}
796
797
798/*------------------------------------------------------.
ae93e4e4 799| TEXT is a location token (i.e., a '@...'). Output to |
e9071366
AD
800| OBSTACK_FOR_STRING a reference to this location. |
801`------------------------------------------------------*/
802
803static void
676997e5 804handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366 805{
676997e5
JD
806 char *cp = text + 1;
807 symbol_list *effective_rule;
872b52bc
AR
808 int effective_rule_length;
809 int n;
b9f1d9a4
AR
810
811 if (rule->midrule_parent_rule)
812 {
813 effective_rule = rule->midrule_parent_rule;
814 effective_rule_length = rule->midrule_parent_rhs_index - 1;
815 }
816 else
817 {
818 effective_rule = rule;
819 effective_rule_length = symbol_list_length (rule->next);
820 }
ffa4ba3a 821
bc0f5737 822 muscle_percent_define_ensure("locations", at_loc, true);
e9071366 823
872b52bc 824 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 825 rule->midrule_parent_rhs_index, text, at_loc, '@');
b9f1d9a4 826 switch (n)
e9071366 827 {
b9f1d9a4
AR
828 case INVALID_REF:
829 break;
e9071366 830
b9f1d9a4
AR
831 case LHS_REF:
832 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
833 break;
834
835 default:
836 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
e9690142 837 effective_rule_length, n);
b9f1d9a4 838 break;
e9071366
AD
839 }
840}
841
842
843/*-------------------------.
844| Initialize the scanner. |
845`-------------------------*/
846
28e52c0d 847/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 848 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 849
eb095650 850static char const *
28e52c0d 851translate_action (code_props *self, int sc_context)
e9071366 852{
2ce4ed68 853 char *res;
e9071366
AD
854 static bool initialized = false;
855 if (!initialized)
856 {
857 obstack_init (&obstack_for_string);
e9071366
AD
858 yy_flex_debug = 0;
859 initialized = true;
860 }
861
28e52c0d
JD
862 loc->start = loc->end = self->location.start;
863 yy_switch_to_buffer (yy_scan_string (self->code));
864 res = code_lex (self, sc_context);
e9071366
AD
865 yy_delete_buffer (YY_CURRENT_BUFFER);
866
867 return res;
868}
869
28e52c0d
JD
870/*------------------------------------------------------------------------.
871| Implementation of the public interface as documented in "scan-code.h". |
872`------------------------------------------------------------------------*/
873
874void
875code_props_none_init (code_props *self)
76290368 876{
28e52c0d 877 *self = code_props_none;
76290368
JD
878}
879
70946cff 880code_props code_props_none = CODE_PROPS_NONE_INIT;
28e52c0d
JD
881
882void
872b52bc 883code_props_plain_init (code_props *self, char const *code,
e9690142 884 location code_loc)
76290368 885{
ea9a35c6 886 code_props_none_init (self);
28e52c0d
JD
887 self->kind = CODE_PROPS_PLAIN;
888 self->code = code;
889 self->location = code_loc;
76290368
JD
890}
891
28e52c0d
JD
892void
893code_props_symbol_action_init (code_props *self, char const *code,
894 location code_loc)
e9071366 895{
ea9a35c6 896 code_props_none_init (self);
28e52c0d
JD
897 self->kind = CODE_PROPS_SYMBOL_ACTION;
898 self->code = code;
899 self->location = code_loc;
e9071366
AD
900}
901
28e52c0d
JD
902void
903code_props_rule_action_init (code_props *self, char const *code,
b9f1d9a4 904 location code_loc, symbol_list *rule,
e9690142 905 named_ref *name, bool is_predicate)
28e52c0d 906{
ea9a35c6 907 code_props_none_init (self);
28e52c0d
JD
908 self->kind = CODE_PROPS_RULE_ACTION;
909 self->code = code;
910 self->location = code_loc;
28e52c0d 911 self->rule = rule;
ba4184ec 912 self->named_ref = name;
ca2a6d15 913 self->is_predicate = is_predicate;
28e52c0d
JD
914}
915
916void
917code_props_translate_code (code_props *self)
918{
919 switch (self->kind)
920 {
921 case CODE_PROPS_NONE:
922 break;
923 case CODE_PROPS_PLAIN:
924 self->code = translate_action (self, INITIAL);
925 break;
926 case CODE_PROPS_SYMBOL_ACTION:
927 self->code = translate_action (self, SC_SYMBOL_ACTION);
928 break;
929 case CODE_PROPS_RULE_ACTION:
930 self->code = translate_action (self, SC_RULE_ACTION);
931 break;
932 }
933}
934
935void
936code_scanner_last_string_free (void)
937{
938 STRING_FREE;
939}
e9071366
AD
940
941void
942code_scanner_free (void)
943{
944 obstack_free (&obstack_for_string, 0);
13cdf208
AR
945 variant_table_free ();
946
e9071366 947 /* Reclaim Flex's buffers. */
580b8926 948 yylex_destroy ();
e9071366 949}