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