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