]> git.saurik.com Git - bison.git/blame - src/scan-code.l
maint: run "make update-copyright"
[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. */
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 *
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 ();
ba4184ec 389 r->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
411/* Returned from "parse_ref" when the reference
412 is inappropriate. */
b9f1d9a4 413#define INVALID_REF (INT_MIN)
872b52bc
AR
414
415/* Returned from "parse_ref" when the reference
416 points to LHS ($$) of the current rule. */
b9f1d9a4
AR
417#define LHS_REF (INT_MIN + 1)
418
872b52bc
AR
419/* Parse named or positional reference. In case of positional
420 references, can return negative values for $-n "deep" stack
421 accesses. */
b9f1d9a4 422static long int
872b52bc 423parse_ref (char *cp, symbol_list *rule, int rule_length,
ba4184ec 424 int midrule_rhs_index, char *text, location text_loc,
872b52bc 425 char dollar_or_at)
b9f1d9a4
AR
426{
427 symbol_list *l;
428 char *cp_end;
429 bool exact_mode;
430 bool has_error;
431 bool has_valid;
872b52bc 432 unsigned i;
b9f1d9a4
AR
433
434 if ('$' == *cp)
435 return LHS_REF;
436
872b52bc 437 if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1))))
b9f1d9a4
AR
438 {
439 long int num = strtol (cp, &cp, 10);
440 if (1 - INT_MAX + rule_length <= num && num <= rule_length)
441 return num;
442 else
443 {
ba4184ec
AR
444 complain_at (text_loc, _("integer out of range: %s"),
445 quote (text));
b9f1d9a4
AR
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 478 {
ba4184ec 479 unsigned symbol_index;
872b52bc 480 variant_count = 0;
ba4184ec
AR
481 for (symbol_index = 0, l = rule; !symbol_list_null (l);
482 ++symbol_index, l = l->next)
872b52bc 483 {
ba4184ec 484 variant *var;
872b52bc
AR
485 if (l->content_type != SYMLIST_SYMBOL)
486 continue;
b9f1d9a4 487
ba4184ec
AR
488 var = variant_add (l->content.sym->tag, l->sym_loc,
489 symbol_index, cp, cp_end, exact_mode);
490 if (var && l->named_ref)
491 var->hidden_by = l->named_ref;
b9f1d9a4 492
872b52bc 493 if (l->named_ref)
ba4184ec
AR
494 variant_add (l->named_ref->id, l->named_ref->loc,
495 symbol_index, cp, cp_end, exact_mode);
872b52bc
AR
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 {
ba4184ec
AR
504 variant *var = &variant_table[i];
505 unsigned symbol_index = var->index;
b9f1d9a4
AR
506
507 /* Check visibility from mid-rule actions. */
872b52bc 508 if (midrule_rhs_index != 0
ba4184ec 509 && (symbol_index == 0 || midrule_rhs_index < symbol_index))
b9f1d9a4 510 {
ba4184ec 511 var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
b9f1d9a4
AR
512 has_error = true;
513 }
514
515 /* Check correct bracketing. */
ba4184ec 516 if (!exact_mode && contains_dot_or_dash (var->id))
b9f1d9a4 517 {
ba4184ec 518 var->err |= VARIANT_BAD_BRACKETING;
b9f1d9a4
AR
519 has_error = true;
520 }
521
522 /* Check using of hidden symbols. */
ba4184ec 523 if (var->hidden_by)
b9f1d9a4 524 {
ba4184ec 525 var->err |= VARIANT_HIDDEN;
b9f1d9a4
AR
526 has_error = true;
527 }
528
ba4184ec 529 if (!var->err)
b9f1d9a4
AR
530 has_valid = true;
531 }
532
533 if (variant_count == 1 && has_valid)
534 {
535 /* The only "good" case is here. */
ba4184ec
AR
536 unsigned symbol_index = variant_table[0].index;
537 if (symbol_index == midrule_rhs_index)
b9f1d9a4
AR
538 return LHS_REF;
539 else
ba4184ec 540 return symbol_index;
b9f1d9a4
AR
541 }
542
543 /* Start complaining. */
544
545 if (variant_count == 0)
ba4184ec 546 complain_at (text_loc, _("invalid reference: %s, symbol not found"),
b9f1d9a4
AR
547 quote (text));
548 else if (variant_count > 1 && !has_error)
ba4184ec 549 complain_at (text_loc, _("ambiguous reference: %s"),
b9f1d9a4
AR
550 quote (text));
551 else if (variant_count > 1 && has_valid && has_error)
ba4184ec 552 complain_at (text_loc, _("misleading reference: %s"),
b9f1d9a4
AR
553 quote (text));
554 else
ba4184ec 555 complain_at (text_loc, _("invalid reference: %s"),
b9f1d9a4
AR
556 quote (text));
557
558 for (i = 0; i < variant_count; ++i)
559 {
ba4184ec
AR
560 const variant *var = &variant_table[i];
561 const char *at_spec = get_at_spec (var->index);
b9f1d9a4 562
ba4184ec
AR
563 if (var->err == 0)
564 complain_at (var->loc, _(" refers to: %c%s at %s"),
565 dollar_or_at, var->id, at_spec);
b9f1d9a4
AR
566 else
567 {
568 static struct obstack msg_buf;
872b52bc 569 const char *tail = exact_mode ? "" :
ba4184ec
AR
570 cp + strlen (var->id);
571 const char *id = var->hidden_by ? var->hidden_by->id :
572 var->id;
573 location id_loc = var->hidden_by ? var->hidden_by->loc :
574 var->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
ba4184ec 586 if (var->err & VARIANT_HIDDEN)
b9f1d9a4
AR
587 {
588 obstack_fgrow1 (&msg_buf, ", hiding %c", dollar_or_at);
ba4184ec
AR
589 if (contains_dot_or_dash (var->id))
590 obstack_fgrow1 (&msg_buf, "[%s]", var->id);
b9f1d9a4 591 else
ba4184ec 592 obstack_sgrow (&msg_buf, var->id);
b9f1d9a4
AR
593 obstack_sgrow (&msg_buf, tail);
594 }
595
872b52bc 596 obstack_fgrow1 (&msg_buf, " at %s", at_spec);
b9f1d9a4 597
ba4184ec 598 if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
b9f1d9a4
AR
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');
ba4184ec 603 complain_at (id_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 838 location code_loc, symbol_list *rule,
ba4184ec 839 named_ref *name)
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;
ba4184ec 846 self->named_ref = name;
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}