]> git.saurik.com Git - bison.git/blame - src/scan-gram.l
* src/getargs.c (usage): Take status as argument and exit
[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); \
1a715ef2 37 yylloc->file = infile; \
8efe435c
AD
38 /* This is only to avoid GCC warnings. */ \
39 if (yycontrol) {;}; \
40} while (0)
41
1a715ef2 42#define YY_USER_ACTION LOCATION_COLUMNS (*yylloc, yyleng);
a5d50994 43#define YY_LINES LOCATION_LINES (*yylloc, yyleng);
1a715ef2 44#define YY_STEP LOCATION_STEP (*yylloc);
e9955c83 45
44995b2e
AD
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
efcb44dd
PE
82/* Within well-formed rules, RULE_LENGTH is the number of values in
83 the current rule so far, which says where to find `$0' with respect
84 to the top of the stack. It is not the same as the rule->length in
85 the case of mid rule actions.
86
87 Outside of well-formed rules, RULE_LENGTH has an undefined value. */
88static int rule_length;
89
f25bfb75
AD
90static void handle_dollar PARAMS ((braced_code_t code_kind,
91 char *cp, location_t location));
92static void handle_at PARAMS ((braced_code_t code_kind,
93 char *cp, location_t location));
e9955c83
AD
94
95%}
96%x SC_COMMENT
97%x SC_STRING SC_CHARACTER
98%x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
99%x SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
100
5dde258a 101id [.a-zA-Z_][.a-zA-Z_0-9]*
e9955c83
AD
102int [0-9]+
103eols (\n|\r|\n\r|\r\n)+
104blanks [ \t\f]+
105
106%%
107%{
108 /* At each yylex invocation, mark the current position as the
109 start of the next token. */
e9955c83 110 YY_STEP;
e9955c83
AD
111%}
112
113
114 /*----------------------------.
115 | Scanning Bison directives. |
116 `----------------------------*/
117<INITIAL>
118{
119 "%binary" return PERCENT_NONASSOC;
120 "%debug" return PERCENT_DEBUG;
121 "%define" return PERCENT_DEFINE;
122 "%defines" return PERCENT_DEFINES;
9280d3ef 123 "%destructor" return PERCENT_DESTRUCTOR;
676385e2 124 "%dprec" return PERCENT_DPREC;
e9955c83
AD
125 "%error"[-_]"verbose" return PERCENT_ERROR_VERBOSE;
126 "%expect" return PERCENT_EXPECT;
127 "%file-prefix" return PERCENT_FILE_PREFIX;
128 "%fixed"[-_]"output"[-_]"files" return PERCENT_YACC;
676385e2 129 "%glr"[-_]"parser" return PERCENT_GLR_PARSER;
e9955c83
AD
130 "%left" return PERCENT_LEFT;
131 "%locations" return PERCENT_LOCATIONS;
676385e2 132 "%merge" return PERCENT_MERGE;
e9955c83
AD
133 "%name"[-_]"prefix" return PERCENT_NAME_PREFIX;
134 "%no"[-_]"lines" return PERCENT_NO_LINES;
135 "%nonassoc" return PERCENT_NONASSOC;
136 "%nterm" return PERCENT_NTERM;
137 "%output" return PERCENT_OUTPUT;
efcb44dd 138 "%prec" { rule_length--; return PERCENT_PREC; }
366eea36 139 "%printer" return PERCENT_PRINTER;
e9955c83
AD
140 "%pure"[-_]"parser" return PERCENT_PURE_PARSER;
141 "%right" return PERCENT_RIGHT;
142 "%skeleton" return PERCENT_SKELETON;
143 "%start" return PERCENT_START;
144 "%term" return PERCENT_TOKEN;
145 "%token" return PERCENT_TOKEN;
146 "%token"[-_]"table" return PERCENT_TOKEN_TABLE;
147 "%type" return PERCENT_TYPE;
148 "%union" return PERCENT_UNION;
149 "%verbose" return PERCENT_VERBOSE;
150 "%yacc" return PERCENT_YACC;
151
152 "=" return EQUAL;
efcb44dd
PE
153 ":" { rule_length = 0; return COLON; }
154 "|" { rule_length = 0; return PIPE; }
e9955c83
AD
155 ";" return SEMICOLON;
156
157 {eols} YY_LINES; YY_STEP;
158 {blanks} YY_STEP;
159 {id} {
39f41916 160 yylval->symbol = symbol_get (yytext, *yylloc);
efcb44dd 161 rule_length++;
e9955c83
AD
162 return ID;
163 }
164
165 {int} yylval->integer = strtol (yytext, 0, 10); return INT;
166
167 /* Characters. We don't check there is only one. */
db2cc12f 168 "'" YY_OBS_GROW; yy_push_state (SC_ESCAPED_CHARACTER);
e9955c83
AD
169
170 /* Strings. */
db2cc12f 171 "\"" YY_OBS_GROW; yy_push_state (SC_ESCAPED_STRING);
e9955c83
AD
172
173 /* Comments. */
174 "/*" yy_push_state (SC_COMMENT);
175 "//".* YY_STEP;
176
177 /* Prologue. */
1d6412ad 178 "%{" yy_push_state (SC_PROLOGUE);
e9955c83
AD
179
180 /* Code in between braces. */
1d6412ad 181 "{" YY_OBS_GROW; ++braces_level; yy_push_state (SC_BRACED_CODE);
e9955c83
AD
182
183 /* A type. */
4cdb01db 184 "<"[^>]+">" {
4cdb01db
AD
185 obstack_grow (&string_obstack, yytext + 1, yyleng - 2);
186 YY_OBS_FINISH;
187 yylval->string = last_string;
188 return TYPE;
189 }
190
e9955c83
AD
191
192 "%%" {
193 if (++percent_percent_count == 2)
194 yy_push_state (SC_EPILOGUE);
195 return PERCENT_PERCENT;
196 }
197
198 . {
199 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 200 fprintf (stderr, _(": invalid character: `%c'\n"), *yytext);
e9955c83
AD
201 YY_STEP;
202 }
203}
204
205
206 /*------------------------------------------------------------.
207 | Whatever the start condition (but those which correspond to |
208 | entity `swallowed' by Bison: SC_ESCAPED_STRING and |
209 | SC_ESCAPED_CHARACTER), no M4 character must escape as is. |
210 `------------------------------------------------------------*/
211
212<SC_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
213{
1d6412ad
AD
214 \[ if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@<:@");
215 \] if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@:>@");
e9955c83
AD
216}
217
218
219
220 /*-----------------------------------------------------------.
221 | Scanning a C comment. The initial `/ *' is already eaten. |
222 `-----------------------------------------------------------*/
223
224<SC_COMMENT>
225{
226 "*/" { /* End of the comment. */
227 if (yy_top_state () == INITIAL)
228 {
229 YY_STEP;
230 }
231 else
232 {
44995b2e 233 YY_OBS_GROW;
e9955c83
AD
234 }
235 yy_pop_state ();
236 }
237
44995b2e
AD
238 [^\[\]*\n\r]+ if (yy_top_state () != INITIAL) YY_OBS_GROW;
239 {eols} if (yy_top_state () != INITIAL) YY_OBS_GROW; YY_LINES;
240 . /* Stray `*'. */if (yy_top_state () != INITIAL) YY_OBS_GROW;
e9955c83
AD
241
242 <<EOF>> {
243 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 244 fprintf (stderr, _(": unexpected end of file in a comment\n"));
e9955c83
AD
245 yy_pop_state ();
246 }
247}
248
249
250 /*----------------------------------------------------------------.
251 | Scanning a C string, including its escapes. The initial `"' is |
252 | already eaten. |
253 `----------------------------------------------------------------*/
254
255<SC_ESCAPED_STRING>
256{
db2cc12f 257 "\"" {
e9955c83 258 assert (yy_top_state () == INITIAL);
44995b2e
AD
259 YY_OBS_GROW;
260 YY_OBS_FINISH;
4cdb01db 261 yylval->string = last_string;
e9955c83 262 yy_pop_state ();
efcb44dd 263 rule_length++;
e9955c83
AD
264 return STRING;
265 }
266
44995b2e 267 [^\"\n\r\\]+ YY_OBS_GROW;
e9955c83
AD
268
269 {eols} obstack_1grow (&string_obstack, '\n'); YY_LINES;
270
271 <<EOF>> {
272 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 273 fprintf (stderr, _(": unexpected end of file in a string\n"));
e9955c83 274 assert (yy_top_state () == INITIAL);
44995b2e 275 YY_OBS_FINISH;
4cdb01db 276 yylval->string = last_string;
e9955c83
AD
277 yy_pop_state ();
278 return STRING;
279 }
280}
281
282 /*---------------------------------------------------------------.
283 | Scanning a C character, decoding its escapes. The initial "'" |
284 | is already eaten. |
285 `---------------------------------------------------------------*/
286
287<SC_ESCAPED_CHARACTER>
288{
db2cc12f 289 "'" {
44995b2e 290 YY_OBS_GROW;
e9955c83
AD
291 assert (yy_top_state () == INITIAL);
292 {
44995b2e 293 YY_OBS_FINISH;
39f41916 294 yylval->symbol = symbol_get (last_string, *yylloc);
e776192e 295 symbol_class_set (yylval->symbol, token_sym, *yylloc);
e68d4575
PE
296 symbol_user_token_number_set (yylval->symbol,
297 (unsigned char) last_string[1], *yylloc);
44995b2e 298 YY_OBS_FREE;
e9955c83 299 yy_pop_state ();
efcb44dd 300 rule_length++;
e9955c83
AD
301 return ID;
302 }
303 }
304
db2cc12f 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);
db2cc12f 311 fprintf (stderr, _(": unexpected end of file in a character\n"));
e9955c83 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);
db2cc12f 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');
eb714592 350 \\[\\""''] obstack_1grow (&string_obstack, yytext[1]);
4f25ebb0 351 \\(.|\n) {
e9955c83 352 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 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{
db2cc12f 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);
db2cc12f 383 fprintf (stderr, _(": unexpected end of file in a character\n"));
e9955c83
AD
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{
db2cc12f 397 "\"" {
e9955c83 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);
db2cc12f 412 fprintf (stderr, _(": unexpected end of file in a string\n"));
e9955c83
AD
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. */
db2cc12f 426 "'" YY_OBS_GROW; yy_push_state (SC_CHARACTER);
e9955c83
AD
427
428 /* Strings. */
db2cc12f 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;
efcb44dd 454 rule_length++;
e9955c83
AD
455 return BRACED_CODE;
456 }
457 }
458
44995b2e 459 "{" YY_OBS_GROW; braces_level++;
e9955c83 460
f25bfb75
AD
461 "$"("<"[^>]+">")?(-?[0-9]+|"$") { handle_dollar (current_braced_code,
462 yytext, *yylloc); }
463 "@"(-?[0-9]+|"$") { handle_at (current_braced_code,
464 yytext, *yylloc); }
e9955c83 465
6c35d22c 466 [^$@\[\]/\'\"\{\}\n\r]+ YY_OBS_GROW;
44995b2e 467 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
468
469 /* A lose $, or /, or etc. */
44995b2e 470 . YY_OBS_GROW;
e9955c83
AD
471
472 <<EOF>> {
473 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 474 fprintf (stderr, _(": unexpected end of file in a braced code\n"));
e9955c83 475 yy_pop_state ();
44995b2e 476 YY_OBS_FINISH;
4cdb01db
AD
477 yylval->string = last_string;
478 return BRACED_CODE;
e9955c83
AD
479 }
480
481}
482
483
484 /*--------------------------------------------------------------.
485 | Scanning some prologue: from "%{" (already scanned) to "%}". |
486 `--------------------------------------------------------------*/
487
488<SC_PROLOGUE>
489{
490 "%}" {
491 yy_pop_state ();
44995b2e 492 YY_OBS_FINISH;
4cdb01db 493 yylval->string = last_string;
e9955c83
AD
494 return PROLOGUE;
495 }
496
4f25ebb0
AD
497 [^%\[\]/\'\"\n\r]+ YY_OBS_GROW;
498 "%" YY_OBS_GROW;
499 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
500
501 <<EOF>> {
502 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 503 fprintf (stderr, _(": unexpected end of file in a prologue\n"));
e9955c83 504 yy_pop_state ();
44995b2e 505 YY_OBS_FINISH;
4cdb01db 506 yylval->string = last_string;
e9955c83
AD
507 return PROLOGUE;
508 }
e9955c83
AD
509}
510
511
512 /*---------------------------------------------------------------.
513 | Scanning the epilogue (everything after the second "%%", which |
514 | has already been eaten. |
515 `---------------------------------------------------------------*/
516
517<SC_EPILOGUE>
518{
44995b2e 519 ([^\[\]]|{eols})+ YY_OBS_GROW;
e9955c83
AD
520
521 <<EOF>> {
522 yy_pop_state ();
44995b2e 523 YY_OBS_FINISH;
4cdb01db 524 yylval->string = last_string;
e9955c83
AD
525 return EPILOGUE;
526 }
527}
528
529
530%%
531
532/*------------------------------------------------------------------.
366eea36 533| TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
e9955c83
AD
534| |
535| Possible inputs: $[<TYPENAME>]($|integer) |
536| |
537| Output to the STRING_OBSTACK a reference to this semantic value. |
538`------------------------------------------------------------------*/
539
f25bfb75 540static inline void
366eea36 541handle_action_dollar (char *text, location_t location)
e9955c83
AD
542{
543 const char *type_name = NULL;
366eea36 544 char *cp = text + 1;
e9955c83
AD
545
546 /* Get the type name if explicit. */
547 if (*cp == '<')
548 {
549 type_name = ++cp;
550 while (*cp != '>')
551 ++cp;
552 *cp = '\0';
553 ++cp;
554 }
555
556 if (*cp == '$')
557 {
558 if (!type_name)
56c47203 559 type_name = symbol_list_n_type_name_get (current_rule, location, 0);
e9955c83 560 if (!type_name && typed)
56c47203 561 complain_at (location, _("$$ of `%s' has no declared type"),
97650f4e 562 current_rule->sym->tag);
e9955c83
AD
563 if (!type_name)
564 type_name = "";
565 obstack_fgrow1 (&string_obstack,
566 "]b4_lhs_value([%s])[", type_name);
567 }
db2cc12f 568 else if (('0' <= *cp && *cp <= '9') || *cp == '-')
e9955c83
AD
569 {
570 int n = strtol (cp, &cp, 10);
571
572 if (n > rule_length)
56c47203 573 complain_at (location, _("invalid value: %s%d"), "$", n);
e9955c83
AD
574 else
575 {
576 if (!type_name && n > 0)
56c47203
AD
577 type_name = symbol_list_n_type_name_get (current_rule, location,
578 n);
e9955c83 579 if (!type_name && typed)
56c47203 580 complain_at (location, _("$%d of `%s' has no declared type"),
97650f4e 581 n, current_rule->sym->tag);
e9955c83
AD
582 if (!type_name)
583 type_name = "";
584 obstack_fgrow3 (&string_obstack,
585 "]b4_rhs_value([%d], [%d], [%s])[",
586 rule_length, n, type_name);
587 }
588 }
589 else
590 {
366eea36 591 complain_at (location, _("%s is invalid"), quote (text));
9280d3ef
AD
592 }
593}
594
595
366eea36
AD
596/*---------------------------------------------------------------.
597| TEXT is expexted tp be $$ in some code associated to a symbol: |
598| destructor or printer. |
599`---------------------------------------------------------------*/
9280d3ef 600
f25bfb75 601static inline void
366eea36 602handle_symbol_code_dollar (char *text, location_t location)
9280d3ef 603{
366eea36 604 char *cp = text + 1;
9280d3ef 605 if (*cp == '$')
366eea36 606 obstack_sgrow (&string_obstack, "]b4_dollar_dollar[");
9280d3ef 607 else
366eea36 608 complain_at (location, _("%s is invalid"), quote (text));
e9955c83
AD
609}
610
f25bfb75
AD
611
612/*-----------------------------------------------------------------.
613| Dispatch onto handle_action_dollar, or handle_destructor_dollar, |
614| depending upon CODE_KIND. |
615`-----------------------------------------------------------------*/
e9955c83
AD
616
617static void
f25bfb75
AD
618handle_dollar (braced_code_t braced_code_kind,
619 char *text, location_t location)
620{
621 switch (braced_code_kind)
622 {
623 case action_braced_code:
624 handle_action_dollar (text, location);
625 break;
626
627 case destructor_braced_code:
366eea36
AD
628 case printer_braced_code:
629 handle_symbol_code_dollar (text, location);
f25bfb75
AD
630 break;
631 }
632}
633
634
635/*------------------------------------------------------.
636| TEXT is a location token (i.e., a `@...'). Output to |
637| STRING_OBSTACK a reference to this location. |
638`------------------------------------------------------*/
639
640static inline void
641handle_action_at (char *text, location_t location)
e9955c83 642{
366eea36 643 char *cp = text + 1;
e9955c83 644 locations_flag = 1;
e9955c83 645
366eea36 646 if (*cp == '$')
e9955c83
AD
647 {
648 obstack_sgrow (&string_obstack, "]b4_lhs_location[");
649 }
db2cc12f 650 else if (('0' <= *cp && *cp <= '9') || *cp == '-')
e9955c83 651 {
366eea36 652 int n = strtol (cp, &cp, 10);
dafdc66f 653
e9955c83 654 if (n > rule_length)
f25bfb75 655 complain_at (location, _("invalid value: %s%d"), "@", n);
e9955c83
AD
656 else
657 obstack_fgrow2 (&string_obstack, "]b4_rhs_location([%d], [%d])[",
658 rule_length, n);
659 }
660 else
661 {
366eea36 662 complain_at (location, _("%s is invalid"), quote (text));
f25bfb75
AD
663 }
664}
665
666
366eea36
AD
667/*---------------------------------------------------------------.
668| TEXT is expexted tp be @$ in some code associated to a symbol: |
669| destructor or printer. |
670`---------------------------------------------------------------*/
f25bfb75
AD
671
672static inline void
366eea36 673handle_symbol_code_at (char *text, location_t location)
f25bfb75 674{
366eea36
AD
675 char *cp = text + 1;
676 if (*cp == '$')
677 obstack_sgrow (&string_obstack, "]b4_at_dollar[");
f25bfb75 678 else
366eea36 679 complain_at (location, _("%s is invalid"), quote (text));
e9955c83 680}
4cdb01db 681
f25bfb75
AD
682
683/*-------------------------------------------------------------------.
684| Dispatch onto handle_action_at, or handle_destructor_at, depending |
685| upon CODE_KIND. |
686`-------------------------------------------------------------------*/
687
688static void
689handle_at (braced_code_t braced_code_kind,
690 char *text, location_t location)
691{
692 switch (braced_code_kind)
693 {
694 case action_braced_code:
695 handle_action_at (text, location);
696 break;
697
698 case destructor_braced_code:
366eea36
AD
699 case printer_braced_code:
700 handle_symbol_code_at (text, location);
f25bfb75
AD
701 break;
702 }
703}
704
705
706/*-------------------------.
707| Initialize the scanner. |
708`-------------------------*/
709
1d6412ad
AD
710void
711scanner_initialize (void)
712{
713 obstack_init (&string_obstack);
714}
715
716
f25bfb75
AD
717/*-----------------------------------------------.
718| Free all the memory allocated to the scanner. |
719`-----------------------------------------------*/
720
4cdb01db
AD
721void
722scanner_free (void)
723{
724 obstack_free (&string_obstack, 0);
536545f3
AD
725 /* Reclaim Flex's buffers. */
726 yy_delete_buffer (YY_CURRENT_BUFFER);
4cdb01db 727}