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