]> git.saurik.com Git - bison.git/blame - src/scan-gram.l
(AC_PROG_LEX): Use instead of AM_PROG_LEX.
[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
d33cb3ae
PE
90static void handle_dollar (braced_code_t code_kind,
91 char *cp, location_t location);
92static void handle_at (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;
ae7453f2 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;
ae7453f2 138 "%parse-param" return PERCENT_PARSE_PARAM;
efcb44dd 139 "%prec" { rule_length--; return PERCENT_PREC; }
366eea36 140 "%printer" return PERCENT_PRINTER;
e9955c83
AD
141 "%pure"[-_]"parser" return PERCENT_PURE_PARSER;
142 "%right" return PERCENT_RIGHT;
ae7453f2 143 "%lex-param" return PERCENT_LEX_PARAM;
e9955c83
AD
144 "%skeleton" return PERCENT_SKELETON;
145 "%start" return PERCENT_START;
146 "%term" return PERCENT_TOKEN;
147 "%token" return PERCENT_TOKEN;
148 "%token"[-_]"table" return PERCENT_TOKEN_TABLE;
149 "%type" return PERCENT_TYPE;
150 "%union" return PERCENT_UNION;
151 "%verbose" return PERCENT_VERBOSE;
152 "%yacc" return PERCENT_YACC;
153
154 "=" return EQUAL;
efcb44dd
PE
155 ":" { rule_length = 0; return COLON; }
156 "|" { rule_length = 0; return PIPE; }
ae7453f2 157 "," return COMMA;
e9955c83
AD
158 ";" return SEMICOLON;
159
160 {eols} YY_LINES; YY_STEP;
161 {blanks} YY_STEP;
162 {id} {
39f41916 163 yylval->symbol = symbol_get (yytext, *yylloc);
efcb44dd 164 rule_length++;
e9955c83
AD
165 return ID;
166 }
167
168 {int} yylval->integer = strtol (yytext, 0, 10); return INT;
169
170 /* Characters. We don't check there is only one. */
db2cc12f 171 "'" YY_OBS_GROW; yy_push_state (SC_ESCAPED_CHARACTER);
e9955c83
AD
172
173 /* Strings. */
db2cc12f 174 "\"" YY_OBS_GROW; yy_push_state (SC_ESCAPED_STRING);
e9955c83
AD
175
176 /* Comments. */
177 "/*" yy_push_state (SC_COMMENT);
178 "//".* YY_STEP;
179
180 /* Prologue. */
1d6412ad 181 "%{" yy_push_state (SC_PROLOGUE);
e9955c83
AD
182
183 /* Code in between braces. */
1d6412ad 184 "{" YY_OBS_GROW; ++braces_level; yy_push_state (SC_BRACED_CODE);
e9955c83
AD
185
186 /* A type. */
4cdb01db 187 "<"[^>]+">" {
4cdb01db
AD
188 obstack_grow (&string_obstack, yytext + 1, yyleng - 2);
189 YY_OBS_FINISH;
190 yylval->string = last_string;
191 return TYPE;
192 }
193
e9955c83
AD
194
195 "%%" {
196 if (++percent_percent_count == 2)
197 yy_push_state (SC_EPILOGUE);
198 return PERCENT_PERCENT;
199 }
200
201 . {
202 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 203 fprintf (stderr, _(": invalid character: `%c'\n"), *yytext);
e9955c83
AD
204 YY_STEP;
205 }
206}
207
208
209 /*------------------------------------------------------------.
210 | Whatever the start condition (but those which correspond to |
211 | entity `swallowed' by Bison: SC_ESCAPED_STRING and |
212 | SC_ESCAPED_CHARACTER), no M4 character must escape as is. |
213 `------------------------------------------------------------*/
214
215<SC_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
216{
1d6412ad
AD
217 \[ if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@<:@");
218 \] if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@:>@");
e9955c83
AD
219}
220
221
222
223 /*-----------------------------------------------------------.
224 | Scanning a C comment. The initial `/ *' is already eaten. |
225 `-----------------------------------------------------------*/
226
227<SC_COMMENT>
228{
229 "*/" { /* End of the comment. */
230 if (yy_top_state () == INITIAL)
231 {
232 YY_STEP;
233 }
234 else
235 {
44995b2e 236 YY_OBS_GROW;
e9955c83
AD
237 }
238 yy_pop_state ();
239 }
240
44995b2e
AD
241 [^\[\]*\n\r]+ if (yy_top_state () != INITIAL) YY_OBS_GROW;
242 {eols} if (yy_top_state () != INITIAL) YY_OBS_GROW; YY_LINES;
243 . /* Stray `*'. */if (yy_top_state () != INITIAL) YY_OBS_GROW;
e9955c83
AD
244
245 <<EOF>> {
246 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 247 fprintf (stderr, _(": unexpected end of file in a comment\n"));
e9955c83
AD
248 yy_pop_state ();
249 }
250}
251
252
253 /*----------------------------------------------------------------.
254 | Scanning a C string, including its escapes. The initial `"' is |
255 | already eaten. |
256 `----------------------------------------------------------------*/
257
258<SC_ESCAPED_STRING>
259{
db2cc12f 260 "\"" {
e9955c83 261 assert (yy_top_state () == INITIAL);
44995b2e
AD
262 YY_OBS_GROW;
263 YY_OBS_FINISH;
4cdb01db 264 yylval->string = last_string;
e9955c83 265 yy_pop_state ();
efcb44dd 266 rule_length++;
e9955c83
AD
267 return STRING;
268 }
269
44995b2e 270 [^\"\n\r\\]+ YY_OBS_GROW;
e9955c83
AD
271
272 {eols} obstack_1grow (&string_obstack, '\n'); YY_LINES;
273
274 <<EOF>> {
275 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 276 fprintf (stderr, _(": unexpected end of file in a string\n"));
e9955c83 277 assert (yy_top_state () == INITIAL);
44995b2e 278 YY_OBS_FINISH;
4cdb01db 279 yylval->string = last_string;
e9955c83
AD
280 yy_pop_state ();
281 return STRING;
282 }
283}
284
285 /*---------------------------------------------------------------.
286 | Scanning a C character, decoding its escapes. The initial "'" |
287 | is already eaten. |
288 `---------------------------------------------------------------*/
289
290<SC_ESCAPED_CHARACTER>
291{
db2cc12f 292 "'" {
44995b2e 293 YY_OBS_GROW;
e9955c83
AD
294 assert (yy_top_state () == INITIAL);
295 {
44995b2e 296 YY_OBS_FINISH;
39f41916 297 yylval->symbol = symbol_get (last_string, *yylloc);
e776192e 298 symbol_class_set (yylval->symbol, token_sym, *yylloc);
e68d4575
PE
299 symbol_user_token_number_set (yylval->symbol,
300 (unsigned char) last_string[1], *yylloc);
44995b2e 301 YY_OBS_FREE;
e9955c83 302 yy_pop_state ();
efcb44dd 303 rule_length++;
e9955c83
AD
304 return ID;
305 }
306 }
307
db2cc12f 308 [^\n\r\\] YY_OBS_GROW;
e9955c83
AD
309
310 {eols} obstack_1grow (&string_obstack, '\n'); YY_LINES;
311
312 <<EOF>> {
313 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 314 fprintf (stderr, _(": unexpected end of file in a character\n"));
e9955c83 315 assert (yy_top_state () == INITIAL);
44995b2e 316 YY_OBS_FINISH;
4cdb01db 317 yylval->string = last_string;
e9955c83
AD
318 yy_pop_state ();
319 return CHARACTER;
320 }
321}
322
323
324 /*----------------------------.
325 | Decode escaped characters. |
326 `----------------------------*/
327
328<SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
329{
330 \\[0-7]{3} {
331 long c = strtol (yytext + 1, 0, 8);
332 if (c > 255)
333 {
334 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 335 fprintf (stderr, _(": invalid escape: %s\n"), quote (yytext));
e9955c83
AD
336 YY_STEP;
337 }
338 else
339 obstack_1grow (&string_obstack, c);
340 }
341
342 \\x[0-9a-fA-F]{2} {
343 obstack_1grow (&string_obstack, strtol (yytext + 2, 0, 16));
344 }
345
346 \\a obstack_1grow (&string_obstack, '\a');
347 \\b obstack_1grow (&string_obstack, '\b');
348 \\f obstack_1grow (&string_obstack, '\f');
349 \\n obstack_1grow (&string_obstack, '\n');
350 \\r obstack_1grow (&string_obstack, '\r');
351 \\t obstack_1grow (&string_obstack, '\t');
352 \\v obstack_1grow (&string_obstack, '\v');
eb714592 353 \\[\\""''] obstack_1grow (&string_obstack, yytext[1]);
4f25ebb0 354 \\(.|\n) {
e9955c83 355 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 356 fprintf (stderr, _(": unrecognized escape: %s\n"), quote (yytext));
44995b2e 357 YY_OBS_GROW;
e9955c83 358 }
4f25ebb0
AD
359 /* FLex wants this rule, in case of a `\<<EOF>>'. */
360 \\ YY_OBS_GROW;
e9955c83
AD
361}
362
363
364 /*----------------------------------------------------------.
365 | Scanning a C character without decoding its escapes. The |
366 | initial "'" is already eaten. |
367 `----------------------------------------------------------*/
368
369<SC_CHARACTER>
370{
db2cc12f 371 "'" {
44995b2e 372 YY_OBS_GROW;
e9955c83
AD
373 assert (yy_top_state () != INITIAL);
374 yy_pop_state ();
375 }
376
4f25ebb0
AD
377 [^\[\]\'\n\r\\]+ YY_OBS_GROW;
378 \\(.|\n) YY_OBS_GROW;
379 /* FLex wants this rule, in case of a `\<<EOF>>'. */
380 \\ YY_OBS_GROW;
e9955c83 381
44995b2e 382 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
383
384 <<EOF>> {
385 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 386 fprintf (stderr, _(": unexpected end of file in a character\n"));
e9955c83
AD
387 assert (yy_top_state () != INITIAL);
388 yy_pop_state ();
389 }
390}
391
392
393 /*----------------------------------------------------------------.
394 | Scanning a C string, without decoding its escapes. The initial |
395 | `"' is already eaten. |
396 `----------------------------------------------------------------*/
397
398<SC_STRING>
399{
db2cc12f 400 "\"" {
e9955c83 401 assert (yy_top_state () != INITIAL);
44995b2e 402 YY_OBS_GROW;
e9955c83
AD
403 yy_pop_state ();
404 }
405
44995b2e 406 [^\[\]\"\n\r\\]+ YY_OBS_GROW;
4f25ebb0
AD
407 \\(.|\n) YY_OBS_GROW;
408 /* FLex wants this rule, in case of a `\<<EOF>>'. */
409 \\ YY_OBS_GROW;
e9955c83 410
44995b2e 411 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
412
413 <<EOF>> {
414 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 415 fprintf (stderr, _(": unexpected end of file in a string\n"));
e9955c83
AD
416 assert (yy_top_state () != INITIAL);
417 yy_pop_state ();
418 }
419}
420
421
422 /*---------------------------------------------------.
423 | Strings, comments etc. can be found in user code. |
424 `---------------------------------------------------*/
425
426<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
427{
428 /* Characters. We don't check there is only one. */
db2cc12f 429 "'" YY_OBS_GROW; yy_push_state (SC_CHARACTER);
e9955c83
AD
430
431 /* Strings. */
db2cc12f 432 "\"" YY_OBS_GROW; yy_push_state (SC_STRING);
e9955c83
AD
433
434 /* Comments. */
44995b2e
AD
435 "/*" YY_OBS_GROW; yy_push_state (SC_COMMENT);
436 "//".* YY_OBS_GROW;
4f25ebb0
AD
437
438 /* Not comments. */
439 "/" YY_OBS_GROW;
e9955c83
AD
440}
441
442
443 /*---------------------------------------------------------------.
444 | Scanning some code in braces (%union and actions). The initial |
445 | "{" is already eaten. |
446 `---------------------------------------------------------------*/
447
448<SC_BRACED_CODE>
449{
450 "}" {
44995b2e 451 YY_OBS_GROW;
e9955c83
AD
452 if (--braces_level == 0)
453 {
454 yy_pop_state ();
44995b2e 455 YY_OBS_FINISH;
4cdb01db 456 yylval->string = last_string;
efcb44dd 457 rule_length++;
e9955c83
AD
458 return BRACED_CODE;
459 }
460 }
461
44995b2e 462 "{" YY_OBS_GROW; braces_level++;
e9955c83 463
f25bfb75
AD
464 "$"("<"[^>]+">")?(-?[0-9]+|"$") { handle_dollar (current_braced_code,
465 yytext, *yylloc); }
466 "@"(-?[0-9]+|"$") { handle_at (current_braced_code,
467 yytext, *yylloc); }
e9955c83 468
6c35d22c 469 [^$@\[\]/\'\"\{\}\n\r]+ YY_OBS_GROW;
44995b2e 470 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
471
472 /* A lose $, or /, or etc. */
44995b2e 473 . YY_OBS_GROW;
e9955c83
AD
474
475 <<EOF>> {
476 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 477 fprintf (stderr, _(": unexpected end of file in a braced code\n"));
e9955c83 478 yy_pop_state ();
44995b2e 479 YY_OBS_FINISH;
4cdb01db
AD
480 yylval->string = last_string;
481 return BRACED_CODE;
e9955c83
AD
482 }
483
484}
485
486
487 /*--------------------------------------------------------------.
488 | Scanning some prologue: from "%{" (already scanned) to "%}". |
489 `--------------------------------------------------------------*/
490
491<SC_PROLOGUE>
492{
493 "%}" {
494 yy_pop_state ();
44995b2e 495 YY_OBS_FINISH;
4cdb01db 496 yylval->string = last_string;
e9955c83
AD
497 return PROLOGUE;
498 }
499
4f25ebb0
AD
500 [^%\[\]/\'\"\n\r]+ YY_OBS_GROW;
501 "%" YY_OBS_GROW;
502 {eols} YY_OBS_GROW; YY_LINES;
e9955c83
AD
503
504 <<EOF>> {
505 LOCATION_PRINT (stderr, *yylloc);
db2cc12f 506 fprintf (stderr, _(": unexpected end of file in a prologue\n"));
e9955c83 507 yy_pop_state ();
44995b2e 508 YY_OBS_FINISH;
4cdb01db 509 yylval->string = last_string;
e9955c83
AD
510 return PROLOGUE;
511 }
e9955c83
AD
512}
513
514
515 /*---------------------------------------------------------------.
516 | Scanning the epilogue (everything after the second "%%", which |
517 | has already been eaten. |
518 `---------------------------------------------------------------*/
519
520<SC_EPILOGUE>
521{
44995b2e 522 ([^\[\]]|{eols})+ YY_OBS_GROW;
e9955c83
AD
523
524 <<EOF>> {
525 yy_pop_state ();
44995b2e 526 YY_OBS_FINISH;
4cdb01db 527 yylval->string = last_string;
e9955c83
AD
528 return EPILOGUE;
529 }
530}
531
532
533%%
534
535/*------------------------------------------------------------------.
366eea36 536| TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
e9955c83
AD
537| |
538| Possible inputs: $[<TYPENAME>]($|integer) |
539| |
540| Output to the STRING_OBSTACK a reference to this semantic value. |
541`------------------------------------------------------------------*/
542
f25bfb75 543static inline void
366eea36 544handle_action_dollar (char *text, location_t location)
e9955c83
AD
545{
546 const char *type_name = NULL;
366eea36 547 char *cp = text + 1;
e9955c83
AD
548
549 /* Get the type name if explicit. */
550 if (*cp == '<')
551 {
552 type_name = ++cp;
553 while (*cp != '>')
554 ++cp;
555 *cp = '\0';
556 ++cp;
557 }
558
559 if (*cp == '$')
560 {
561 if (!type_name)
56c47203 562 type_name = symbol_list_n_type_name_get (current_rule, location, 0);
e9955c83 563 if (!type_name && typed)
56c47203 564 complain_at (location, _("$$ of `%s' has no declared type"),
97650f4e 565 current_rule->sym->tag);
e9955c83
AD
566 if (!type_name)
567 type_name = "";
568 obstack_fgrow1 (&string_obstack,
569 "]b4_lhs_value([%s])[", type_name);
570 }
db2cc12f 571 else if (('0' <= *cp && *cp <= '9') || *cp == '-')
e9955c83
AD
572 {
573 int n = strtol (cp, &cp, 10);
574
575 if (n > rule_length)
56c47203 576 complain_at (location, _("invalid value: %s%d"), "$", n);
e9955c83
AD
577 else
578 {
579 if (!type_name && n > 0)
56c47203
AD
580 type_name = symbol_list_n_type_name_get (current_rule, location,
581 n);
e9955c83 582 if (!type_name && typed)
56c47203 583 complain_at (location, _("$%d of `%s' has no declared type"),
97650f4e 584 n, current_rule->sym->tag);
e9955c83
AD
585 if (!type_name)
586 type_name = "";
587 obstack_fgrow3 (&string_obstack,
588 "]b4_rhs_value([%d], [%d], [%s])[",
589 rule_length, n, type_name);
590 }
591 }
592 else
593 {
366eea36 594 complain_at (location, _("%s is invalid"), quote (text));
9280d3ef
AD
595 }
596}
597
598
366eea36
AD
599/*---------------------------------------------------------------.
600| TEXT is expexted tp be $$ in some code associated to a symbol: |
601| destructor or printer. |
602`---------------------------------------------------------------*/
9280d3ef 603
f25bfb75 604static inline void
366eea36 605handle_symbol_code_dollar (char *text, location_t location)
9280d3ef 606{
366eea36 607 char *cp = text + 1;
9280d3ef 608 if (*cp == '$')
366eea36 609 obstack_sgrow (&string_obstack, "]b4_dollar_dollar[");
9280d3ef 610 else
366eea36 611 complain_at (location, _("%s is invalid"), quote (text));
e9955c83
AD
612}
613
f25bfb75
AD
614
615/*-----------------------------------------------------------------.
616| Dispatch onto handle_action_dollar, or handle_destructor_dollar, |
617| depending upon CODE_KIND. |
618`-----------------------------------------------------------------*/
e9955c83
AD
619
620static void
f25bfb75
AD
621handle_dollar (braced_code_t braced_code_kind,
622 char *text, location_t location)
623{
624 switch (braced_code_kind)
625 {
626 case action_braced_code:
627 handle_action_dollar (text, location);
628 break;
629
630 case destructor_braced_code:
366eea36
AD
631 case printer_braced_code:
632 handle_symbol_code_dollar (text, location);
f25bfb75
AD
633 break;
634 }
635}
636
637
638/*------------------------------------------------------.
639| TEXT is a location token (i.e., a `@...'). Output to |
640| STRING_OBSTACK a reference to this location. |
641`------------------------------------------------------*/
642
643static inline void
644handle_action_at (char *text, location_t location)
e9955c83 645{
366eea36 646 char *cp = text + 1;
e9955c83 647 locations_flag = 1;
e9955c83 648
366eea36 649 if (*cp == '$')
e9955c83
AD
650 {
651 obstack_sgrow (&string_obstack, "]b4_lhs_location[");
652 }
db2cc12f 653 else if (('0' <= *cp && *cp <= '9') || *cp == '-')
e9955c83 654 {
366eea36 655 int n = strtol (cp, &cp, 10);
dafdc66f 656
e9955c83 657 if (n > rule_length)
f25bfb75 658 complain_at (location, _("invalid value: %s%d"), "@", n);
e9955c83
AD
659 else
660 obstack_fgrow2 (&string_obstack, "]b4_rhs_location([%d], [%d])[",
661 rule_length, n);
662 }
663 else
664 {
366eea36 665 complain_at (location, _("%s is invalid"), quote (text));
f25bfb75
AD
666 }
667}
668
669
366eea36
AD
670/*---------------------------------------------------------------.
671| TEXT is expexted tp be @$ in some code associated to a symbol: |
672| destructor or printer. |
673`---------------------------------------------------------------*/
f25bfb75
AD
674
675static inline void
366eea36 676handle_symbol_code_at (char *text, location_t location)
f25bfb75 677{
366eea36
AD
678 char *cp = text + 1;
679 if (*cp == '$')
680 obstack_sgrow (&string_obstack, "]b4_at_dollar[");
f25bfb75 681 else
366eea36 682 complain_at (location, _("%s is invalid"), quote (text));
e9955c83 683}
4cdb01db 684
f25bfb75
AD
685
686/*-------------------------------------------------------------------.
687| Dispatch onto handle_action_at, or handle_destructor_at, depending |
688| upon CODE_KIND. |
689`-------------------------------------------------------------------*/
690
691static void
692handle_at (braced_code_t braced_code_kind,
693 char *text, location_t location)
694{
695 switch (braced_code_kind)
696 {
697 case action_braced_code:
698 handle_action_at (text, location);
699 break;
700
701 case destructor_braced_code:
366eea36
AD
702 case printer_braced_code:
703 handle_symbol_code_at (text, location);
f25bfb75
AD
704 break;
705 }
706}
707
708
709/*-------------------------.
710| Initialize the scanner. |
711`-------------------------*/
712
1d6412ad
AD
713void
714scanner_initialize (void)
715{
716 obstack_init (&string_obstack);
717}
718
719
f25bfb75
AD
720/*-----------------------------------------------.
721| Free all the memory allocated to the scanner. |
722`-----------------------------------------------*/
723
4cdb01db
AD
724void
725scanner_free (void)
726{
727 obstack_free (&string_obstack, 0);
536545f3
AD
728 /* Reclaim Flex's buffers. */
729 yy_delete_buffer (YY_CURRENT_BUFFER);
4cdb01db 730}