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