]> git.saurik.com Git - bison.git/blame - src/scan-gram.l
Fix some memory leaks, and fix a bug: state 0 was examined twice.
[bison.git] / src / scan-gram.l
CommitLineData
e9955c83
AD
1/* Bison Grammar Scanner -*- C -*-
2 Copyright (C) 2002 Free Software Foundation, Inc.
3
4 This file is part of Bison, the GNU Compiler Compiler.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA
20*/
21
22%option debug nodefault noyywrap nounput never-interactive stack
23%option prefix="gram_" outfile="lex.yy.c"
24
25%{
26#include "system.h"
27#include "complain.h"
28#include "quote.h"
29#include "getargs.h"
30#include "gram.h"
31#include "reader.h"
32
33/* Each time we match a string, move the end cursor to its end. */
8efe435c
AD
34#define YY_USER_INIT \
35do { \
36 LOCATION_RESET (*yylloc); \
37 /* This is only to avoid GCC warnings. */ \
38 if (yycontrol) {;}; \
39} while (0)
40
e9955c83
AD
41#define YY_USER_ACTION LOCATION_COLUMNS (*yylloc, yyleng)
42#define YY_LINES LOCATION_LINES (*yylloc, yyleng); lineno += yyleng;
43#define YY_STEP LOCATION_STEP (*yylloc)
44
44995b2e
AD
45
46/* STRING_OBSTACK -- Used to store all the characters that we need to
47 keep (to construct ID, STRINGS etc.). Use the following macros to
48 use it.
49
1d6412ad
AD
50 Use YY_OBS_GROW to append what has just been matched, and
51 YY_OBS_FINISH to end the string (it puts the ending 0).
52 YY_OBS_FINISH also stores this string in LAST_STRING, which can be
53 used, and which is used by YY_OBS_FREE to free the last string. */
44995b2e
AD
54
55static struct obstack string_obstack;
56char *last_string;
57
44995b2e
AD
58#define YY_OBS_GROW \
59 obstack_grow (&string_obstack, yytext, yyleng)
60
61#define YY_OBS_FINISH \
62 do { \
63 obstack_1grow (&string_obstack, '\0'); \
64 last_string = obstack_finish (&string_obstack); \
44995b2e
AD
65 } while (0)
66
67#define YY_OBS_FREE \
68 do { \
69 obstack_free (&string_obstack, last_string); \
70 } while (0)
e9955c83 71
4cdb01db
AD
72void
73scanner_last_string_free (void)
74{
75 YY_OBS_FREE;
76}
77
78
e9955c83
AD
79static int braces_level = 0;
80static int percent_percent_count = 0;
81
f25bfb75
AD
82static void handle_dollar PARAMS ((braced_code_t code_kind,
83 char *cp, location_t location));
84static void handle_at PARAMS ((braced_code_t code_kind,
85 char *cp, location_t location));
e9955c83
AD
86
87%}
88%x SC_COMMENT
89%x SC_STRING SC_CHARACTER
90%x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
91%x SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
92
93id [.a-zA-Z][.a-zA-Z_0-9]*
94int [0-9]+
95eols (\n|\r|\n\r|\r\n)+
96blanks [ \t\f]+
97
98%%
99%{
100 /* At each yylex invocation, mark the current position as the
101 start of the next token. */
102#define TR_POS 0
103#if TR_POS
8efe435c 104 fprintf (stderr, "FOO1: %p: ", yylloc);
e9955c83
AD
105 LOCATION_PRINT (stderr, *yylloc);
106 fprintf (stderr, "\n");
107#endif
108 YY_STEP;
109#if TR_POS
110 fprintf (stderr, "BAR1: ");
111 LOCATION_PRINT (stderr, *yylloc);
112 fprintf (stderr, "\n");
113#endif
114%}
115
116
117 /*----------------------------.
118 | Scanning Bison directives. |
119 `----------------------------*/
120<INITIAL>
121{
122 "%binary" return PERCENT_NONASSOC;
123 "%debug" return PERCENT_DEBUG;
124 "%define" return PERCENT_DEFINE;
125 "%defines" return PERCENT_DEFINES;
9280d3ef 126 "%destructor" return PERCENT_DESTRUCTOR;
676385e2 127 "%dprec" return PERCENT_DPREC;
e9955c83
AD
128 "%error"[-_]"verbose" return PERCENT_ERROR_VERBOSE;
129 "%expect" return PERCENT_EXPECT;
130 "%file-prefix" return PERCENT_FILE_PREFIX;
131 "%fixed"[-_]"output"[-_]"files" return PERCENT_YACC;
676385e2 132 "%glr"[-_]"parser" return PERCENT_GLR_PARSER;
e9955c83
AD
133 "%left" return PERCENT_LEFT;
134 "%locations" return PERCENT_LOCATIONS;
676385e2 135 "%merge" return PERCENT_MERGE;
e9955c83
AD
136 "%name"[-_]"prefix" return PERCENT_NAME_PREFIX;
137 "%no"[-_]"lines" return PERCENT_NO_LINES;
138 "%nonassoc" return PERCENT_NONASSOC;
139 "%nterm" return PERCENT_NTERM;
140 "%output" return PERCENT_OUTPUT;
141 "%prec" return PERCENT_PREC;
366eea36 142 "%printer" return PERCENT_PRINTER;
e9955c83
AD
143 "%pure"[-_]"parser" return PERCENT_PURE_PARSER;
144 "%right" return PERCENT_RIGHT;
145 "%skeleton" return PERCENT_SKELETON;
146 "%start" return PERCENT_START;
147 "%term" return PERCENT_TOKEN;
148 "%token" return PERCENT_TOKEN;
149 "%token"[-_]"table" return PERCENT_TOKEN_TABLE;
150 "%type" return PERCENT_TYPE;
151 "%union" return PERCENT_UNION;
152 "%verbose" return PERCENT_VERBOSE;
153 "%yacc" return PERCENT_YACC;
154
155 "=" return EQUAL;
156 ":" return COLON;
157 "|" return PIPE;
158 ";" return SEMICOLON;
159
160 {eols} YY_LINES; YY_STEP;
161 {blanks} YY_STEP;
162 {id} {
39f41916 163 yylval->symbol = symbol_get (yytext, *yylloc);
e9955c83
AD
164 return ID;
165 }
166
167 {int} yylval->integer = strtol (yytext, 0, 10); return INT;
168
169 /* Characters. We don't check there is only one. */
1d6412ad 170 \' YY_OBS_GROW; yy_push_state (SC_ESCAPED_CHARACTER);
e9955c83
AD
171
172 /* Strings. */
1d6412ad 173 \" YY_OBS_GROW; yy_push_state (SC_ESCAPED_STRING);
e9955c83
AD
174
175 /* Comments. */
176 "/*" yy_push_state (SC_COMMENT);
177 "//".* YY_STEP;
178
179 /* Prologue. */
1d6412ad 180 "%{" yy_push_state (SC_PROLOGUE);
e9955c83
AD
181
182 /* Code in between braces. */
1d6412ad 183 "{" YY_OBS_GROW; ++braces_level; yy_push_state (SC_BRACED_CODE);
e9955c83
AD
184
185 /* A type. */
4cdb01db 186 "<"[^>]+">" {
4cdb01db
AD
187 obstack_grow (&string_obstack, yytext + 1, yyleng - 2);
188 YY_OBS_FINISH;
189 yylval->string = last_string;
190 return TYPE;
191 }
192
e9955c83
AD
193
194 "%%" {
195 if (++percent_percent_count == 2)
196 yy_push_state (SC_EPILOGUE);
197 return PERCENT_PERCENT;
198 }
199
200 . {
201 LOCATION_PRINT (stderr, *yylloc);
202 fprintf (stderr, ": invalid character: `%c'\n", *yytext);
203 YY_STEP;
204 }
205}
206
207
208 /*------------------------------------------------------------.
209 | Whatever the start condition (but those which correspond to |
210 | entity `swallowed' by Bison: SC_ESCAPED_STRING and |
211 | SC_ESCAPED_CHARACTER), no M4 character must escape as is. |
212 `------------------------------------------------------------*/
213
214<SC_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
215{
1d6412ad
AD
216 \[ if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@<:@");
217 \] if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@:>@");
e9955c83
AD
218}
219
220
221
222 /*-----------------------------------------------------------.
223 | Scanning a C comment. The initial `/ *' is already eaten. |
224 `-----------------------------------------------------------*/
225
226<SC_COMMENT>
227{
228 "*/" { /* End of the comment. */
229 if (yy_top_state () == INITIAL)
230 {
231 YY_STEP;
232 }
233 else
234 {
44995b2e 235 YY_OBS_GROW;
e9955c83
AD
236 }
237 yy_pop_state ();
238 }
239
44995b2e
AD
240 [^\[\]*\n\r]+ if (yy_top_state () != INITIAL) YY_OBS_GROW;
241 {eols} if (yy_top_state () != INITIAL) YY_OBS_GROW; YY_LINES;
242 . /* Stray `*'. */if (yy_top_state () != INITIAL) YY_OBS_GROW;
e9955c83
AD
243
244 <<EOF>> {
245 LOCATION_PRINT (stderr, *yylloc);
246 fprintf (stderr, ": unexpected end of file in a comment\n");
247 yy_pop_state ();
248 }
249}
250
251
252 /*----------------------------------------------------------------.
253 | Scanning a C string, including its escapes. The initial `"' is |
254 | already eaten. |
255 `----------------------------------------------------------------*/
256
257<SC_ESCAPED_STRING>
258{
259 \" {
260 assert (yy_top_state () == INITIAL);
44995b2e
AD
261 YY_OBS_GROW;
262 YY_OBS_FINISH;
4cdb01db 263 yylval->string = last_string;
e9955c83
AD
264 yy_pop_state ();
265 return STRING;
266 }
267
44995b2e 268 [^\"\n\r\\]+ YY_OBS_GROW;
e9955c83
AD
269
270 {eols} obstack_1grow (&string_obstack, '\n'); YY_LINES;
271
272 <<EOF>> {
273 LOCATION_PRINT (stderr, *yylloc);
274 fprintf (stderr, ": unexpected end of file in a string\n");
275 assert (yy_top_state () == INITIAL);
44995b2e 276 YY_OBS_FINISH;
4cdb01db 277 yylval->string = last_string;
e9955c83
AD
278 yy_pop_state ();
279 return STRING;
280 }
281}
282
283 /*---------------------------------------------------------------.
284 | Scanning a C character, decoding its escapes. The initial "'" |
285 | is already eaten. |
286 `---------------------------------------------------------------*/
287
288<SC_ESCAPED_CHARACTER>
289{
290 \' {
44995b2e 291 YY_OBS_GROW;
e9955c83
AD
292 assert (yy_top_state () == INITIAL);
293 {
44995b2e 294 YY_OBS_FINISH;
39f41916 295 yylval->symbol = symbol_get (last_string, *yylloc);
e776192e 296 symbol_class_set (yylval->symbol, token_sym, *yylloc);
e68d4575
PE
297 symbol_user_token_number_set (yylval->symbol,
298 (unsigned char) last_string[1], *yylloc);
44995b2e 299 YY_OBS_FREE;
e9955c83
AD
300 yy_pop_state ();
301 return ID;
302 }
303 }
304
44995b2e 305 [^\'\n\r\\] YY_OBS_GROW;
e9955c83
AD
306
307 {eols} obstack_1grow (&string_obstack, '\n'); YY_LINES;
308
309 <<EOF>> {
310 LOCATION_PRINT (stderr, *yylloc);
311 fprintf (stderr, ": unexpected end of file in a character\n");
312 assert (yy_top_state () == INITIAL);
44995b2e 313 YY_OBS_FINISH;
4cdb01db 314 yylval->string = last_string;
e9955c83
AD
315 yy_pop_state ();
316 return CHARACTER;
317 }
318}
319
320
321 /*----------------------------.
322 | Decode escaped characters. |
323 `----------------------------*/
324
325<SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
326{
327 \\[0-7]{3} {
328 long c = strtol (yytext + 1, 0, 8);
329 if (c > 255)
330 {
331 LOCATION_PRINT (stderr, *yylloc);
4f25ebb0 332 fprintf (stderr, ": invalid escape: %s\n", quote (yytext));
e9955c83
AD
333 YY_STEP;
334 }
335 else
336 obstack_1grow (&string_obstack, c);
337 }
338
339 \\x[0-9a-fA-F]{2} {
340 obstack_1grow (&string_obstack, strtol (yytext + 2, 0, 16));
341 }
342
343 \\a obstack_1grow (&string_obstack, '\a');
344 \\b obstack_1grow (&string_obstack, '\b');
345 \\f obstack_1grow (&string_obstack, '\f');
346 \\n obstack_1grow (&string_obstack, '\n');
347 \\r obstack_1grow (&string_obstack, '\r');
348 \\t obstack_1grow (&string_obstack, '\t');
349 \\v obstack_1grow (&string_obstack, '\v');
350 \\[\\""] obstack_1grow (&string_obstack, yytext[1]);
4f25ebb0 351 \\(.|\n) {
e9955c83 352 LOCATION_PRINT (stderr, *yylloc);
4f25ebb0 353 fprintf (stderr, ": unrecognized escape: %s\n", quote (yytext));
44995b2e 354 YY_OBS_GROW;
e9955c83 355 }
4f25ebb0
AD
356 /* FLex wants this rule, in case of a `\<<EOF>>'. */
357 \\ YY_OBS_GROW;
e9955c83
AD
358}
359
360
361 /*----------------------------------------------------------.
362 | Scanning a C character without decoding its escapes. The |
363 | initial "'" is already eaten. |
364 `----------------------------------------------------------*/
365
366<SC_CHARACTER>
367{
368 \' {
44995b2e 369 YY_OBS_GROW;
e9955c83
AD
370 assert (yy_top_state () != INITIAL);
371 yy_pop_state ();
372 }
373
4f25ebb0
AD
374 [^\[\]\'\n\r\\]+ YY_OBS_GROW;
375 \\(.|\n) YY_OBS_GROW;
376 /* FLex wants this rule, in case of a `\<<EOF>>'. */
377 \\ YY_OBS_GROW;
e9955c83 378
44995b2e 379 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
380
381 <<EOF>> {
382 LOCATION_PRINT (stderr, *yylloc);
383 fprintf (stderr, ": unexpected end of file in a character\n");
384 assert (yy_top_state () != INITIAL);
385 yy_pop_state ();
386 }
387}
388
389
390 /*----------------------------------------------------------------.
391 | Scanning a C string, without decoding its escapes. The initial |
392 | `"' is already eaten. |
393 `----------------------------------------------------------------*/
394
395<SC_STRING>
396{
397 \" {
398 assert (yy_top_state () != INITIAL);
44995b2e 399 YY_OBS_GROW;
e9955c83
AD
400 yy_pop_state ();
401 }
402
44995b2e 403 [^\[\]\"\n\r\\]+ YY_OBS_GROW;
4f25ebb0
AD
404 \\(.|\n) YY_OBS_GROW;
405 /* FLex wants this rule, in case of a `\<<EOF>>'. */
406 \\ YY_OBS_GROW;
e9955c83 407
44995b2e 408 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
409
410 <<EOF>> {
411 LOCATION_PRINT (stderr, *yylloc);
412 fprintf (stderr, ": unexpected end of file in a string\n");
413 assert (yy_top_state () != INITIAL);
414 yy_pop_state ();
415 }
416}
417
418
419 /*---------------------------------------------------.
420 | Strings, comments etc. can be found in user code. |
421 `---------------------------------------------------*/
422
423<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
424{
425 /* Characters. We don't check there is only one. */
44995b2e 426 \' YY_OBS_GROW; yy_push_state (SC_CHARACTER);
e9955c83
AD
427
428 /* Strings. */
44995b2e 429 \" YY_OBS_GROW; yy_push_state (SC_STRING);
e9955c83
AD
430
431 /* Comments. */
44995b2e
AD
432 "/*" YY_OBS_GROW; yy_push_state (SC_COMMENT);
433 "//".* YY_OBS_GROW;
4f25ebb0
AD
434
435 /* Not comments. */
436 "/" YY_OBS_GROW;
e9955c83
AD
437}
438
439
440 /*---------------------------------------------------------------.
441 | Scanning some code in braces (%union and actions). The initial |
442 | "{" is already eaten. |
443 `---------------------------------------------------------------*/
444
445<SC_BRACED_CODE>
446{
447 "}" {
44995b2e 448 YY_OBS_GROW;
e9955c83
AD
449 if (--braces_level == 0)
450 {
451 yy_pop_state ();
44995b2e 452 YY_OBS_FINISH;
4cdb01db 453 yylval->string = last_string;
e9955c83
AD
454 return BRACED_CODE;
455 }
456 }
457
44995b2e 458 "{" YY_OBS_GROW; braces_level++;
e9955c83 459
f25bfb75
AD
460 "$"("<"[^>]+">")?(-?[0-9]+|"$") { handle_dollar (current_braced_code,
461 yytext, *yylloc); }
462 "@"(-?[0-9]+|"$") { handle_at (current_braced_code,
463 yytext, *yylloc); }
e9955c83 464
6c35d22c 465 [^$@\[\]/\'\"\{\}\n\r]+ YY_OBS_GROW;
44995b2e 466 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
467
468 /* A lose $, or /, or etc. */
44995b2e 469 . YY_OBS_GROW;
e9955c83
AD
470
471 <<EOF>> {
472 LOCATION_PRINT (stderr, *yylloc);
473 fprintf (stderr, ": unexpected end of file in a braced code\n");
474 yy_pop_state ();
44995b2e 475 YY_OBS_FINISH;
4cdb01db
AD
476 yylval->string = last_string;
477 return BRACED_CODE;
e9955c83
AD
478 }
479
480}
481
482
483 /*--------------------------------------------------------------.
484 | Scanning some prologue: from "%{" (already scanned) to "%}". |
485 `--------------------------------------------------------------*/
486
487<SC_PROLOGUE>
488{
489 "%}" {
490 yy_pop_state ();
44995b2e 491 YY_OBS_FINISH;
4cdb01db 492 yylval->string = last_string;
e9955c83
AD
493 return PROLOGUE;
494 }
495
4f25ebb0
AD
496 [^%\[\]/\'\"\n\r]+ YY_OBS_GROW;
497 "%" YY_OBS_GROW;
498 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
499
500 <<EOF>> {
501 LOCATION_PRINT (stderr, *yylloc);
502 fprintf (stderr, ": unexpected end of file in a prologue\n");
503 yy_pop_state ();
44995b2e 504 YY_OBS_FINISH;
4cdb01db 505 yylval->string = last_string;
e9955c83
AD
506 return PROLOGUE;
507 }
e9955c83
AD
508}
509
510
511 /*---------------------------------------------------------------.
512 | Scanning the epilogue (everything after the second "%%", which |
513 | has already been eaten. |
514 `---------------------------------------------------------------*/
515
516<SC_EPILOGUE>
517{
44995b2e 518 ([^\[\]]|{eols})+ YY_OBS_GROW;
e9955c83
AD
519
520 <<EOF>> {
521 yy_pop_state ();
44995b2e 522 YY_OBS_FINISH;
4cdb01db 523 yylval->string = last_string;
e9955c83
AD
524 return EPILOGUE;
525 }
526}
527
528
529%%
530
531/*------------------------------------------------------------------.
366eea36 532| TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
e9955c83
AD
533| |
534| Possible inputs: $[<TYPENAME>]($|integer) |
535| |
536| Output to the STRING_OBSTACK a reference to this semantic value. |
537`------------------------------------------------------------------*/
538
f25bfb75 539static inline void
366eea36 540handle_action_dollar (char *text, location_t location)
e9955c83
AD
541{
542 const char *type_name = NULL;
366eea36 543 char *cp = text + 1;
e9955c83
AD
544
545 /* Get the type name if explicit. */
546 if (*cp == '<')
547 {
548 type_name = ++cp;
549 while (*cp != '>')
550 ++cp;
551 *cp = '\0';
552 ++cp;
553 }
554
555 if (*cp == '$')
556 {
557 if (!type_name)
56c47203 558 type_name = symbol_list_n_type_name_get (current_rule, location, 0);
e9955c83 559 if (!type_name && typed)
56c47203 560 complain_at (location, _("$$ of `%s' has no declared type"),
97650f4e 561 current_rule->sym->tag);
e9955c83
AD
562 if (!type_name)
563 type_name = "";
564 obstack_fgrow1 (&string_obstack,
565 "]b4_lhs_value([%s])[", type_name);
566 }
567 else if (isdigit (*cp) || *cp == '-')
568 {
dafdc66f
AD
569 /* RULE_LENGTH is the number of values in the current rule so
570 far, which says where to find `$0' with respect to the top of
571 the stack. It is not the same as the rule->length in the
572 case of mid rule actions. */
573 int rule_length = symbol_list_length (current_rule->next);
e9955c83
AD
574 int n = strtol (cp, &cp, 10);
575
576 if (n > rule_length)
56c47203 577 complain_at (location, _("invalid value: %s%d"), "$", n);
e9955c83
AD
578 else
579 {
580 if (!type_name && n > 0)
56c47203
AD
581 type_name = symbol_list_n_type_name_get (current_rule, location,
582 n);
e9955c83 583 if (!type_name && typed)
56c47203 584 complain_at (location, _("$%d of `%s' has no declared type"),
97650f4e 585 n, current_rule->sym->tag);
e9955c83
AD
586 if (!type_name)
587 type_name = "";
588 obstack_fgrow3 (&string_obstack,
589 "]b4_rhs_value([%d], [%d], [%s])[",
590 rule_length, n, type_name);
591 }
592 }
593 else
594 {
366eea36 595 complain_at (location, _("%s is invalid"), quote (text));
9280d3ef
AD
596 }
597}
598
599
366eea36
AD
600/*---------------------------------------------------------------.
601| TEXT is expexted tp be $$ in some code associated to a symbol: |
602| destructor or printer. |
603`---------------------------------------------------------------*/
9280d3ef 604
f25bfb75 605static inline void
366eea36 606handle_symbol_code_dollar (char *text, location_t location)
9280d3ef 607{
366eea36 608 char *cp = text + 1;
9280d3ef 609 if (*cp == '$')
366eea36 610 obstack_sgrow (&string_obstack, "]b4_dollar_dollar[");
9280d3ef 611 else
366eea36 612 complain_at (location, _("%s is invalid"), quote (text));
e9955c83
AD
613}
614
f25bfb75
AD
615
616/*-----------------------------------------------------------------.
617| Dispatch onto handle_action_dollar, or handle_destructor_dollar, |
618| depending upon CODE_KIND. |
619`-----------------------------------------------------------------*/
e9955c83
AD
620
621static void
f25bfb75
AD
622handle_dollar (braced_code_t braced_code_kind,
623 char *text, location_t location)
624{
625 switch (braced_code_kind)
626 {
627 case action_braced_code:
628 handle_action_dollar (text, location);
629 break;
630
631 case destructor_braced_code:
366eea36
AD
632 case printer_braced_code:
633 handle_symbol_code_dollar (text, location);
f25bfb75
AD
634 break;
635 }
636}
637
638
639/*------------------------------------------------------.
640| TEXT is a location token (i.e., a `@...'). Output to |
641| STRING_OBSTACK a reference to this location. |
642`------------------------------------------------------*/
643
644static inline void
645handle_action_at (char *text, location_t location)
e9955c83 646{
366eea36 647 char *cp = text + 1;
e9955c83 648 locations_flag = 1;
e9955c83 649
366eea36 650 if (*cp == '$')
e9955c83
AD
651 {
652 obstack_sgrow (&string_obstack, "]b4_lhs_location[");
653 }
366eea36 654 else if (isdigit (*cp) || *cp == '-')
e9955c83 655 {
dafdc66f
AD
656 /* RULE_LENGTH is the number of values in the current rule so
657 far, which says where to find `$0' with respect to the top of
658 the stack. It is not the same as the rule->length in the
659 case of mid rule actions. */
660 int rule_length = symbol_list_length (current_rule->next);
366eea36 661 int n = strtol (cp, &cp, 10);
dafdc66f 662
e9955c83 663 if (n > rule_length)
f25bfb75 664 complain_at (location, _("invalid value: %s%d"), "@", n);
e9955c83
AD
665 else
666 obstack_fgrow2 (&string_obstack, "]b4_rhs_location([%d], [%d])[",
667 rule_length, n);
668 }
669 else
670 {
366eea36 671 complain_at (location, _("%s is invalid"), quote (text));
f25bfb75
AD
672 }
673}
674
675
366eea36
AD
676/*---------------------------------------------------------------.
677| TEXT is expexted tp be @$ in some code associated to a symbol: |
678| destructor or printer. |
679`---------------------------------------------------------------*/
f25bfb75
AD
680
681static inline void
366eea36 682handle_symbol_code_at (char *text, location_t location)
f25bfb75 683{
366eea36
AD
684 char *cp = text + 1;
685 if (*cp == '$')
686 obstack_sgrow (&string_obstack, "]b4_at_dollar[");
f25bfb75 687 else
366eea36 688 complain_at (location, _("%s is invalid"), quote (text));
e9955c83 689}
4cdb01db 690
f25bfb75
AD
691
692/*-------------------------------------------------------------------.
693| Dispatch onto handle_action_at, or handle_destructor_at, depending |
694| upon CODE_KIND. |
695`-------------------------------------------------------------------*/
696
697static void
698handle_at (braced_code_t braced_code_kind,
699 char *text, location_t location)
700{
701 switch (braced_code_kind)
702 {
703 case action_braced_code:
704 handle_action_at (text, location);
705 break;
706
707 case destructor_braced_code:
366eea36
AD
708 case printer_braced_code:
709 handle_symbol_code_at (text, location);
f25bfb75
AD
710 break;
711 }
712}
713
714
715/*-------------------------.
716| Initialize the scanner. |
717`-------------------------*/
718
1d6412ad
AD
719void
720scanner_initialize (void)
721{
722 obstack_init (&string_obstack);
723}
724
725
f25bfb75
AD
726/*-----------------------------------------------.
727| Free all the memory allocated to the scanner. |
728`-----------------------------------------------*/
729
4cdb01db
AD
730void
731scanner_free (void)
732{
733 obstack_free (&string_obstack, 0);
734}