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