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