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