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