]> git.saurik.com Git - bison.git/blame - src/scan-code.l
muscle: enforce definition syntax for keyword variables
[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);
345 const char *id = var->hidden_by ? var->hidden_by->id : var->id;
346 location id_loc = var->hidden_by ? var->hidden_by->loc : var->loc;
ce268795 347
cceb7b94
AD
348 /* Create the explanation message. */
349 obstack_init (&msg_buf);
350
351 obstack_printf (&msg_buf, _("possibly meant: %c"), dollar_or_at);
352 if (contains_dot_or_dash (id))
353 obstack_printf (&msg_buf, "[%s]", id);
ce268795 354 else
cceb7b94
AD
355 obstack_sgrow (&msg_buf, id);
356 obstack_sgrow (&msg_buf, tail);
357
358 if (var->err & VARIANT_HIDDEN)
e9690142 359 {
cceb7b94
AD
360 obstack_printf (&msg_buf, _(", hiding %c"), dollar_or_at);
361 if (contains_dot_or_dash (var->id))
362 obstack_printf (&msg_buf, "[%s]", var->id);
e9690142 363 else
cceb7b94 364 obstack_sgrow (&msg_buf, var->id);
e9690142 365 obstack_sgrow (&msg_buf, tail);
cceb7b94 366 }
e9690142 367
cceb7b94
AD
368 obstack_printf (&msg_buf, _(" at %s"), at_spec);
369
370 if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
c7324354
AD
371 obstack_printf (&msg_buf,
372 _(", cannot be accessed from mid-rule action at $%d"),
373 midrule_rhs_index);
cceb7b94 374
ac0eca3c
TR
375 complain_indent (&id_loc, warning, &indent, "%s",
376 obstack_finish0 (&msg_buf));
cceb7b94 377 obstack_free (&msg_buf, 0);
ce268795
AR
378 }
379}
380
cceb7b94 381static void
ac0eca3c
TR
382show_sub_messages (warnings warning,
383 const char* cp, bool explicit_bracketing,
cceb7b94 384 int midrule_rhs_index, char dollar_or_at,
a49f4904 385 unsigned indent)
cceb7b94
AD
386{
387 unsigned i;
388
389 for (i = 0; i < variant_count; ++i)
ac0eca3c
TR
390 show_sub_message (warning | silent,
391 cp, explicit_bracketing,
cceb7b94 392 midrule_rhs_index, dollar_or_at,
a49f4904 393 indent, &variant_table[i]);
cceb7b94
AD
394}
395
872b52bc
AR
396/* Returned from "parse_ref" when the reference
397 is inappropriate. */
b9f1d9a4 398#define INVALID_REF (INT_MIN)
872b52bc
AR
399
400/* Returned from "parse_ref" when the reference
ce268795 401 points to LHS ($$) of the current rule or midrule. */
b9f1d9a4
AR
402#define LHS_REF (INT_MIN + 1)
403
676997e5
JD
404/* Parse named or positional reference. In case of positional
405 references, can return negative values for $-n "deep" stack
406 accesses. */
b9f1d9a4 407static long int
676997e5 408parse_ref (char *cp, symbol_list *rule, int rule_length,
e9690142
JD
409 int midrule_rhs_index, char *text, location text_loc,
410 char dollar_or_at)
b9f1d9a4 411{
676997e5
JD
412 symbol_list *l;
413 char *cp_end;
61bc57e5 414 bool explicit_bracketing;
872b52bc 415 unsigned i;
ce268795
AR
416 unsigned valid_variants = 0;
417 unsigned valid_variant_index = 0;
b9f1d9a4
AR
418
419 if ('$' == *cp)
420 return LHS_REF;
421
676997e5 422 if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1))))
b9f1d9a4 423 {
676997e5 424 long int num = strtol (cp, &cp, 10);
b9f1d9a4 425 if (1 - INT_MAX + rule_length <= num && num <= rule_length)
e9690142 426 return num;
b9f1d9a4 427 else
e9690142 428 {
bb8e56ff
TR
429 complain (&text_loc, complaint, _("integer out of range: %s"),
430 quote (text));
e9690142
JD
431 return INVALID_REF;
432 }
b9f1d9a4
AR
433 }
434
676997e5
JD
435 if ('[' == *cp)
436 {
437 /* Ignore the brackets. */
438 char *p;
439 for (p = ++cp; *p != ']'; ++p)
e9690142 440 continue;
676997e5
JD
441 cp_end = p;
442
443 explicit_bracketing = true;
444 }
445 else
446 {
447 /* Take all characters of the name. */
448 char* p;
449 for (p = cp; *p; ++p)
e9690142
JD
450 if (is_dot_or_dash (*p))
451 {
452 ref_tail_fields = p;
453 break;
454 }
676997e5 455 for (p = cp; *p; ++p)
e9690142 456 continue;
676997e5
JD
457 cp_end = p;
458
459 explicit_bracketing = false;
460 }
b9f1d9a4
AR
461
462 /* Add all relevant variants. */
872b52bc 463 {
ba4184ec 464 unsigned symbol_index;
872b52bc 465 variant_count = 0;
ba4184ec
AR
466 for (symbol_index = 0, l = rule; !symbol_list_null (l);
467 ++symbol_index, l = l->next)
872b52bc 468 {
e9690142
JD
469 variant *var;
470 if (l->content_type != SYMLIST_SYMBOL)
471 continue;
b9f1d9a4 472
e9690142 473 var = variant_add (l->content.sym->tag, l->sym_loc,
676997e5 474 symbol_index, cp, cp_end, explicit_bracketing);
e9690142
JD
475 if (var && l->named_ref)
476 var->hidden_by = l->named_ref;
b9f1d9a4 477
e9690142
JD
478 if (l->named_ref)
479 variant_add (l->named_ref->id, l->named_ref->loc,
676997e5 480 symbol_index, cp, cp_end, explicit_bracketing);
872b52bc
AR
481 }
482 }
b9f1d9a4
AR
483
484 /* Check errors. */
b9f1d9a4
AR
485 for (i = 0; i < variant_count; ++i)
486 {
ba4184ec 487 variant *var = &variant_table[i];
ce268795 488 unsigned symbol_index = var->symbol_index;
b9f1d9a4
AR
489
490 /* Check visibility from mid-rule actions. */
872b52bc 491 if (midrule_rhs_index != 0
e9690142 492 && (symbol_index == 0 || midrule_rhs_index < symbol_index))
ce268795 493 var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
b9f1d9a4 494
676997e5
JD
495 /* Check correct bracketing. */
496 if (!explicit_bracketing && contains_dot_or_dash (var->id))
497 var->err |= VARIANT_BAD_BRACKETING;
498
b9f1d9a4 499 /* Check using of hidden symbols. */
ba4184ec 500 if (var->hidden_by)
ce268795 501 var->err |= VARIANT_HIDDEN;
b9f1d9a4 502
ba4184ec 503 if (!var->err)
ce268795
AR
504 {
505 valid_variant_index = i;
506 ++valid_variants;
507 }
b9f1d9a4
AR
508 }
509
ce268795 510 switch (valid_variants)
b9f1d9a4 511 {
ce268795 512 case 0:
f64e406b 513 {
676997e5
JD
514 unsigned len = (explicit_bracketing || !ref_tail_fields) ?
515 cp_end - cp : ref_tail_fields - cp;
66381412 516 unsigned indent = 0;
f64e406b 517
b999409e
TR
518 complain_indent (&text_loc, complaint, &indent,
519 _("invalid reference: %s"), quote (text));
66381412 520 indent += SUB_INDENT;
5c9efc75
JD
521 if (len == 0)
522 {
523 location sym_loc = text_loc;
524 sym_loc.start.column += 1;
525 sym_loc.end = sym_loc.start;
b999409e
TR
526 complain_indent (&sym_loc, complaint, &indent,
527 _("syntax error after '%c', expecting integer, "
528 "letter, '_', '[', or '$'"),
529 dollar_or_at);
5c9efc75
JD
530 }
531 else if (midrule_rhs_index)
b999409e
TR
532 complain_indent (&rule->location, complaint, &indent,
533 _("symbol not found in production before $%d: "
534 "%.*s"),
535 midrule_rhs_index, len, cp);
f64e406b 536 else
b999409e
TR
537 complain_indent (&rule->location, complaint, &indent,
538 _("symbol not found in production: %.*s"),
539 len, cp);
f64e406b
AR
540
541 if (variant_count > 0)
ac0eca3c
TR
542 show_sub_messages (complaint,
543 cp, explicit_bracketing, midrule_rhs_index,
a49f4904 544 dollar_or_at, indent);
f64e406b
AR
545 return INVALID_REF;
546 }
ce268795
AR
547 case 1:
548 {
66381412 549 unsigned indent = 0;
ce268795
AR
550 if (variant_count > 1)
551 {
b999409e
TR
552 complain_indent (&text_loc, Wother, &indent,
553 _("misleading reference: %s"), quote (text));
ac0eca3c
TR
554 show_sub_messages (Wother,
555 cp, explicit_bracketing, midrule_rhs_index,
a49f4904 556 dollar_or_at, indent + SUB_INDENT);
ce268795
AR
557 }
558 {
559 unsigned symbol_index =
560 variant_table[valid_variant_index].symbol_index;
561 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
562 }
563 }
564 case 2:
565 default:
66381412
AR
566 {
567 unsigned indent = 0;
b999409e
TR
568 complain_indent (&text_loc, complaint, &indent,
569 _("ambiguous reference: %s"), quote (text));
ac0eca3c
TR
570 show_sub_messages (complaint,
571 cp, explicit_bracketing, midrule_rhs_index,
a49f4904 572 dollar_or_at, indent + SUB_INDENT);
66381412
AR
573 return INVALID_REF;
574 }
b9f1d9a4
AR
575 }
576
ce268795 577 /* Not reachable. */
b9f1d9a4
AR
578 return INVALID_REF;
579}
580
e9071366
AD
581/* Keeps track of the maximum number of semantic values to the left of
582 a handle (those referenced by $0, $-1, etc.) are required by the
583 semantic actions of this grammar. */
584int max_left_semantic_context = 0;
585
586
65a99eca
AD
587/* If CP points to a typename (i.e., <.*?>), set TYPE_NAME to its
588 beginning (i.e., after the opening "<", and return the pointer
589 immediately after it. */
590
591static
592char *
593fetch_type_name (char *cp, char const **type_name,
594 location dollar_loc)
595{
596 if (*cp == '<')
597 {
598 *type_name = ++cp;
cb8d8bb9
AD
599 /* Series of non-'>' or "->". */
600 while (*cp != '>' || cp[-1] == '-')
4323e0da 601 ++cp;
65a99eca
AD
602
603 /* The '>' symbol will be later replaced by '\0'. Original
4323e0da 604 'text' is needed for error messages. */
65a99eca
AD
605 ++cp;
606 if (untyped_var_seen)
bb8e56ff
TR
607 complain (&dollar_loc, complaint,
608 _("explicit type given in untyped grammar"));
65a99eca
AD
609 tag_seen = true;
610 }
611 return cp;
612}
613
e9071366 614/*------------------------------------------------------------------.
ae93e4e4 615| TEXT is pointing to a wannabee semantic value (i.e., a '$'). |
e9071366 616| |
676997e5 617| Possible inputs: $[<TYPENAME>]($|integer) |
e9071366
AD
618| |
619| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
620`------------------------------------------------------------------*/
621
622static void
676997e5 623handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 624{
28e52c0d 625 char const *type_name = NULL;
e9071366 626 char *cp = text + 1;
ffa4ba3a 627 symbol_list *effective_rule;
872b52bc
AR
628 int effective_rule_length;
629 int n;
ffa4ba3a
JD
630
631 if (rule->midrule_parent_rule)
632 {
633 effective_rule = rule->midrule_parent_rule;
634 effective_rule_length = rule->midrule_parent_rhs_index - 1;
635 }
636 else
637 {
638 effective_rule = rule;
639 effective_rule_length = symbol_list_length (rule->next);
640 }
e9071366
AD
641
642 /* Get the type name if explicit. */
65a99eca 643 cp = fetch_type_name (cp, &type_name, dollar_loc);
e9071366 644
872b52bc 645 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 646 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
b9f1d9a4 647
65a99eca
AD
648 /* End type_name. */
649 if (type_name)
650 cp[-1] = '\0';
b9f1d9a4
AR
651
652 switch (n)
e9071366 653 {
b9f1d9a4
AR
654 case INVALID_REF:
655 break;
656
657 case LHS_REF:
e9071366 658 if (!type_name)
e9690142 659 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
660
661 if (!type_name)
e9690142
JD
662 {
663 if (union_seen | tag_seen)
664 {
665 if (rule->midrule_parent_rule)
bb8e56ff 666 complain (&dollar_loc, complaint,
4a9cd8f2 667 _("$$ for the midrule at $%d of %s"
e9690142
JD
668 " has no declared type"),
669 rule->midrule_parent_rhs_index,
4a9cd8f2 670 quote (effective_rule->content.sym->tag));
e9690142 671 else
bb8e56ff
TR
672 complain (&dollar_loc, complaint,
673 _("$$ of %s has no declared type"),
674 quote (rule->content.sym->tag));
e9690142
JD
675 }
676 else
677 untyped_var_seen = true;
e9690142 678 }
ddc8ede1 679
8617d87e
AD
680 obstack_sgrow (&obstack_for_string, "]b4_lhs_value(");
681 obstack_quote (&obstack_for_string, type_name);
682 obstack_sgrow (&obstack_for_string, ")[");
f6857bbf 683 rule->action_props.is_value_used = true;
b9f1d9a4
AR
684 break;
685
686 default:
687 if (max_left_semantic_context < 1 - n)
e9690142 688 max_left_semantic_context = 1 - n;
b9f1d9a4 689 if (!type_name && 0 < n)
e9690142
JD
690 type_name =
691 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
b9f1d9a4 692 if (!type_name)
e9690142
JD
693 {
694 if (union_seen | tag_seen)
bb8e56ff
TR
695 complain (&dollar_loc, complaint,
696 _("$%s of %s has no declared type"), cp,
697 quote (effective_rule->content.sym->tag));
e9690142
JD
698 else
699 untyped_var_seen = true;
e9690142 700 }
b9f1d9a4 701
aaf63e45 702 obstack_printf (&obstack_for_string,
4323e0da 703 "]b4_rhs_value(%d, %d, ", effective_rule_length, n);
8617d87e
AD
704 obstack_quote (&obstack_for_string, type_name);
705 obstack_sgrow (&obstack_for_string, ")[");
b9f1d9a4 706 if (n > 0)
e9690142
JD
707 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
708 true;
b9f1d9a4 709 break;
e9071366
AD
710 }
711}
712
713
714/*------------------------------------------------------.
ae93e4e4 715| TEXT is a location token (i.e., a '@...'). Output to |
e9071366
AD
716| OBSTACK_FOR_STRING a reference to this location. |
717`------------------------------------------------------*/
718
719static void
676997e5 720handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366 721{
676997e5
JD
722 char *cp = text + 1;
723 symbol_list *effective_rule;
872b52bc
AR
724 int effective_rule_length;
725 int n;
b9f1d9a4
AR
726
727 if (rule->midrule_parent_rule)
728 {
729 effective_rule = rule->midrule_parent_rule;
730 effective_rule_length = rule->midrule_parent_rhs_index - 1;
731 }
732 else
733 {
734 effective_rule = rule;
735 effective_rule_length = symbol_list_length (rule->next);
736 }
ffa4ba3a 737
bc0f5737 738 muscle_percent_define_ensure("locations", at_loc, true);
e9071366 739
872b52bc 740 n = parse_ref (cp, effective_rule, effective_rule_length,
e9690142 741 rule->midrule_parent_rhs_index, text, at_loc, '@');
b9f1d9a4 742 switch (n)
e9071366 743 {
b9f1d9a4
AR
744 case INVALID_REF:
745 break;
e9071366 746
b9f1d9a4
AR
747 case LHS_REF:
748 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
749 break;
750
751 default:
aaf63e45 752 obstack_printf (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
e9690142 753 effective_rule_length, n);
b9f1d9a4 754 break;
e9071366
AD
755 }
756}
757
758
759/*-------------------------.
760| Initialize the scanner. |
761`-------------------------*/
762
28e52c0d 763/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 764 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 765
eb095650 766static char const *
28e52c0d 767translate_action (code_props *self, int sc_context)
e9071366 768{
2ce4ed68 769 char *res;
e9071366
AD
770 static bool initialized = false;
771 if (!initialized)
772 {
773 obstack_init (&obstack_for_string);
e9071366
AD
774 yy_flex_debug = 0;
775 initialized = true;
776 }
777
28e52c0d
JD
778 loc->start = loc->end = self->location.start;
779 yy_switch_to_buffer (yy_scan_string (self->code));
780 res = code_lex (self, sc_context);
e9071366
AD
781 yy_delete_buffer (YY_CURRENT_BUFFER);
782
783 return res;
784}
785
28e52c0d
JD
786/*------------------------------------------------------------------------.
787| Implementation of the public interface as documented in "scan-code.h". |
788`------------------------------------------------------------------------*/
789
790void
791code_props_none_init (code_props *self)
76290368 792{
28e52c0d 793 *self = code_props_none;
76290368
JD
794}
795
70946cff 796code_props code_props_none = CODE_PROPS_NONE_INIT;
28e52c0d
JD
797
798void
872b52bc 799code_props_plain_init (code_props *self, char const *code,
e9690142 800 location code_loc)
76290368 801{
ea9a35c6 802 code_props_none_init (self);
28e52c0d
JD
803 self->kind = CODE_PROPS_PLAIN;
804 self->code = code;
805 self->location = code_loc;
76290368
JD
806}
807
28e52c0d
JD
808void
809code_props_symbol_action_init (code_props *self, char const *code,
810 location code_loc)
e9071366 811{
ea9a35c6 812 code_props_none_init (self);
28e52c0d
JD
813 self->kind = CODE_PROPS_SYMBOL_ACTION;
814 self->code = code;
815 self->location = code_loc;
e9071366
AD
816}
817
28e52c0d
JD
818void
819code_props_rule_action_init (code_props *self, char const *code,
b9f1d9a4 820 location code_loc, symbol_list *rule,
e9690142 821 named_ref *name, bool is_predicate)
28e52c0d 822{
ea9a35c6 823 code_props_none_init (self);
28e52c0d
JD
824 self->kind = CODE_PROPS_RULE_ACTION;
825 self->code = code;
826 self->location = code_loc;
28e52c0d 827 self->rule = rule;
ba4184ec 828 self->named_ref = name;
ca2a6d15 829 self->is_predicate = is_predicate;
28e52c0d
JD
830}
831
832void
833code_props_translate_code (code_props *self)
834{
835 switch (self->kind)
836 {
837 case CODE_PROPS_NONE:
838 break;
839 case CODE_PROPS_PLAIN:
840 self->code = translate_action (self, INITIAL);
841 break;
842 case CODE_PROPS_SYMBOL_ACTION:
843 self->code = translate_action (self, SC_SYMBOL_ACTION);
844 break;
845 case CODE_PROPS_RULE_ACTION:
846 self->code = translate_action (self, SC_RULE_ACTION);
847 break;
848 }
849}
850
851void
852code_scanner_last_string_free (void)
853{
854 STRING_FREE;
855}
e9071366
AD
856
857void
858code_scanner_free (void)
859{
860 obstack_free (&obstack_for_string, 0);
13cdf208
AR
861 variant_table_free ();
862
e9071366 863 /* Reclaim Flex's buffers. */
580b8926 864 yylex_destroy ();
e9071366 865}