]> git.saurik.com Git - bison.git/blame - src/scan-code.l
tests: skip C++ tests that are too demanding for some compilers
[bison.git] / src / scan-code.l
CommitLineData
e9071366
AD
1/* Bison Action Scanner -*- C -*-
2
7d6bad19 3 Copyright (C) 2006-2013 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
cb8d8bb9
AD
81 NUL and newline, as this simplifies our implementation. We allow
82 "->" as a means to dereference a pointer. */
83tag ([^\0\n>]|->)+
e9071366
AD
84
85/* Zero or more instances of backslash-newline. Following GCC, allow
86 white space between the backslash and the newline. */
e9690142 87splice (\\[ \f\t\v]*\n)*
e9071366 88
676997e5
JD
89/* C style identifier. Must start with letter. Will be used for
90 named symbol references. Shall be kept synchronized with
91 scan-gram.l "letter" and "id". */
e9690142
JD
92letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
93id {letter}({letter}|[-0-9])*
676997e5 94ref -?[0-9]+|{id}|"["{id}"]"|"$"
b9f1d9a4 95
e9071366
AD
96%%
97
98%{
99 /* This scanner is special: it is invoked only once, henceforth
100 is expected to return only once. This initialization is
101 therefore done once per action to translate. */
4f82b42a 102 aver (sc_context == SC_SYMBOL_ACTION
e9690142
JD
103 || sc_context == SC_RULE_ACTION
104 || sc_context == INITIAL);
e9071366
AD
105 BEGIN sc_context;
106%}
107
108 /*------------------------------------------------------------.
ae93e4e4 109 | Scanning a C comment. The initial '/ *' is already eaten. |
e9071366
AD
110 `------------------------------------------------------------*/
111
112<SC_COMMENT>
113{
114 "*"{splice}"/" STRING_GROW; BEGIN sc_context;
115}
116
117
118 /*--------------------------------------------------------------.
ae93e4e4 119 | Scanning a line comment. The initial '//' is already eaten. |
e9071366
AD
120 `--------------------------------------------------------------*/
121
122<SC_LINE_COMMENT>
123{
e9690142
JD
124 "\n" STRING_GROW; BEGIN sc_context;
125 {splice} STRING_GROW;
e9071366
AD
126}
127
128
129 /*--------------------------------------------.
130 | Scanning user-code characters and strings. |
131 `--------------------------------------------*/
132
133<SC_CHARACTER,SC_STRING>
134{
e9690142 135 {splice}|\\{splice}. STRING_GROW;
e9071366
AD
136}
137
138<SC_CHARACTER>
139{
e9690142 140 "'" STRING_GROW; BEGIN sc_context;
e9071366
AD
141}
142
143<SC_STRING>
144{
e9690142 145 "\"" STRING_GROW; BEGIN sc_context;
e9071366
AD
146}
147
148
4d24ffb7
AD
149<SC_RULE_ACTION,SC_SYMBOL_ACTION>
150{
05e25f23
AD
151 "'" STRING_GROW; BEGIN SC_CHARACTER;
152 "\"" STRING_GROW; BEGIN SC_STRING;
153 "/"{splice}"*" STRING_GROW; BEGIN SC_COMMENT;
154 "/"{splice}"/" STRING_GROW; BEGIN SC_LINE_COMMENT;
155
26313726 156 [$@] {
bb8e56ff 157 complain (loc, Wother, _("stray '%s'"), yytext);
26313726 158 obstack_escape (&obstack_for_string, yytext);
26313726 159 }
e9071366
AD
160}
161
162<SC_RULE_ACTION>
163{
b9f1d9a4 164 "$"("<"{tag}">")?{ref} {
9b858541 165 ref_tail_fields = NULL;
676997e5 166 handle_action_dollar (self->rule, yytext, *loc);
9b858541 167 if (ref_tail_fields)
676997e5 168 obstack_sgrow (&obstack_for_string, ref_tail_fields);
28e52c0d 169 }
b9f1d9a4 170 "@"{ref} {
9b858541 171 ref_tail_fields = NULL;
676997e5 172 handle_action_at (self->rule, yytext, *loc);
9b858541 173 if (ref_tail_fields)
676997e5 174 obstack_sgrow (&obstack_for_string, ref_tail_fields);
e9071366
AD
175 }
176}
177
178<SC_SYMBOL_ACTION>
179{
4982f078
AD
180 "$"("<"{tag}">")?"$" {
181 const char *type_name = NULL;
182 fetch_type_name (yytext + 1, &type_name, *loc)[-1] = 0;
183 obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar(");
184 obstack_quote (&obstack_for_string, type_name);
185 obstack_sgrow (&obstack_for_string, ")[");
28e52c0d
JD
186 self->is_value_used = true;
187 }
e785ccf7
JD
188 "@$" {
189 obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
bc0f5737 190 muscle_percent_define_ensure("locations", the_location, true);
e785ccf7 191 }
e9071366
AD
192}
193
194
e9071366
AD
195<*>
196{
26313726
AD
197 /* Escape M4 quoting characters in C code. */
198 [$@\[\]] obstack_escape (&obstack_for_string, yytext);
e9071366 199
26313726
AD
200 /* By default, grow the string obstack with the input. */
201 .|\n STRING_GROW;
e9071366
AD
202
203 /* End of processing. */
26313726
AD
204 <<EOF>> STRING_FINISH; return last_string;
205}
e9071366
AD
206
207%%
208
b9f1d9a4 209static inline bool
872b52bc 210is_dot_or_dash (char ch)
b9f1d9a4
AR
211{
212 return ch == '.' || ch == '-';
213}
214
215static inline bool
872b52bc 216contains_dot_or_dash (const char* p)
b9f1d9a4 217{
872b52bc
AR
218 for (; *p; ++p)
219 if (is_dot_or_dash (*p))
220 return true;
221 return false;
b9f1d9a4
AR
222}
223
872b52bc 224/* Defines a variant of a symbolic name resolution. */
b9f1d9a4
AR
225typedef struct
226{
227 /* Index in symbol list. */
ce268795 228 unsigned symbol_index;
b9f1d9a4
AR
229
230 /* Matched symbol id and loc. */
231 uniqstr id;
232 location loc;
233
872b52bc 234 /* Hiding named reference. */
b9f1d9a4
AR
235 named_ref* hidden_by;
236
872b52bc
AR
237 /* Error flags. May contain zero (no errors) or
238 a combination of VARIANT_* values. */
b9f1d9a4
AR
239 unsigned err;
240} variant;
241
872b52bc
AR
242/* Set when the variant refers to a symbol hidden
243 by an explicit symbol reference. */
244#define VARIANT_HIDDEN (1 << 0)
245
676997e5
JD
246/* Set when the variant refers to a symbol containing
247 dots or dashes. Will require explicit bracketing. */
248#define VARIANT_BAD_BRACKETING (1 << 1)
249
872b52bc
AR
250/* Set when the variant refers to a symbol which is
251 not visible from current midrule. */
676997e5 252#define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2)
872b52bc 253
9b858541 254static variant *variant_table = NULL;
b9f1d9a4
AR
255static unsigned variant_table_size = 0;
256static unsigned variant_count = 0;
257
258static variant *
ba4184ec 259variant_table_grow (void)
b9f1d9a4
AR
260{
261 ++variant_count;
262 if (variant_count > variant_table_size)
263 {
264 while (variant_count > variant_table_size)
e9690142 265 variant_table_size = 2 * variant_table_size + 3;
b9f1d9a4 266 variant_table = xnrealloc (variant_table, variant_table_size,
e9690142 267 sizeof *variant_table);
b9f1d9a4
AR
268 }
269 return &variant_table[variant_count - 1];
270}
271
13cdf208 272static void
ba4184ec 273variant_table_free (void)
13cdf208 274{
ba4184ec 275 free (variant_table);
9b858541 276 variant_table = NULL;
13cdf208
AR
277 variant_table_size = variant_count = 0;
278}
279
676997e5
JD
280static char *
281find_prefix_end (const char *prefix, char *begin, char *end)
b9f1d9a4 282{
676997e5
JD
283 char *ptr = begin;
284
285 for (; *prefix && ptr != end; ++prefix, ++ptr)
286 if (*prefix != *ptr)
287 return 0;
288
289 if (*prefix)
290 return 0;
291
292 return ptr;
b9f1d9a4
AR
293}
294
295static variant *
ba4184ec 296variant_add (uniqstr id, location id_loc, unsigned symbol_index,
e9690142 297 char *cp, char *cp_end, bool explicit_bracketing)
b9f1d9a4 298{
676997e5
JD
299 char *prefix_end;
300
301 prefix_end = find_prefix_end (id, cp, cp_end);
302 if (prefix_end &&
303 (prefix_end == cp_end ||
304 (!explicit_bracketing && is_dot_or_dash (*prefix_end))))
b9f1d9a4 305 {
872b52bc 306 variant *r = variant_table_grow ();
ce268795 307 r->symbol_index = symbol_index;
b9f1d9a4 308 r->id = id;
ba4184ec 309 r->loc = id_loc;
b9f1d9a4
AR
310 r->hidden_by = NULL;
311 r->err = 0;
312 return r;
313 }
314 else
315 return NULL;
316}
317
872b52bc 318static const char *
ba4184ec 319get_at_spec(unsigned symbol_index)
872b52bc
AR
320{
321 static char at_buf[20];
ba4184ec 322 if (symbol_index == 0)
872b52bc
AR
323 strcpy (at_buf, "$$");
324 else
ba4184ec 325 snprintf (at_buf, sizeof at_buf, "$%u", symbol_index);
872b52bc
AR
326 return at_buf;
327}
328
ce268795 329static void
ac0eca3c
TR
330show_sub_message (warnings warning,
331 const char* cp, bool explicit_bracketing,
cceb7b94 332 int midrule_rhs_index, char dollar_or_at,
a49f4904 333 unsigned indent, const variant *var)
ce268795 334{
cceb7b94 335 const char *at_spec = get_at_spec (var->symbol_index);
ce268795 336
cceb7b94 337 if (var->err == 0)
ac0eca3c 338 complain_indent (&var->loc, warning, &indent,
b999409e
TR
339 _("refers to: %c%s at %s"), dollar_or_at,
340 var->id, at_spec);
cceb7b94
AD
341 else
342 {
343 static struct obstack msg_buf;
344 const char *tail = explicit_bracketing ? "" : cp + strlen (var->id);
67411a88
PE
345 const char *id;
346 location id_loc;
347
348 if (var->hidden_by)
ee9cdb85
AD
349 {
350 id = var->hidden_by->id;
351 id_loc = var->hidden_by->loc;
352 }
67411a88 353 else
ee9cdb85
AD
354 {
355 id = var->id;
356 id_loc = var->loc;
357 }
ce268795 358
cceb7b94
AD
359 /* Create the explanation message. */
360 obstack_init (&msg_buf);
361
362 obstack_printf (&msg_buf, _("possibly meant: %c"), dollar_or_at);
363 if (contains_dot_or_dash (id))
364 obstack_printf (&msg_buf, "[%s]", id);
ce268795 365 else
cceb7b94
AD
366 obstack_sgrow (&msg_buf, id);
367 obstack_sgrow (&msg_buf, tail);
368
369 if (var->err & VARIANT_HIDDEN)
e9690142 370 {
cceb7b94
AD
371 obstack_printf (&msg_buf, _(", hiding %c"), dollar_or_at);
372 if (contains_dot_or_dash (var->id))
373 obstack_printf (&msg_buf, "[%s]", var->id);
e9690142 374 else
cceb7b94 375 obstack_sgrow (&msg_buf, var->id);
e9690142 376 obstack_sgrow (&msg_buf, tail);
cceb7b94 377 }
e9690142 378
cceb7b94
AD
379 obstack_printf (&msg_buf, _(" at %s"), at_spec);
380
381 if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
c7324354
AD
382 obstack_printf (&msg_buf,
383 _(", cannot be accessed from mid-rule action at $%d"),
384 midrule_rhs_index);
cceb7b94 385
ac0eca3c
TR
386 complain_indent (&id_loc, warning, &indent, "%s",
387 obstack_finish0 (&msg_buf));
cceb7b94 388 obstack_free (&msg_buf, 0);
ce268795
AR
389 }
390}
391
cceb7b94 392static void
ac0eca3c
TR
393show_sub_messages (warnings warning,
394 const char* cp, bool explicit_bracketing,
cceb7b94 395 int midrule_rhs_index, char dollar_or_at,
a49f4904 396 unsigned indent)
cceb7b94
AD
397{
398 unsigned i;
399
400 for (i = 0; i < variant_count; ++i)
ac0eca3c
TR
401 show_sub_message (warning | silent,
402 cp, explicit_bracketing,
cceb7b94 403 midrule_rhs_index, dollar_or_at,
a49f4904 404 indent, &variant_table[i]);
cceb7b94
AD
405}
406
872b52bc
AR
407/* Returned from "parse_ref" when the reference
408 is inappropriate. */
b9f1d9a4 409#define INVALID_REF (INT_MIN)
872b52bc
AR
410
411/* Returned from "parse_ref" when the reference
ce268795 412 points to LHS ($$) of the current rule or midrule. */
b9f1d9a4
AR
413#define LHS_REF (INT_MIN + 1)
414
676997e5
JD
415/* Parse named or positional reference. In case of positional
416 references, can return negative values for $-n "deep" stack
417 accesses. */
b9f1d9a4 418static long int
676997e5 419parse_ref (char *cp, symbol_list *rule, int rule_length,
e9690142
JD
420 int midrule_rhs_index, char *text, location text_loc,
421 char dollar_or_at)
b9f1d9a4 422{
676997e5
JD
423 symbol_list *l;
424 char *cp_end;
61bc57e5 425 bool explicit_bracketing;
872b52bc 426 unsigned i;
ce268795
AR
427 unsigned valid_variants = 0;
428 unsigned valid_variant_index = 0;
b9f1d9a4
AR
429
430 if ('$' == *cp)
431 return LHS_REF;
432
676997e5 433 if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1))))
b9f1d9a4 434 {
676997e5 435 long int num = strtol (cp, &cp, 10);
b9f1d9a4 436 if (1 - INT_MAX + rule_length <= num && num <= rule_length)
e9690142 437 return num;
b9f1d9a4 438 else
e9690142 439 {
bb8e56ff
TR
440 complain (&text_loc, complaint, _("integer out of range: %s"),
441 quote (text));
e9690142
JD
442 return INVALID_REF;
443 }
b9f1d9a4
AR
444 }
445
676997e5
JD
446 if ('[' == *cp)
447 {
448 /* Ignore the brackets. */
449 char *p;
450 for (p = ++cp; *p != ']'; ++p)
e9690142 451 continue;
676997e5
JD
452 cp_end = p;
453
454 explicit_bracketing = true;
455 }
456 else
457 {
458 /* Take all characters of the name. */
459 char* p;
460 for (p = cp; *p; ++p)
e9690142
JD
461 if (is_dot_or_dash (*p))
462 {
463 ref_tail_fields = p;
464 break;
465 }
676997e5 466 for (p = cp; *p; ++p)
e9690142 467 continue;
676997e5
JD
468 cp_end = p;
469
470 explicit_bracketing = false;
471 }
b9f1d9a4
AR
472
473 /* Add all relevant variants. */
872b52bc 474 {
ba4184ec 475 unsigned symbol_index;
872b52bc 476 variant_count = 0;
ba4184ec
AR
477 for (symbol_index = 0, l = rule; !symbol_list_null (l);
478 ++symbol_index, l = l->next)
872b52bc 479 {
e9690142
JD
480 variant *var;
481 if (l->content_type != SYMLIST_SYMBOL)
482 continue;
b9f1d9a4 483
e9690142 484 var = variant_add (l->content.sym->tag, l->sym_loc,
676997e5 485 symbol_index, cp, cp_end, explicit_bracketing);
e9690142
JD
486 if (var && l->named_ref)
487 var->hidden_by = l->named_ref;
b9f1d9a4 488
e9690142
JD
489 if (l->named_ref)
490 variant_add (l->named_ref->id, l->named_ref->loc,
676997e5 491 symbol_index, cp, cp_end, explicit_bracketing);
872b52bc
AR
492 }
493 }
b9f1d9a4
AR
494
495 /* Check errors. */
b9f1d9a4
AR
496 for (i = 0; i < variant_count; ++i)
497 {
ba4184ec 498 variant *var = &variant_table[i];
ce268795 499 unsigned symbol_index = var->symbol_index;
b9f1d9a4
AR
500
501 /* Check visibility from mid-rule actions. */
872b52bc 502 if (midrule_rhs_index != 0
e9690142 503 && (symbol_index == 0 || midrule_rhs_index < symbol_index))
ce268795 504 var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
b9f1d9a4 505
676997e5
JD
506 /* Check correct bracketing. */
507 if (!explicit_bracketing && contains_dot_or_dash (var->id))
508 var->err |= VARIANT_BAD_BRACKETING;
509
b9f1d9a4 510 /* Check using of hidden symbols. */
ba4184ec 511 if (var->hidden_by)
ce268795 512 var->err |= VARIANT_HIDDEN;
b9f1d9a4 513
ba4184ec 514 if (!var->err)
ce268795
AR
515 {
516 valid_variant_index = i;
517 ++valid_variants;
518 }
b9f1d9a4
AR
519 }
520
ce268795 521 switch (valid_variants)
b9f1d9a4 522 {
ce268795 523 case 0:
f64e406b 524 {
676997e5
JD
525 unsigned len = (explicit_bracketing || !ref_tail_fields) ?
526 cp_end - cp : ref_tail_fields - cp;
66381412 527 unsigned indent = 0;
f64e406b 528
b999409e
TR
529 complain_indent (&text_loc, complaint, &indent,
530 _("invalid reference: %s"), quote (text));
66381412 531 indent += SUB_INDENT;
5c9efc75
JD
532 if (len == 0)
533 {
534 location sym_loc = text_loc;
535 sym_loc.start.column += 1;
536 sym_loc.end = sym_loc.start;
b999409e
TR
537 complain_indent (&sym_loc, complaint, &indent,
538 _("syntax error after '%c', expecting integer, "
539 "letter, '_', '[', or '$'"),
540 dollar_or_at);
5c9efc75
JD
541 }
542 else if (midrule_rhs_index)
b999409e
TR
543 complain_indent (&rule->location, complaint, &indent,
544 _("symbol not found in production before $%d: "
545 "%.*s"),
546 midrule_rhs_index, len, cp);
f64e406b 547 else
b999409e
TR
548 complain_indent (&rule->location, complaint, &indent,
549 _("symbol not found in production: %.*s"),
550 len, cp);
f64e406b
AR
551
552 if (variant_count > 0)
ac0eca3c
TR
553 show_sub_messages (complaint,
554 cp, explicit_bracketing, midrule_rhs_index,
a49f4904 555 dollar_or_at, indent);
f64e406b
AR
556 return INVALID_REF;
557 }
ce268795
AR
558 case 1:
559 {
66381412 560 unsigned indent = 0;
ce268795
AR
561 if (variant_count > 1)
562 {
b999409e
TR
563 complain_indent (&text_loc, Wother, &indent,
564 _("misleading reference: %s"), quote (text));
ac0eca3c
TR
565 show_sub_messages (Wother,
566 cp, explicit_bracketing, midrule_rhs_index,
a49f4904 567 dollar_or_at, indent + SUB_INDENT);
ce268795
AR
568 }
569 {
570 unsigned symbol_index =
571 variant_table[valid_variant_index].symbol_index;
572 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
573 }
574 }
575 case 2:
576 default:
66381412
AR
577 {
578 unsigned indent = 0;
b999409e
TR
579 complain_indent (&text_loc, complaint, &indent,
580 _("ambiguous reference: %s"), quote (text));
ac0eca3c
TR
581 show_sub_messages (complaint,
582 cp, explicit_bracketing, midrule_rhs_index,
a49f4904 583 dollar_or_at, indent + SUB_INDENT);
66381412
AR
584 return INVALID_REF;
585 }
b9f1d9a4 586 }
b9f1d9a4
AR
587}
588
e9071366
AD
589/* Keeps track of the maximum number of semantic values to the left of
590 a handle (those referenced by $0, $-1, etc.) are required by the
591 semantic actions of this grammar. */
592int max_left_semantic_context = 0;
593
594
65a99eca
AD
595/* If CP points to a typename (i.e., <.*?>), set TYPE_NAME to its
596 beginning (i.e., after the opening "<", and return the pointer
597 immediately after it. */
598
599static
600char *
601fetch_type_name (char *cp, char const **type_name,
602 location dollar_loc)
603{
604 if (*cp == '<')
605 {
606 *type_name = ++cp;
cb8d8bb9
AD
607 /* Series of non-'>' or "->". */
608 while (*cp != '>' || cp[-1] == '-')
4323e0da 609 ++cp;
65a99eca
AD
610
611 /* The '>' symbol will be later replaced by '\0'. Original
4323e0da 612 'text' is needed for error messages. */
65a99eca
AD
613 ++cp;
614 if (untyped_var_seen)
bb8e56ff
TR
615 complain (&dollar_loc, complaint,
616 _("explicit type given in untyped grammar"));
65a99eca
AD
617 tag_seen = true;
618 }
619 return cp;
620}
621
e9071366 622/*------------------------------------------------------------------.
ae93e4e4 623| TEXT is pointing to a wannabee semantic value (i.e., a '$'). |
e9071366 624| |
676997e5 625| Possible inputs: $[<TYPENAME>]($|integer) |
e9071366
AD
626| |
627| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
628`------------------------------------------------------------------*/
629
630static void
676997e5 631handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 632{
28e52c0d 633 char const *type_name = NULL;
e9071366 634 char *cp = text + 1;
ffa4ba3a 635 symbol_list *effective_rule;
872b52bc
AR
636 int effective_rule_length;
637 int n;
ffa4ba3a
JD
638
639 if (rule->midrule_parent_rule)
640 {
641 effective_rule = rule->midrule_parent_rule;
642 effective_rule_length = rule->midrule_parent_rhs_index - 1;
643 }
644 else
645 {
646 effective_rule = rule;
647 effective_rule_length = symbol_list_length (rule->next);
648 }
e9071366
AD
649
650 /* Get the type name if explicit. */
65a99eca 651 cp = fetch_type_name (cp, &type_name, dollar_loc);
e9071366 652
872b52bc 653 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 654 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
b9f1d9a4 655
65a99eca
AD
656 /* End type_name. */
657 if (type_name)
658 cp[-1] = '\0';
b9f1d9a4
AR
659
660 switch (n)
e9071366 661 {
b9f1d9a4
AR
662 case INVALID_REF:
663 break;
664
665 case LHS_REF:
e9071366 666 if (!type_name)
e9690142 667 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
668
669 if (!type_name)
e9690142
JD
670 {
671 if (union_seen | tag_seen)
672 {
673 if (rule->midrule_parent_rule)
bb8e56ff 674 complain (&dollar_loc, complaint,
4a9cd8f2 675 _("$$ for the midrule at $%d of %s"
e9690142
JD
676 " has no declared type"),
677 rule->midrule_parent_rhs_index,
4a9cd8f2 678 quote (effective_rule->content.sym->tag));
e9690142 679 else
bb8e56ff
TR
680 complain (&dollar_loc, complaint,
681 _("$$ of %s has no declared type"),
682 quote (rule->content.sym->tag));
e9690142
JD
683 }
684 else
685 untyped_var_seen = true;
e9690142 686 }
ddc8ede1 687
8617d87e
AD
688 obstack_sgrow (&obstack_for_string, "]b4_lhs_value(");
689 obstack_quote (&obstack_for_string, type_name);
690 obstack_sgrow (&obstack_for_string, ")[");
f6857bbf 691 rule->action_props.is_value_used = true;
b9f1d9a4
AR
692 break;
693
694 default:
695 if (max_left_semantic_context < 1 - n)
e9690142 696 max_left_semantic_context = 1 - n;
b9f1d9a4 697 if (!type_name && 0 < n)
e9690142
JD
698 type_name =
699 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
b9f1d9a4 700 if (!type_name)
e9690142
JD
701 {
702 if (union_seen | tag_seen)
bb8e56ff
TR
703 complain (&dollar_loc, complaint,
704 _("$%s of %s has no declared type"), cp,
705 quote (effective_rule->content.sym->tag));
e9690142
JD
706 else
707 untyped_var_seen = true;
e9690142 708 }
b9f1d9a4 709
aaf63e45 710 obstack_printf (&obstack_for_string,
4323e0da 711 "]b4_rhs_value(%d, %d, ", effective_rule_length, n);
8617d87e
AD
712 obstack_quote (&obstack_for_string, type_name);
713 obstack_sgrow (&obstack_for_string, ")[");
b9f1d9a4 714 if (n > 0)
e9690142
JD
715 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
716 true;
b9f1d9a4 717 break;
e9071366
AD
718 }
719}
720
721
722/*------------------------------------------------------.
ae93e4e4 723| TEXT is a location token (i.e., a '@...'). Output to |
e9071366
AD
724| OBSTACK_FOR_STRING a reference to this location. |
725`------------------------------------------------------*/
726
727static void
676997e5 728handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366 729{
676997e5
JD
730 char *cp = text + 1;
731 symbol_list *effective_rule;
872b52bc
AR
732 int effective_rule_length;
733 int n;
b9f1d9a4
AR
734
735 if (rule->midrule_parent_rule)
736 {
737 effective_rule = rule->midrule_parent_rule;
738 effective_rule_length = rule->midrule_parent_rhs_index - 1;
739 }
740 else
741 {
742 effective_rule = rule;
743 effective_rule_length = symbol_list_length (rule->next);
744 }
ffa4ba3a 745
bc0f5737 746 muscle_percent_define_ensure("locations", at_loc, true);
e9071366 747
872b52bc 748 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 749 rule->midrule_parent_rhs_index, text, at_loc, '@');
b9f1d9a4 750 switch (n)
e9071366 751 {
b9f1d9a4
AR
752 case INVALID_REF:
753 break;
e9071366 754
b9f1d9a4
AR
755 case LHS_REF:
756 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
757 break;
758
759 default:
aaf63e45 760 obstack_printf (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
e9690142 761 effective_rule_length, n);
b9f1d9a4 762 break;
e9071366
AD
763 }
764}
765
766
767/*-------------------------.
768| Initialize the scanner. |
769`-------------------------*/
770
28e52c0d 771/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 772 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 773
eb095650 774static char const *
28e52c0d 775translate_action (code_props *self, int sc_context)
e9071366 776{
2ce4ed68 777 char *res;
e9071366
AD
778 static bool initialized = false;
779 if (!initialized)
780 {
781 obstack_init (&obstack_for_string);
e9071366
AD
782 yy_flex_debug = 0;
783 initialized = true;
784 }
785
28e52c0d
JD
786 loc->start = loc->end = self->location.start;
787 yy_switch_to_buffer (yy_scan_string (self->code));
788 res = code_lex (self, sc_context);
e9071366
AD
789 yy_delete_buffer (YY_CURRENT_BUFFER);
790
791 return res;
792}
793
28e52c0d
JD
794/*------------------------------------------------------------------------.
795| Implementation of the public interface as documented in "scan-code.h". |
796`------------------------------------------------------------------------*/
797
798void
799code_props_none_init (code_props *self)
76290368 800{
28e52c0d 801 *self = code_props_none;
76290368
JD
802}
803
70946cff 804code_props code_props_none = CODE_PROPS_NONE_INIT;
28e52c0d
JD
805
806void
872b52bc 807code_props_plain_init (code_props *self, char const *code,
e9690142 808 location code_loc)
76290368 809{
ea9a35c6 810 code_props_none_init (self);
28e52c0d
JD
811 self->kind = CODE_PROPS_PLAIN;
812 self->code = code;
813 self->location = code_loc;
76290368
JD
814}
815
28e52c0d
JD
816void
817code_props_symbol_action_init (code_props *self, char const *code,
818 location code_loc)
e9071366 819{
ea9a35c6 820 code_props_none_init (self);
28e52c0d
JD
821 self->kind = CODE_PROPS_SYMBOL_ACTION;
822 self->code = code;
823 self->location = code_loc;
e9071366
AD
824}
825
28e52c0d
JD
826void
827code_props_rule_action_init (code_props *self, char const *code,
b9f1d9a4 828 location code_loc, symbol_list *rule,
e9690142 829 named_ref *name, bool is_predicate)
28e52c0d 830{
ea9a35c6 831 code_props_none_init (self);
28e52c0d
JD
832 self->kind = CODE_PROPS_RULE_ACTION;
833 self->code = code;
834 self->location = code_loc;
28e52c0d 835 self->rule = rule;
ba4184ec 836 self->named_ref = name;
ca2a6d15 837 self->is_predicate = is_predicate;
28e52c0d
JD
838}
839
840void
841code_props_translate_code (code_props *self)
842{
843 switch (self->kind)
844 {
845 case CODE_PROPS_NONE:
846 break;
847 case CODE_PROPS_PLAIN:
848 self->code = translate_action (self, INITIAL);
849 break;
850 case CODE_PROPS_SYMBOL_ACTION:
851 self->code = translate_action (self, SC_SYMBOL_ACTION);
852 break;
853 case CODE_PROPS_RULE_ACTION:
854 self->code = translate_action (self, SC_RULE_ACTION);
855 break;
856 }
857}
858
859void
860code_scanner_last_string_free (void)
861{
862 STRING_FREE;
863}
e9071366
AD
864
865void
866code_scanner_free (void)
867{
868 obstack_free (&obstack_for_string, 0);
13cdf208
AR
869 variant_table_free ();
870
e9071366 871 /* Reclaim Flex's buffers. */
580b8926 872 yylex_destroy ();
e9071366 873}