]> git.saurik.com Git - bison.git/blame - src/scan-code.l
Merge remote-tracking branch 'origin/maint'
[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;
4395a9ff
JD
251
252 /* YYFAIL is undocumented and was formally deprecated in Bison
253 2.4.2. */
254 YYFAIL {
255 STRING_GROW; need_semicolon = true;
6fb8b256
VS
256 complain_at (*loc, Wother,
257 _("use of YYFAIL, which is deprecated and will be removed"));
4395a9ff
JD
258 }
259
260 /* The sole purpose of this is to make sure identifiers that merely
261 contain YYFAIL don't produce the above warning. */
262 [A-Za-z_][0-9A-Za-z_]* STRING_GROW; need_semicolon = true;
263
264 . STRING_GROW; need_semicolon = true;
e9071366
AD
265}
266
267<SC_SYMBOL_ACTION>
268{
28e52c0d
JD
269 "$$" {
270 obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
271 self->is_value_used = true;
272 }
e785ccf7
JD
273 "@$" {
274 obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
bc0f5737 275 muscle_percent_define_ensure("locations", the_location, true);
e785ccf7 276 }
e9071366
AD
277}
278
279
280 /*-----------------------------------------.
281 | Escape M4 quoting characters in C code. |
282 `-----------------------------------------*/
283
284<*>
285{
e9690142
JD
286 \$ obstack_sgrow (&obstack_for_string, "$][");
287 \@ obstack_sgrow (&obstack_for_string, "@@");
288 \[ obstack_sgrow (&obstack_for_string, "@{");
289 \] obstack_sgrow (&obstack_for_string, "@}");
e9071366
AD
290}
291
292 /*-----------------------------------------------------.
293 | By default, grow the string obstack with the input. |
294 `-----------------------------------------------------*/
295
e9690142 296<*>.|\n STRING_GROW;
e9071366
AD
297
298 /* End of processing. */
e9690142 299<*><<EOF>> {
28e52c0d
JD
300 STRING_FINISH;
301 return last_string;
e9071366
AD
302 }
303
304%%
305
b9f1d9a4 306static inline bool
872b52bc 307is_dot_or_dash (char ch)
b9f1d9a4
AR
308{
309 return ch == '.' || ch == '-';
310}
311
312static inline bool
872b52bc 313contains_dot_or_dash (const char* p)
b9f1d9a4 314{
872b52bc
AR
315 for (; *p; ++p)
316 if (is_dot_or_dash (*p))
317 return true;
318 return false;
b9f1d9a4
AR
319}
320
872b52bc 321/* Defines a variant of a symbolic name resolution. */
b9f1d9a4
AR
322typedef struct
323{
324 /* Index in symbol list. */
ce268795 325 unsigned symbol_index;
b9f1d9a4
AR
326
327 /* Matched symbol id and loc. */
328 uniqstr id;
329 location loc;
330
872b52bc 331 /* Hiding named reference. */
b9f1d9a4
AR
332 named_ref* hidden_by;
333
872b52bc
AR
334 /* Error flags. May contain zero (no errors) or
335 a combination of VARIANT_* values. */
b9f1d9a4
AR
336 unsigned err;
337} variant;
338
872b52bc
AR
339/* Set when the variant refers to a symbol hidden
340 by an explicit symbol reference. */
341#define VARIANT_HIDDEN (1 << 0)
342
676997e5
JD
343/* Set when the variant refers to a symbol containing
344 dots or dashes. Will require explicit bracketing. */
345#define VARIANT_BAD_BRACKETING (1 << 1)
346
872b52bc
AR
347/* Set when the variant refers to a symbol which is
348 not visible from current midrule. */
676997e5 349#define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2)
872b52bc 350
b9f1d9a4
AR
351static variant *variant_table = 0;
352static unsigned variant_table_size = 0;
353static unsigned variant_count = 0;
354
355static variant *
ba4184ec 356variant_table_grow (void)
b9f1d9a4
AR
357{
358 ++variant_count;
359 if (variant_count > variant_table_size)
360 {
361 while (variant_count > variant_table_size)
e9690142 362 variant_table_size = 2 * variant_table_size + 3;
b9f1d9a4 363 variant_table = xnrealloc (variant_table, variant_table_size,
e9690142 364 sizeof *variant_table);
b9f1d9a4
AR
365 }
366 return &variant_table[variant_count - 1];
367}
368
13cdf208 369static void
ba4184ec 370variant_table_free (void)
13cdf208 371{
ba4184ec 372 free (variant_table);
13cdf208
AR
373 variant_table = 0;
374 variant_table_size = variant_count = 0;
375}
376
676997e5
JD
377static char *
378find_prefix_end (const char *prefix, char *begin, char *end)
b9f1d9a4 379{
676997e5
JD
380 char *ptr = begin;
381
382 for (; *prefix && ptr != end; ++prefix, ++ptr)
383 if (*prefix != *ptr)
384 return 0;
385
386 if (*prefix)
387 return 0;
388
389 return ptr;
b9f1d9a4
AR
390}
391
392static variant *
ba4184ec 393variant_add (uniqstr id, location id_loc, unsigned symbol_index,
e9690142 394 char *cp, char *cp_end, bool explicit_bracketing)
b9f1d9a4 395{
676997e5
JD
396 char *prefix_end;
397
398 prefix_end = find_prefix_end (id, cp, cp_end);
399 if (prefix_end &&
400 (prefix_end == cp_end ||
401 (!explicit_bracketing && is_dot_or_dash (*prefix_end))))
b9f1d9a4 402 {
872b52bc 403 variant *r = variant_table_grow ();
ce268795 404 r->symbol_index = symbol_index;
b9f1d9a4 405 r->id = id;
ba4184ec 406 r->loc = id_loc;
b9f1d9a4
AR
407 r->hidden_by = NULL;
408 r->err = 0;
409 return r;
410 }
411 else
412 return NULL;
413}
414
872b52bc 415static const char *
ba4184ec 416get_at_spec(unsigned symbol_index)
872b52bc
AR
417{
418 static char at_buf[20];
ba4184ec 419 if (symbol_index == 0)
872b52bc
AR
420 strcpy (at_buf, "$$");
421 else
ba4184ec 422 snprintf (at_buf, sizeof at_buf, "$%u", symbol_index);
872b52bc
AR
423 return at_buf;
424}
425
ce268795 426static void
676997e5
JD
427show_sub_messages (const char* cp, bool explicit_bracketing,
428 int midrule_rhs_index, char dollar_or_at,
66381412 429 bool is_warning, unsigned indent)
ce268795
AR
430{
431 unsigned i;
432
433 for (i = 0; i < variant_count; ++i)
434 {
435 const variant *var = &variant_table[i];
436 const char *at_spec = get_at_spec (var->symbol_index);
437
438 if (var->err == 0)
439 {
440 if (is_warning)
6fb8b256
VS
441 complain_at_indent (var->loc, Wother, &indent,
442 _("refers to: %c%s at %s"), dollar_or_at,
443 var->id, at_spec);
ce268795 444 else
6fb8b256
VS
445 complain_at_indent (var->loc, complaint, &indent,
446 _("refers to: %c%s at %s"), dollar_or_at,
447 var->id, at_spec);
ce268795
AR
448 }
449 else
e9690142
JD
450 {
451 static struct obstack msg_buf;
452 const char *tail = explicit_bracketing ? "" :
453 cp + strlen (var->id);
454 const char *id = var->hidden_by ? var->hidden_by->id :
455 var->id;
456 location id_loc = var->hidden_by ? var->hidden_by->loc :
457 var->loc;
458
459 /* Create the explanation message. */
460 obstack_init (&msg_buf);
461
462 obstack_fgrow1 (&msg_buf, _("possibly meant: %c"), dollar_or_at);
463 if (contains_dot_or_dash (id))
464 obstack_fgrow1 (&msg_buf, "[%s]", id);
465 else
466 obstack_sgrow (&msg_buf, id);
467 obstack_sgrow (&msg_buf, tail);
468
469 if (var->err & VARIANT_HIDDEN)
470 {
471 obstack_fgrow1 (&msg_buf, _(", hiding %c"), dollar_or_at);
472 if (contains_dot_or_dash (var->id))
473 obstack_fgrow1 (&msg_buf, "[%s]", var->id);
474 else
475 obstack_sgrow (&msg_buf, var->id);
476 obstack_sgrow (&msg_buf, tail);
477 }
478
479 obstack_fgrow1 (&msg_buf, _(" at %s"), at_spec);
480
481 if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
66381412
AR
482 {
483 const char *format =
484 _(", cannot be accessed from mid-rule action at $%d");
485 obstack_fgrow1 (&msg_buf, format, midrule_rhs_index);
486 }
ce268795 487
e9690142 488 obstack_1grow (&msg_buf, '\0');
ce268795 489 if (is_warning)
6fb8b256
VS
490 complain_at_indent (id_loc, Wother, &indent, "%s",
491 (char *) obstack_finish (&msg_buf));
ce268795 492 else
6fb8b256 493 complain_at_indent (id_loc, complaint, &indent, "%s",
66381412 494 (char *) obstack_finish (&msg_buf));
e9690142
JD
495 obstack_free (&msg_buf, 0);
496 }
ce268795
AR
497 }
498}
499
872b52bc
AR
500/* Returned from "parse_ref" when the reference
501 is inappropriate. */
b9f1d9a4 502#define INVALID_REF (INT_MIN)
872b52bc
AR
503
504/* Returned from "parse_ref" when the reference
ce268795 505 points to LHS ($$) of the current rule or midrule. */
b9f1d9a4
AR
506#define LHS_REF (INT_MIN + 1)
507
66381412
AR
508/* Sub-messages indent. */
509#define SUB_INDENT (4)
510
676997e5
JD
511/* Parse named or positional reference. In case of positional
512 references, can return negative values for $-n "deep" stack
513 accesses. */
b9f1d9a4 514static long int
676997e5 515parse_ref (char *cp, symbol_list *rule, int rule_length,
e9690142
JD
516 int midrule_rhs_index, char *text, location text_loc,
517 char dollar_or_at)
b9f1d9a4 518{
676997e5
JD
519 symbol_list *l;
520 char *cp_end;
61bc57e5 521 bool explicit_bracketing;
872b52bc 522 unsigned i;
ce268795
AR
523 unsigned valid_variants = 0;
524 unsigned valid_variant_index = 0;
b9f1d9a4
AR
525
526 if ('$' == *cp)
527 return LHS_REF;
528
676997e5 529 if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1))))
b9f1d9a4 530 {
676997e5 531 long int num = strtol (cp, &cp, 10);
b9f1d9a4 532 if (1 - INT_MAX + rule_length <= num && num <= rule_length)
e9690142 533 return num;
b9f1d9a4 534 else
e9690142 535 {
6fb8b256 536 complain_at (text_loc, complaint, _("integer out of range: %s"),
ba4184ec 537 quote (text));
e9690142
JD
538 return INVALID_REF;
539 }
b9f1d9a4
AR
540 }
541
676997e5
JD
542 if ('[' == *cp)
543 {
544 /* Ignore the brackets. */
545 char *p;
546 for (p = ++cp; *p != ']'; ++p)
e9690142 547 continue;
676997e5
JD
548 cp_end = p;
549
550 explicit_bracketing = true;
551 }
552 else
553 {
554 /* Take all characters of the name. */
555 char* p;
556 for (p = cp; *p; ++p)
e9690142
JD
557 if (is_dot_or_dash (*p))
558 {
559 ref_tail_fields = p;
560 break;
561 }
676997e5 562 for (p = cp; *p; ++p)
e9690142 563 continue;
676997e5
JD
564 cp_end = p;
565
566 explicit_bracketing = false;
567 }
b9f1d9a4
AR
568
569 /* Add all relevant variants. */
872b52bc 570 {
ba4184ec 571 unsigned symbol_index;
872b52bc 572 variant_count = 0;
ba4184ec
AR
573 for (symbol_index = 0, l = rule; !symbol_list_null (l);
574 ++symbol_index, l = l->next)
872b52bc 575 {
e9690142
JD
576 variant *var;
577 if (l->content_type != SYMLIST_SYMBOL)
578 continue;
b9f1d9a4 579
e9690142 580 var = variant_add (l->content.sym->tag, l->sym_loc,
676997e5 581 symbol_index, cp, cp_end, explicit_bracketing);
e9690142
JD
582 if (var && l->named_ref)
583 var->hidden_by = l->named_ref;
b9f1d9a4 584
e9690142
JD
585 if (l->named_ref)
586 variant_add (l->named_ref->id, l->named_ref->loc,
676997e5 587 symbol_index, cp, cp_end, explicit_bracketing);
872b52bc
AR
588 }
589 }
b9f1d9a4
AR
590
591 /* Check errors. */
b9f1d9a4
AR
592 for (i = 0; i < variant_count; ++i)
593 {
ba4184ec 594 variant *var = &variant_table[i];
ce268795 595 unsigned symbol_index = var->symbol_index;
b9f1d9a4
AR
596
597 /* Check visibility from mid-rule actions. */
872b52bc 598 if (midrule_rhs_index != 0
e9690142 599 && (symbol_index == 0 || midrule_rhs_index < symbol_index))
ce268795 600 var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
b9f1d9a4 601
676997e5
JD
602 /* Check correct bracketing. */
603 if (!explicit_bracketing && contains_dot_or_dash (var->id))
604 var->err |= VARIANT_BAD_BRACKETING;
605
b9f1d9a4 606 /* Check using of hidden symbols. */
ba4184ec 607 if (var->hidden_by)
ce268795 608 var->err |= VARIANT_HIDDEN;
b9f1d9a4 609
ba4184ec 610 if (!var->err)
ce268795
AR
611 {
612 valid_variant_index = i;
613 ++valid_variants;
614 }
b9f1d9a4
AR
615 }
616
ce268795 617 switch (valid_variants)
b9f1d9a4 618 {
ce268795 619 case 0:
f64e406b 620 {
676997e5
JD
621 unsigned len = (explicit_bracketing || !ref_tail_fields) ?
622 cp_end - cp : ref_tail_fields - cp;
66381412 623 unsigned indent = 0;
f64e406b 624
6fb8b256
VS
625 complain_at_indent (text_loc, complaint, &indent,
626 _("invalid reference: %s"), quote (text));
66381412 627 indent += SUB_INDENT;
5c9efc75
JD
628 if (len == 0)
629 {
630 location sym_loc = text_loc;
631 sym_loc.start.column += 1;
632 sym_loc.end = sym_loc.start;
633 const char *format =
ae93e4e4
JM
634 _("syntax error after '%c', expecting integer, letter,"
635 " '_', '[', or '$'");
6fb8b256
VS
636 complain_at_indent (sym_loc, complaint, &indent, format,
637 dollar_or_at);
5c9efc75
JD
638 }
639 else if (midrule_rhs_index)
66381412
AR
640 {
641 const char *format =
642 _("symbol not found in production before $%d: %.*s");
6fb8b256 643 complain_at_indent (rule->location, complaint, &indent, format,
66381412
AR
644 midrule_rhs_index, len, cp);
645 }
f64e406b 646 else
66381412
AR
647 {
648 const char *format =
649 _("symbol not found in production: %.*s");
6fb8b256 650 complain_at_indent (rule->location, complaint, &indent, format,
66381412
AR
651 len, cp);
652 }
f64e406b
AR
653
654 if (variant_count > 0)
676997e5
JD
655 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
656 dollar_or_at, false, indent);
f64e406b
AR
657 return INVALID_REF;
658 }
ce268795
AR
659 case 1:
660 {
66381412 661 unsigned indent = 0;
ce268795
AR
662 if (variant_count > 1)
663 {
6fb8b256
VS
664 complain_at_indent (text_loc, Wother, &indent,
665 _("misleading reference: %s"), quote (text));
676997e5
JD
666 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
667 dollar_or_at, true, indent + SUB_INDENT);
ce268795
AR
668 }
669 {
670 unsigned symbol_index =
671 variant_table[valid_variant_index].symbol_index;
672 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
673 }
674 }
675 case 2:
676 default:
66381412
AR
677 {
678 unsigned indent = 0;
6fb8b256
VS
679 complain_at_indent (text_loc, complaint, &indent,
680 _("ambiguous reference: %s"), quote (text));
676997e5
JD
681 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
682 dollar_or_at, false, indent + SUB_INDENT);
66381412
AR
683 return INVALID_REF;
684 }
b9f1d9a4
AR
685 }
686
ce268795 687 /* Not reachable. */
b9f1d9a4
AR
688 return INVALID_REF;
689}
690
e9071366
AD
691/* Keeps track of the maximum number of semantic values to the left of
692 a handle (those referenced by $0, $-1, etc.) are required by the
693 semantic actions of this grammar. */
694int max_left_semantic_context = 0;
695
696
697/*------------------------------------------------------------------.
ae93e4e4 698| TEXT is pointing to a wannabee semantic value (i.e., a '$'). |
e9071366 699| |
676997e5 700| Possible inputs: $[<TYPENAME>]($|integer) |
e9071366
AD
701| |
702| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
703`------------------------------------------------------------------*/
704
705static void
676997e5 706handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 707{
28e52c0d 708 char const *type_name = NULL;
e9071366 709 char *cp = text + 1;
b9f1d9a4 710 char *gt_ptr = 0;
ffa4ba3a 711 symbol_list *effective_rule;
872b52bc
AR
712 int effective_rule_length;
713 int n;
ffa4ba3a
JD
714
715 if (rule->midrule_parent_rule)
716 {
717 effective_rule = rule->midrule_parent_rule;
718 effective_rule_length = rule->midrule_parent_rhs_index - 1;
719 }
720 else
721 {
722 effective_rule = rule;
723 effective_rule_length = symbol_list_length (rule->next);
724 }
e9071366
AD
725
726 /* Get the type name if explicit. */
727 if (*cp == '<')
728 {
729 type_name = ++cp;
730 while (*cp != '>')
e9690142 731 ++cp;
b9f1d9a4
AR
732
733 /* The '>' symbol will be later replaced by '\0'. Original
e9690142 734 'text' is needed for error messages. */
b9f1d9a4 735 gt_ptr = cp;
e9071366 736 ++cp;
ddc8ede1 737 if (untyped_var_seen)
6fb8b256
VS
738 complain_at (dollar_loc, complaint,
739 _("explicit type given in untyped grammar"));
ddc8ede1 740 tag_seen = true;
e9071366
AD
741 }
742
872b52bc 743 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 744 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
b9f1d9a4
AR
745
746 if (gt_ptr)
747 *gt_ptr = '\0';
748
749 switch (n)
e9071366 750 {
b9f1d9a4
AR
751 case INVALID_REF:
752 break;
753
754 case LHS_REF:
e9071366 755 if (!type_name)
e9690142 756 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
757
758 if (!type_name)
e9690142
JD
759 {
760 if (union_seen | tag_seen)
761 {
762 if (rule->midrule_parent_rule)
6fb8b256 763 complain_at (dollar_loc, complaint,
4a9cd8f2 764 _("$$ for the midrule at $%d of %s"
e9690142
JD
765 " has no declared type"),
766 rule->midrule_parent_rhs_index,
4a9cd8f2 767 quote (effective_rule->content.sym->tag));
e9690142 768 else
6fb8b256
VS
769 complain_at (dollar_loc, complaint,
770 _("$$ of %s has no declared type"),
4a9cd8f2 771 quote (rule->content.sym->tag));
e9690142
JD
772 }
773 else
774 untyped_var_seen = true;
775 type_name = "";
776 }
ddc8ede1 777
e9071366 778 obstack_fgrow1 (&obstack_for_string,
e9690142 779 "]b4_lhs_value([%s])[", type_name);
f6857bbf 780 rule->action_props.is_value_used = true;
b9f1d9a4
AR
781 break;
782
783 default:
784 if (max_left_semantic_context < 1 - n)
e9690142 785 max_left_semantic_context = 1 - n;
b9f1d9a4 786 if (!type_name && 0 < n)
e9690142
JD
787 type_name =
788 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
b9f1d9a4 789 if (!type_name)
e9690142
JD
790 {
791 if (union_seen | tag_seen)
6fb8b256
VS
792 complain_at (dollar_loc, complaint,
793 _("$%s of %s has no declared type"), cp,
794 quote (effective_rule->content.sym->tag));
e9690142
JD
795 else
796 untyped_var_seen = true;
797 type_name = "";
798 }
b9f1d9a4
AR
799
800 obstack_fgrow3 (&obstack_for_string,
e9690142
JD
801 "]b4_rhs_value(%d, %d, [%s])[",
802 effective_rule_length, n, type_name);
b9f1d9a4 803 if (n > 0)
e9690142
JD
804 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
805 true;
b9f1d9a4 806 break;
e9071366
AD
807 }
808}
809
810
811/*------------------------------------------------------.
ae93e4e4 812| TEXT is a location token (i.e., a '@...'). Output to |
e9071366
AD
813| OBSTACK_FOR_STRING a reference to this location. |
814`------------------------------------------------------*/
815
816static void
676997e5 817handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366 818{
676997e5
JD
819 char *cp = text + 1;
820 symbol_list *effective_rule;
872b52bc
AR
821 int effective_rule_length;
822 int n;
b9f1d9a4
AR
823
824 if (rule->midrule_parent_rule)
825 {
826 effective_rule = rule->midrule_parent_rule;
827 effective_rule_length = rule->midrule_parent_rhs_index - 1;
828 }
829 else
830 {
831 effective_rule = rule;
832 effective_rule_length = symbol_list_length (rule->next);
833 }
ffa4ba3a 834
bc0f5737 835 muscle_percent_define_ensure("locations", at_loc, true);
e9071366 836
872b52bc 837 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 838 rule->midrule_parent_rhs_index, text, at_loc, '@');
b9f1d9a4 839 switch (n)
e9071366 840 {
b9f1d9a4
AR
841 case INVALID_REF:
842 break;
e9071366 843
b9f1d9a4
AR
844 case LHS_REF:
845 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
846 break;
847
848 default:
849 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
e9690142 850 effective_rule_length, n);
b9f1d9a4 851 break;
e9071366
AD
852 }
853}
854
855
856/*-------------------------.
857| Initialize the scanner. |
858`-------------------------*/
859
28e52c0d 860/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 861 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 862
eb095650 863static char const *
28e52c0d 864translate_action (code_props *self, int sc_context)
e9071366 865{
2ce4ed68 866 char *res;
e9071366
AD
867 static bool initialized = false;
868 if (!initialized)
869 {
870 obstack_init (&obstack_for_string);
e9071366
AD
871 yy_flex_debug = 0;
872 initialized = true;
873 }
874
28e52c0d
JD
875 loc->start = loc->end = self->location.start;
876 yy_switch_to_buffer (yy_scan_string (self->code));
877 res = code_lex (self, sc_context);
e9071366
AD
878 yy_delete_buffer (YY_CURRENT_BUFFER);
879
880 return res;
881}
882
28e52c0d
JD
883/*------------------------------------------------------------------------.
884| Implementation of the public interface as documented in "scan-code.h". |
885`------------------------------------------------------------------------*/
886
887void
888code_props_none_init (code_props *self)
76290368 889{
28e52c0d 890 *self = code_props_none;
76290368
JD
891}
892
28e52c0d
JD
893code_props const code_props_none = CODE_PROPS_NONE_INIT;
894
895void
872b52bc 896code_props_plain_init (code_props *self, char const *code,
e9690142 897 location code_loc)
76290368 898{
ea9a35c6 899 code_props_none_init (self);
28e52c0d
JD
900 self->kind = CODE_PROPS_PLAIN;
901 self->code = code;
902 self->location = code_loc;
76290368
JD
903}
904
28e52c0d
JD
905void
906code_props_symbol_action_init (code_props *self, char const *code,
907 location code_loc)
e9071366 908{
ea9a35c6 909 code_props_none_init (self);
28e52c0d
JD
910 self->kind = CODE_PROPS_SYMBOL_ACTION;
911 self->code = code;
912 self->location = code_loc;
e9071366
AD
913}
914
28e52c0d
JD
915void
916code_props_rule_action_init (code_props *self, char const *code,
b9f1d9a4 917 location code_loc, symbol_list *rule,
e9690142 918 named_ref *name, bool is_predicate)
28e52c0d 919{
ea9a35c6 920 code_props_none_init (self);
28e52c0d
JD
921 self->kind = CODE_PROPS_RULE_ACTION;
922 self->code = code;
923 self->location = code_loc;
28e52c0d 924 self->rule = rule;
ba4184ec 925 self->named_ref = name;
ca2a6d15 926 self->is_predicate = is_predicate;
28e52c0d
JD
927}
928
929void
930code_props_translate_code (code_props *self)
931{
932 switch (self->kind)
933 {
934 case CODE_PROPS_NONE:
935 break;
936 case CODE_PROPS_PLAIN:
937 self->code = translate_action (self, INITIAL);
938 break;
939 case CODE_PROPS_SYMBOL_ACTION:
940 self->code = translate_action (self, SC_SYMBOL_ACTION);
941 break;
942 case CODE_PROPS_RULE_ACTION:
943 self->code = translate_action (self, SC_RULE_ACTION);
944 break;
945 }
946}
947
948void
949code_scanner_last_string_free (void)
950{
951 STRING_FREE;
952}
e9071366
AD
953
954void
955code_scanner_free (void)
956{
957 obstack_free (&obstack_for_string, 0);
13cdf208
AR
958 variant_table_free ();
959
e9071366 960 /* Reclaim Flex's buffers. */
580b8926 961 yylex_destroy ();
e9071366 962}