]> git.saurik.com Git - bison.git/blame - src/scan-code.l
tests: clean up push.at test group titles.
[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,
14e568d7 378 char *cp, char *cp_end, bool explicit_bracketing)
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 ||
14e568d7 385 (!explicit_bracketing && 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 410static void
14e568d7
AR
411show_sub_messages (const char* cp, bool explicit_bracketing,
412 int midrule_rhs_index, char dollar_or_at, bool is_warning)
1a323c2f
AR
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;
14e568d7 433 const char *tail = explicit_bracketing ? "" :
1a323c2f
AR
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;
14e568d7 494 bool explicit_bracketing;
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 522
14e568d7 523 explicit_bracketing = 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 538
14e568d7 539 explicit_bracketing = 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 553 var = variant_add (l->content.sym->tag, l->sym_loc,
14e568d7 554 symbol_index, cp, cp_end, explicit_bracketing);
992e874a
AR
555 if (var && l->named_ref)
556 var->hidden_by = l->named_ref;
7685e2f7 557
d5e8574b 558 if (l->named_ref)
992e874a 559 variant_add (l->named_ref->id, l->named_ref->loc,
14e568d7 560 symbol_index, cp, cp_end, explicit_bracketing);
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. */
14e568d7 576 if (!explicit_bracketing && 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 592 case 0:
4c56b131
AR
593 {
594 unsigned len = (explicit_bracketing || !ref_tail_fields) ?
595 cp_end - cp : ref_tail_fields - cp;
596 const char *message = "symbol not found in production";
597
598 complain_at (text_loc, _("invalid reference: %s"), quote (text));
599 if (midrule_rhs_index)
600 complain_at (rule->location, _(" %s before $%d: %.*s"),
601 message, midrule_rhs_index, len, cp);
602 else
603 complain_at (rule->location, _(" %s: %.*s"),
604 message, len, cp);
605
606 if (variant_count > 0)
14e568d7 607 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
1a323c2f 608 dollar_or_at, false);
4c56b131
AR
609 return INVALID_REF;
610 }
1a323c2f
AR
611 case 1:
612 {
613 if (variant_count > 1)
614 {
615 warn_at (text_loc, _("misleading reference: %s"),
616 quote (text));
14e568d7 617 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
1a323c2f
AR
618 dollar_or_at, true);
619 }
620 {
621 unsigned symbol_index =
622 variant_table[valid_variant_index].symbol_index;
623 return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
624 }
625 }
626 case 2:
627 default:
628 complain_at (text_loc, _("ambiguous reference: %s"),
629 quote (text));
14e568d7 630 show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
1a323c2f
AR
631 dollar_or_at, false);
632 return INVALID_REF;
7685e2f7
AR
633 }
634
1a323c2f 635 /* Not reachable. */
7685e2f7
AR
636 return INVALID_REF;
637}
638
e9071366
AD
639/* Keeps track of the maximum number of semantic values to the left of
640 a handle (those referenced by $0, $-1, etc.) are required by the
641 semantic actions of this grammar. */
642int max_left_semantic_context = 0;
643
644
645/*------------------------------------------------------------------.
646| TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
647| |
648| Possible inputs: $[<TYPENAME>]($|integer) |
649| |
650| Output to OBSTACK_FOR_STRING a reference to this semantic value. |
651`------------------------------------------------------------------*/
652
653static void
4210cd0b 654handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
e9071366 655{
28e52c0d 656 char const *type_name = NULL;
e9071366 657 char *cp = text + 1;
7685e2f7 658 char *gt_ptr = 0;
ffa4ba3a 659 symbol_list *effective_rule;
d5e8574b
AR
660 int effective_rule_length;
661 int n;
ffa4ba3a
JD
662
663 if (rule->midrule_parent_rule)
664 {
665 effective_rule = rule->midrule_parent_rule;
666 effective_rule_length = rule->midrule_parent_rhs_index - 1;
667 }
668 else
669 {
670 effective_rule = rule;
671 effective_rule_length = symbol_list_length (rule->next);
672 }
e9071366
AD
673
674 /* Get the type name if explicit. */
675 if (*cp == '<')
676 {
677 type_name = ++cp;
678 while (*cp != '>')
679 ++cp;
7685e2f7
AR
680
681 /* The '>' symbol will be later replaced by '\0'. Original
682 'text' is needed for error messages. */
683 gt_ptr = cp;
e9071366 684 ++cp;
ddc8ede1
PE
685 if (untyped_var_seen)
686 complain_at (dollar_loc, _("explicit type given in untyped grammar"));
687 tag_seen = true;
e9071366
AD
688 }
689
d5e8574b
AR
690 n = parse_ref (cp, effective_rule, effective_rule_length,
691 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
7685e2f7
AR
692
693 if (gt_ptr)
694 *gt_ptr = '\0';
695
696 switch (n)
e9071366 697 {
7685e2f7
AR
698 case INVALID_REF:
699 break;
700
701 case LHS_REF:
e9071366 702 if (!type_name)
4210cd0b 703 type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
ddc8ede1
PE
704
705 if (!type_name)
ad6b1efa 706 {
ddc8ede1
PE
707 if (union_seen | tag_seen)
708 {
709 if (rule->midrule_parent_rule)
710 complain_at (dollar_loc,
711 _("$$ for the midrule at $%d of `%s'"
712 " has no declared type"),
713 rule->midrule_parent_rhs_index,
3be03b13 714 effective_rule->content.sym->tag);
ddc8ede1
PE
715 else
716 complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
3be03b13 717 rule->content.sym->tag);
ddc8ede1 718 }
ad6b1efa 719 else
ddc8ede1
PE
720 untyped_var_seen = true;
721 type_name = "";
ad6b1efa 722 }
ddc8ede1 723
e9071366
AD
724 obstack_fgrow1 (&obstack_for_string,
725 "]b4_lhs_value([%s])[", type_name);
f6857bbf 726 rule->action_props.is_value_used = true;
7685e2f7
AR
727 break;
728
729 default:
730 if (max_left_semantic_context < 1 - n)
731 max_left_semantic_context = 1 - n;
732 if (!type_name && 0 < n)
733 type_name =
734 symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
735 if (!type_name)
e9071366 736 {
7685e2f7
AR
737 if (union_seen | tag_seen)
738 complain_at (dollar_loc, _("$%s of `%s' has no declared type"),
739 cp, effective_rule->content.sym->tag);
740 else
741 untyped_var_seen = true;
742 type_name = "";
e9071366 743 }
7685e2f7
AR
744
745 obstack_fgrow3 (&obstack_for_string,
746 "]b4_rhs_value(%d, %d, [%s])[",
747 effective_rule_length, n, type_name);
748 if (n > 0)
749 symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
750 true;
751 break;
e9071366
AD
752 }
753}
754
755
756/*------------------------------------------------------.
757| TEXT is a location token (i.e., a `@...'). Output to |
758| OBSTACK_FOR_STRING a reference to this location. |
759`------------------------------------------------------*/
760
761static void
4210cd0b 762handle_action_at (symbol_list *rule, char *text, location at_loc)
e9071366
AD
763{
764 char *cp = text + 1;
7685e2f7 765 symbol_list *effective_rule;
d5e8574b
AR
766 int effective_rule_length;
767 int n;
7685e2f7
AR
768
769 if (rule->midrule_parent_rule)
770 {
771 effective_rule = rule->midrule_parent_rule;
772 effective_rule_length = rule->midrule_parent_rhs_index - 1;
773 }
774 else
775 {
776 effective_rule = rule;
777 effective_rule_length = symbol_list_length (rule->next);
778 }
ffa4ba3a 779
4f82b42a 780 locations_flag = true;
e9071366 781
d5e8574b 782 n = parse_ref (cp, effective_rule, effective_rule_length,
7685e2f7
AR
783 rule->midrule_parent_rhs_index, text, at_loc, '@');
784 switch (n)
e9071366 785 {
7685e2f7
AR
786 case INVALID_REF:
787 break;
e9071366 788
7685e2f7
AR
789 case LHS_REF:
790 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
791 break;
792
793 default:
794 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
795 effective_rule_length, n);
796 break;
e9071366
AD
797 }
798}
799
800
801/*-------------------------.
802| Initialize the scanner. |
803`-------------------------*/
804
28e52c0d 805/* Translate the dollars and ats in \a self, in the context \a sc_context
ddc8ede1 806 (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */
e9071366 807
eb095650 808static char const *
28e52c0d 809translate_action (code_props *self, int sc_context)
e9071366 810{
2ce4ed68 811 char *res;
e9071366
AD
812 static bool initialized = false;
813 if (!initialized)
814 {
815 obstack_init (&obstack_for_string);
e9071366
AD
816 yy_flex_debug = 0;
817 initialized = true;
818 }
819
28e52c0d
JD
820 loc->start = loc->end = self->location.start;
821 yy_switch_to_buffer (yy_scan_string (self->code));
822 res = code_lex (self, sc_context);
e9071366
AD
823 yy_delete_buffer (YY_CURRENT_BUFFER);
824
825 return res;
826}
827
28e52c0d
JD
828/*------------------------------------------------------------------------.
829| Implementation of the public interface as documented in "scan-code.h". |
830`------------------------------------------------------------------------*/
831
832void
833code_props_none_init (code_props *self)
76290368 834{
28e52c0d 835 *self = code_props_none;
76290368
JD
836}
837
28e52c0d
JD
838code_props const code_props_none = CODE_PROPS_NONE_INIT;
839
840void
d5e8574b
AR
841code_props_plain_init (code_props *self, char const *code,
842 location code_loc)
76290368 843{
28e52c0d
JD
844 self->kind = CODE_PROPS_PLAIN;
845 self->code = code;
846 self->location = code_loc;
847 self->is_value_used = false;
848 self->rule = NULL;
7685e2f7 849 self->named_ref = NULL;
76290368
JD
850}
851
28e52c0d
JD
852void
853code_props_symbol_action_init (code_props *self, char const *code,
854 location code_loc)
e9071366 855{
28e52c0d
JD
856 self->kind = CODE_PROPS_SYMBOL_ACTION;
857 self->code = code;
858 self->location = code_loc;
859 self->is_value_used = false;
860 self->rule = NULL;
7685e2f7 861 self->named_ref = NULL;
e9071366
AD
862}
863
28e52c0d
JD
864void
865code_props_rule_action_init (code_props *self, char const *code,
7685e2f7 866 location code_loc, symbol_list *rule,
992e874a 867 named_ref *name)
28e52c0d
JD
868{
869 self->kind = CODE_PROPS_RULE_ACTION;
870 self->code = code;
871 self->location = code_loc;
872 self->is_value_used = false;
873 self->rule = rule;
992e874a 874 self->named_ref = name;
28e52c0d
JD
875}
876
877void
878code_props_translate_code (code_props *self)
879{
880 switch (self->kind)
881 {
882 case CODE_PROPS_NONE:
883 break;
884 case CODE_PROPS_PLAIN:
885 self->code = translate_action (self, INITIAL);
886 break;
887 case CODE_PROPS_SYMBOL_ACTION:
888 self->code = translate_action (self, SC_SYMBOL_ACTION);
889 break;
890 case CODE_PROPS_RULE_ACTION:
891 self->code = translate_action (self, SC_RULE_ACTION);
892 break;
893 }
894}
895
896void
897code_scanner_last_string_free (void)
898{
899 STRING_FREE;
900}
e9071366
AD
901
902void
903code_scanner_free (void)
904{
905 obstack_free (&obstack_for_string, 0);
1e20ad11
AR
906 variant_table_free ();
907
e9071366 908 /* Reclaim Flex's buffers. */
580b8926 909 yylex_destroy ();
e9071366 910}