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