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