]> git.saurik.com Git - bison.git/blame - src/scan-gram.l
(CHARACTER): Remove unused token. All uses removed.
[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"
d8d3f94a 27#include "mbswidth.h"
e9955c83
AD
28#include "complain.h"
29#include "quote.h"
30#include "getargs.h"
31#include "gram.h"
32#include "reader.h"
33
34/* Each time we match a string, move the end cursor to its end. */
8efe435c
AD
35#define YY_USER_INIT \
36do { \
37 LOCATION_RESET (*yylloc); \
1a715ef2 38 yylloc->file = infile; \
8efe435c
AD
39 /* This is only to avoid GCC warnings. */ \
40 if (yycontrol) {;}; \
41} while (0)
42
d8d3f94a
PE
43#define YY_USER_ACTION extend_location (yylloc, yytext, yyleng);
44#define YY_STEP LOCATION_STEP (*yylloc)
45
46#define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size))
47
48
49/* Read bytes from FP into buffer BUF of size SIZE. Return the
50 number of bytes read. Remove '\r' from input, treating \r\n
51 and isolated \r as \n. */
52
53static size_t
54no_cr_read (FILE *fp, char *buf, size_t size)
55{
56 size_t s = fread (buf, 1, size, fp);
57 if (s)
58 {
59 char *w = memchr (buf, '\r', s);
60 if (w)
61 {
62 char const *r = ++w;
63 char const *lim = buf + s;
64
65 for (;;)
66 {
67 /* Found an '\r'. Treat it like '\n', but ignore any
68 '\n' that immediately follows. */
69 w[-1] = '\n';
70 if (r == lim)
71 {
72 int ch = getc (fp);
73 if (ch != '\n' && ungetc (ch, fp) != ch)
74 break;
75 }
76 else if (*r == '\n')
77 r++;
78
79 /* Copy until the next '\r'. */
80 do
81 {
82 if (r == lim)
83 return w - buf;
84 }
85 while ((*w++ = *r++) != '\r');
86 }
87
88 return w - buf;
89 }
90 }
91
92 return s;
93}
94
95
96/* Extend *LOC to account for token TOKEN of size SIZE. */
97
98static void
99extend_location (location_t *loc, char const *token, int size)
100{
101 int line = loc->last_line;
102 int column = loc->last_column;
103 char const *p0 = token;
104 char const *p = token;
105 char const *lim = token + size;
106
107 for (p = token; p < lim; p++)
108 switch (*p)
109 {
110 case '\r':
111 /* \r shouldn't survive no_cr_read. */
112 abort ();
113
114 case '\n':
115 line++;
116 column = 1;
117 p0 = p + 1;
118 break;
119
120 case '\t':
121 column += mbsnwidth (p0, p - p0, 0);
122 column += 8 - ((column - 1) & 7);
123 p0 = p + 1;
124 break;
125 }
126
127 loc->last_line = line;
128 loc->last_column = column + mbsnwidth (p0, p - p0, 0);
129}
130
131
8e6ef483
PE
132/* Report an unexpected end of file at LOC. A token or comment began
133 with TOKEN_START, but an end of file was encountered and the
134 expected TOKEN_END was missing. */
135
136static void
137unexpected_end_of_file (location_t loc,
138 char const *token_start, char const *token_end)
139{
140 complain_at (loc, _("unexpected end of file in `%s ... %s'"),
141 token_start, token_end);
142}
143
144
e9955c83 145
44995b2e
AD
146/* STRING_OBSTACK -- Used to store all the characters that we need to
147 keep (to construct ID, STRINGS etc.). Use the following macros to
148 use it.
149
1d6412ad
AD
150 Use YY_OBS_GROW to append what has just been matched, and
151 YY_OBS_FINISH to end the string (it puts the ending 0).
152 YY_OBS_FINISH also stores this string in LAST_STRING, which can be
153 used, and which is used by YY_OBS_FREE to free the last string. */
44995b2e
AD
154
155static struct obstack string_obstack;
156char *last_string;
157
44995b2e
AD
158#define YY_OBS_GROW \
159 obstack_grow (&string_obstack, yytext, yyleng)
160
161#define YY_OBS_FINISH \
162 do { \
163 obstack_1grow (&string_obstack, '\0'); \
164 last_string = obstack_finish (&string_obstack); \
44995b2e
AD
165 } while (0)
166
167#define YY_OBS_FREE \
168 do { \
169 obstack_free (&string_obstack, last_string); \
170 } while (0)
e9955c83 171
4cdb01db
AD
172void
173scanner_last_string_free (void)
174{
175 YY_OBS_FREE;
176}
177
178
e9955c83
AD
179static int percent_percent_count = 0;
180
efcb44dd
PE
181/* Within well-formed rules, RULE_LENGTH is the number of values in
182 the current rule so far, which says where to find `$0' with respect
183 to the top of the stack. It is not the same as the rule->length in
184 the case of mid rule actions.
185
186 Outside of well-formed rules, RULE_LENGTH has an undefined value. */
187static int rule_length;
188
d33cb3ae
PE
189static void handle_dollar (braced_code_t code_kind,
190 char *cp, location_t location);
191static void handle_at (braced_code_t code_kind,
192 char *cp, location_t location);
900c5db5 193static void handle_syncline (char *args, location_t *location);
d8d3f94a 194static int convert_ucn_to_byte (char const *hex_text);
e9955c83
AD
195
196%}
d8d3f94a 197%x SC_COMMENT SC_LINE_COMMENT SC_YACC_COMMENT
e9955c83
AD
198%x SC_STRING SC_CHARACTER
199%x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
200%x SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
201
29c01725
AD
202letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
203id {letter}({letter}|[0-9])*
204directive %{letter}({letter}|[0-9]|-)*
205int [0-9]+
d8d3f94a
PE
206
207/* POSIX says that a tag must be both an id and a C union member, but
208 historically almost any character is allowed in a tag. We disallow
209 NUL and newline, as this simplifies our implementation. */
210tag [^\0\n>]+
211
212/* Zero or more instances of backslash-newline. Following GCC, allow
213 white space between the backslash and the newline. */
214splice (\\[ \f\t\v]*\n)*
e9955c83
AD
215
216%%
217%{
1a9e39f1
PE
218 int braces_level IF_LINT (= 0);
219
e9955c83
AD
220 /* At each yylex invocation, mark the current position as the
221 start of the next token. */
e9955c83 222 YY_STEP;
e9955c83
AD
223%}
224
225
226 /*----------------------------.
227 | Scanning Bison directives. |
228 `----------------------------*/
229<INITIAL>
230{
231 "%binary" return PERCENT_NONASSOC;
232 "%debug" return PERCENT_DEBUG;
233 "%define" return PERCENT_DEFINE;
234 "%defines" return PERCENT_DEFINES;
9280d3ef 235 "%destructor" return PERCENT_DESTRUCTOR;
676385e2 236 "%dprec" return PERCENT_DPREC;
e9955c83
AD
237 "%error"[-_]"verbose" return PERCENT_ERROR_VERBOSE;
238 "%expect" return PERCENT_EXPECT;
239 "%file-prefix" return PERCENT_FILE_PREFIX;
240 "%fixed"[-_]"output"[-_]"files" return PERCENT_YACC;
ae7453f2 241 "%glr-parser" return PERCENT_GLR_PARSER;
e9955c83
AD
242 "%left" return PERCENT_LEFT;
243 "%locations" return PERCENT_LOCATIONS;
676385e2 244 "%merge" return PERCENT_MERGE;
e9955c83
AD
245 "%name"[-_]"prefix" return PERCENT_NAME_PREFIX;
246 "%no"[-_]"lines" return PERCENT_NO_LINES;
247 "%nonassoc" return PERCENT_NONASSOC;
248 "%nterm" return PERCENT_NTERM;
249 "%output" return PERCENT_OUTPUT;
ae7453f2 250 "%parse-param" return PERCENT_PARSE_PARAM;
d8d3f94a 251 "%prec" rule_length--; return PERCENT_PREC;
366eea36 252 "%printer" return PERCENT_PRINTER;
e9955c83
AD
253 "%pure"[-_]"parser" return PERCENT_PURE_PARSER;
254 "%right" return PERCENT_RIGHT;
ae7453f2 255 "%lex-param" return PERCENT_LEX_PARAM;
e9955c83
AD
256 "%skeleton" return PERCENT_SKELETON;
257 "%start" return PERCENT_START;
258 "%term" return PERCENT_TOKEN;
259 "%token" return PERCENT_TOKEN;
260 "%token"[-_]"table" return PERCENT_TOKEN_TABLE;
261 "%type" return PERCENT_TYPE;
262 "%union" return PERCENT_UNION;
263 "%verbose" return PERCENT_VERBOSE;
264 "%yacc" return PERCENT_YACC;
265
29c01725
AD
266 {directive} {
267 complain_at (*yylloc, _("invalid directive: %s"), quote (yytext));
268 YY_STEP;
269 }
270
900c5db5
AD
271 ^"#line "{int}" \""[^\"]*"\"\n" handle_syncline (yytext + strlen ("#line "), yylloc); YY_STEP;
272
e9955c83 273 "=" return EQUAL;
d8d3f94a
PE
274 ":" rule_length = 0; return COLON;
275 "|" rule_length = 0; return PIPE;
ae7453f2 276 "," return COMMA;
e9955c83
AD
277 ";" return SEMICOLON;
278
d8d3f94a
PE
279 [ \f\n\t\v]+ YY_STEP;
280
e9955c83 281 {id} {
39f41916 282 yylval->symbol = symbol_get (yytext, *yylloc);
efcb44dd 283 rule_length++;
e9955c83
AD
284 return ID;
285 }
286
d8d3f94a
PE
287 {int} {
288 unsigned long num;
289 errno = 0;
290 num = strtoul (yytext, 0, 10);
291 if (INT_MAX < num || errno)
292 {
98f2caaa 293 complain_at (*yylloc, _("integer out of range: %s"), quote (yytext));
d8d3f94a
PE
294 num = INT_MAX;
295 }
296 yylval->integer = num;
297 return INT;
298 }
e9955c83
AD
299
300 /* Characters. We don't check there is only one. */
db2cc12f 301 "'" YY_OBS_GROW; yy_push_state (SC_ESCAPED_CHARACTER);
e9955c83
AD
302
303 /* Strings. */
db2cc12f 304 "\"" YY_OBS_GROW; yy_push_state (SC_ESCAPED_STRING);
e9955c83
AD
305
306 /* Comments. */
d8d3f94a 307 "/*" BEGIN SC_YACC_COMMENT;
e9955c83
AD
308 "//".* YY_STEP;
309
310 /* Prologue. */
1d6412ad 311 "%{" yy_push_state (SC_PROLOGUE);
e9955c83
AD
312
313 /* Code in between braces. */
1a9e39f1 314 "{" YY_OBS_GROW; braces_level = 0; yy_push_state (SC_BRACED_CODE);
e9955c83
AD
315
316 /* A type. */
d8d3f94a 317 "<"{tag}">" {
4cdb01db
AD
318 obstack_grow (&string_obstack, yytext + 1, yyleng - 2);
319 YY_OBS_FINISH;
320 yylval->string = last_string;
321 return TYPE;
322 }
323
e9955c83
AD
324
325 "%%" {
326 if (++percent_percent_count == 2)
327 yy_push_state (SC_EPILOGUE);
328 return PERCENT_PERCENT;
329 }
330
331 . {
c4d720cd 332 complain_at (*yylloc, _("invalid character: %s"), quote (yytext));
e9955c83
AD
333 YY_STEP;
334 }
335}
336
337
d8d3f94a
PE
338 /*-------------------------------------------------------------------.
339 | Whatever the start condition (but those which correspond to |
340 | entities `swallowed' by Bison: SC_YACC_COMMENT, SC_ESCAPED_STRING, |
341 | and SC_ESCAPED_CHARACTER), no M4 character must escape as is. |
342 `-------------------------------------------------------------------*/
e9955c83 343
d8d3f94a 344<SC_COMMENT,SC_LINE_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
e9955c83 345{
d8d3f94a
PE
346 \[ obstack_sgrow (&string_obstack, "@<:@");
347 \] obstack_sgrow (&string_obstack, "@:>@");
e9955c83
AD
348}
349
350
d8d3f94a
PE
351 /*---------------------------------------------------------------.
352 | Scanning a Yacc comment. The initial `/ *' is already eaten. |
353 `---------------------------------------------------------------*/
e9955c83 354
d8d3f94a 355<SC_YACC_COMMENT>
e9955c83 356{
d8d3f94a
PE
357 "*/" {
358 YY_STEP;
359 BEGIN INITIAL;
e9955c83
AD
360 }
361
d8d3f94a
PE
362 [^*]+|"*" ;
363
364 <<EOF>> {
8e6ef483 365 unexpected_end_of_file (*yylloc, "/*", "*/");
d8d3f94a
PE
366 BEGIN INITIAL;
367 }
368}
369
370
371 /*------------------------------------------------------------.
372 | Scanning a C comment. The initial `/ *' is already eaten. |
373 `------------------------------------------------------------*/
374
375<SC_COMMENT>
376{
377 "*"{splice}"/" YY_OBS_GROW; yy_pop_state ();
378 [^*\[\]]+|"*" YY_OBS_GROW;
e9955c83
AD
379
380 <<EOF>> {
8e6ef483 381 unexpected_end_of_file (*yylloc, "/*", "*/");
e9955c83
AD
382 yy_pop_state ();
383 }
384}
385
386
d8d3f94a
PE
387 /*--------------------------------------------------------------.
388 | Scanning a line comment. The initial `//' is already eaten. |
389 `--------------------------------------------------------------*/
390
391<SC_LINE_COMMENT>
392{
393 "\n" YY_OBS_GROW; yy_pop_state ();
394 ([^\n\[\]]|{splice})+ YY_OBS_GROW;
395 <<EOF>> yy_pop_state ();
396}
397
398
e9955c83
AD
399 /*----------------------------------------------------------------.
400 | Scanning a C string, including its escapes. The initial `"' is |
401 | already eaten. |
402 `----------------------------------------------------------------*/
403
404<SC_ESCAPED_STRING>
405{
db2cc12f 406 "\"" {
e9955c83 407 assert (yy_top_state () == INITIAL);
44995b2e
AD
408 YY_OBS_GROW;
409 YY_OBS_FINISH;
4cdb01db 410 yylval->string = last_string;
e9955c83 411 yy_pop_state ();
efcb44dd 412 rule_length++;
e9955c83
AD
413 return STRING;
414 }
415
d8d3f94a 416 [^\"\\]+ YY_OBS_GROW;
e9955c83
AD
417
418 <<EOF>> {
8e6ef483 419 unexpected_end_of_file (*yylloc, "\"", "\"");
e9955c83 420 assert (yy_top_state () == INITIAL);
44995b2e 421 YY_OBS_FINISH;
4cdb01db 422 yylval->string = last_string;
e9955c83
AD
423 yy_pop_state ();
424 return STRING;
425 }
426}
427
428 /*---------------------------------------------------------------.
429 | Scanning a C character, decoding its escapes. The initial "'" |
430 | is already eaten. |
431 `---------------------------------------------------------------*/
432
433<SC_ESCAPED_CHARACTER>
434{
db2cc12f 435 "'" {
44995b2e 436 YY_OBS_GROW;
e9955c83
AD
437 assert (yy_top_state () == INITIAL);
438 {
44995b2e 439 YY_OBS_FINISH;
39f41916 440 yylval->symbol = symbol_get (last_string, *yylloc);
e776192e 441 symbol_class_set (yylval->symbol, token_sym, *yylloc);
e68d4575
PE
442 symbol_user_token_number_set (yylval->symbol,
443 (unsigned char) last_string[1], *yylloc);
44995b2e 444 YY_OBS_FREE;
e9955c83 445 yy_pop_state ();
efcb44dd 446 rule_length++;
e9955c83
AD
447 return ID;
448 }
449 }
450
c4d720cd 451 [^\'\\]+ YY_OBS_GROW;
e9955c83
AD
452
453 <<EOF>> {
8e6ef483 454 unexpected_end_of_file (*yylloc, "'", "'");
e9955c83 455 assert (yy_top_state () == INITIAL);
44995b2e 456 YY_OBS_FINISH;
4cdb01db 457 yylval->string = last_string;
e9955c83
AD
458 yy_pop_state ();
459 return CHARACTER;
460 }
461}
462
463
464 /*----------------------------.
465 | Decode escaped characters. |
466 `----------------------------*/
467
468<SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
469{
d8d3f94a
PE
470 \\[0-7]{1,3} {
471 unsigned long c = strtoul (yytext + 1, 0, 8);
472 if (UCHAR_MAX < c)
e9955c83 473 {
98f2caaa
PE
474 complain_at (*yylloc, _("invalid escape sequence: %s"),
475 quote (yytext));
e9955c83
AD
476 YY_STEP;
477 }
478 else
479 obstack_1grow (&string_obstack, c);
480 }
481
d8d3f94a
PE
482 \\x[0-9a-fA-F]+ {
483 unsigned long c;
484 errno = 0;
485 c = strtoul (yytext + 2, 0, 16);
486 if (UCHAR_MAX < c || errno)
487 {
98f2caaa
PE
488 complain_at (*yylloc, _("invalid escape sequence: %s"),
489 quote (yytext));
d8d3f94a
PE
490 YY_STEP;
491 }
492 else
493 obstack_1grow (&string_obstack, c);
e9955c83
AD
494 }
495
496 \\a obstack_1grow (&string_obstack, '\a');
497 \\b obstack_1grow (&string_obstack, '\b');
498 \\f obstack_1grow (&string_obstack, '\f');
499 \\n obstack_1grow (&string_obstack, '\n');
500 \\r obstack_1grow (&string_obstack, '\r');
501 \\t obstack_1grow (&string_obstack, '\t');
502 \\v obstack_1grow (&string_obstack, '\v');
c4d720cd 503 \\[\"\'?\\] obstack_1grow (&string_obstack, yytext[1]);
d8d3f94a
PE
504 \\(u|U[0-9a-fA-F]{4})[0-9a-fA-F]{4} {
505 int c = convert_ucn_to_byte (yytext);
506 if (c < 0)
507 {
98f2caaa
PE
508 complain_at (*yylloc, _("invalid escape sequence: %s"),
509 quote (yytext));
d8d3f94a
PE
510 YY_STEP;
511 }
512 else
513 obstack_1grow (&string_obstack, c);
514 }
4f25ebb0 515 \\(.|\n) {
98f2caaa
PE
516 complain_at (*yylloc, _("unrecognized escape sequence: %s"),
517 quote (yytext));
44995b2e 518 YY_OBS_GROW;
e9955c83 519 }
4f25ebb0
AD
520 /* FLex wants this rule, in case of a `\<<EOF>>'. */
521 \\ YY_OBS_GROW;
e9955c83
AD
522}
523
524
525 /*----------------------------------------------------------.
526 | Scanning a C character without decoding its escapes. The |
527 | initial "'" is already eaten. |
528 `----------------------------------------------------------*/
529
530<SC_CHARACTER>
531{
db2cc12f 532 "'" {
44995b2e 533 YY_OBS_GROW;
e9955c83
AD
534 assert (yy_top_state () != INITIAL);
535 yy_pop_state ();
536 }
537
d8d3f94a
PE
538 [^'\[\]\\]+ YY_OBS_GROW;
539 \\{splice}[^\[\]] YY_OBS_GROW;
540 {splice} YY_OBS_GROW;
541 /* Needed for `\<<EOF>>', `\\<<newline>>[', and `\\<<newline>>]'. */
4f25ebb0 542 \\ YY_OBS_GROW;
e9955c83 543
e9955c83 544 <<EOF>> {
8e6ef483 545 unexpected_end_of_file (*yylloc, "'", "'");
e9955c83
AD
546 assert (yy_top_state () != INITIAL);
547 yy_pop_state ();
548 }
549}
550
551
552 /*----------------------------------------------------------------.
553 | Scanning a C string, without decoding its escapes. The initial |
554 | `"' is already eaten. |
555 `----------------------------------------------------------------*/
556
557<SC_STRING>
558{
db2cc12f 559 "\"" {
e9955c83 560 assert (yy_top_state () != INITIAL);
44995b2e 561 YY_OBS_GROW;
e9955c83
AD
562 yy_pop_state ();
563 }
564
d8d3f94a
PE
565 [^\"\[\]\\]+ YY_OBS_GROW;
566 \\{splice}[^\[\]] YY_OBS_GROW;
567 {splice} YY_OBS_GROW;
568 /* Needed for `\<<EOF>>', `\\<<newline>>[', and `\\<<newline>>]'. */
4f25ebb0 569 \\ YY_OBS_GROW;
e9955c83 570
e9955c83 571 <<EOF>> {
8e6ef483 572 unexpected_end_of_file (*yylloc, "\"", "\"");
e9955c83
AD
573 assert (yy_top_state () != INITIAL);
574 yy_pop_state ();
575 }
576}
577
578
579 /*---------------------------------------------------.
580 | Strings, comments etc. can be found in user code. |
581 `---------------------------------------------------*/
582
583<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
584{
585 /* Characters. We don't check there is only one. */
db2cc12f 586 "'" YY_OBS_GROW; yy_push_state (SC_CHARACTER);
e9955c83
AD
587
588 /* Strings. */
db2cc12f 589 "\"" YY_OBS_GROW; yy_push_state (SC_STRING);
e9955c83
AD
590
591 /* Comments. */
d8d3f94a
PE
592 "/"{splice}"*" YY_OBS_GROW; yy_push_state (SC_COMMENT);
593 "/"{splice}"/" YY_OBS_GROW; yy_push_state (SC_LINE_COMMENT);
4f25ebb0
AD
594
595 /* Not comments. */
596 "/" YY_OBS_GROW;
e9955c83
AD
597}
598
599
600 /*---------------------------------------------------------------.
601 | Scanning some code in braces (%union and actions). The initial |
602 | "{" is already eaten. |
603 `---------------------------------------------------------------*/
604
605<SC_BRACED_CODE>
606{
1a9e39f1
PE
607 "{"|"<"{splice}"%" YY_OBS_GROW; braces_level++;
608 "%"{splice}">" YY_OBS_GROW; braces_level--;
e9955c83 609 "}" {
44995b2e 610 YY_OBS_GROW;
1a9e39f1
PE
611 braces_level--;
612 if (braces_level < 0)
e9955c83
AD
613 {
614 yy_pop_state ();
44995b2e 615 YY_OBS_FINISH;
4cdb01db 616 yylval->string = last_string;
efcb44dd 617 rule_length++;
e9955c83
AD
618 return BRACED_CODE;
619 }
620 }
621
d8d3f94a 622 "$"("<"{tag}">")?(-?[0-9]+|"$") { handle_dollar (current_braced_code,
f25bfb75
AD
623 yytext, *yylloc); }
624 "@"(-?[0-9]+|"$") { handle_at (current_braced_code,
625 yytext, *yylloc); }
e9955c83 626
1a9e39f1
PE
627 /* `"<"{splice}"<"' tokenizes `<<%' correctly (as `<<' `%') rather
628 than incorrrectly (as `<' `<%'). */
629 [^\"$%\'/<@\[\]\{\}]+|[$%/<@]|"<"{splice}"<" YY_OBS_GROW;
e9955c83
AD
630
631 <<EOF>> {
8e6ef483 632 unexpected_end_of_file (*yylloc, "{", "}");
e9955c83 633 yy_pop_state ();
44995b2e 634 YY_OBS_FINISH;
4cdb01db
AD
635 yylval->string = last_string;
636 return BRACED_CODE;
e9955c83
AD
637 }
638
639}
640
641
642 /*--------------------------------------------------------------.
643 | Scanning some prologue: from "%{" (already scanned) to "%}". |
644 `--------------------------------------------------------------*/
645
646<SC_PROLOGUE>
647{
648 "%}" {
649 yy_pop_state ();
44995b2e 650 YY_OBS_FINISH;
4cdb01db 651 yylval->string = last_string;
e9955c83
AD
652 return PROLOGUE;
653 }
654
c4d720cd 655 [^%\[\]/\'\"]+ YY_OBS_GROW;
4f25ebb0 656 "%" YY_OBS_GROW;
e9955c83
AD
657
658 <<EOF>> {
8e6ef483 659 unexpected_end_of_file (*yylloc, "%{", "%}");
e9955c83 660 yy_pop_state ();
44995b2e 661 YY_OBS_FINISH;
4cdb01db 662 yylval->string = last_string;
e9955c83
AD
663 return PROLOGUE;
664 }
e9955c83
AD
665}
666
667
668 /*---------------------------------------------------------------.
669 | Scanning the epilogue (everything after the second "%%", which |
d8d3f94a 670 | has already been eaten). |
e9955c83
AD
671 `---------------------------------------------------------------*/
672
673<SC_EPILOGUE>
674{
d8d3f94a 675 [^\[\]]+ YY_OBS_GROW;
e9955c83
AD
676
677 <<EOF>> {
678 yy_pop_state ();
44995b2e 679 YY_OBS_FINISH;
4cdb01db 680 yylval->string = last_string;
e9955c83
AD
681 return EPILOGUE;
682 }
683}
684
685
686%%
687
688/*------------------------------------------------------------------.
366eea36 689| TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
e9955c83
AD
690| |
691| Possible inputs: $[<TYPENAME>]($|integer) |
692| |
693| Output to the STRING_OBSTACK a reference to this semantic value. |
694`------------------------------------------------------------------*/
695
f25bfb75 696static inline void
366eea36 697handle_action_dollar (char *text, location_t location)
e9955c83
AD
698{
699 const char *type_name = NULL;
366eea36 700 char *cp = text + 1;
e9955c83
AD
701
702 /* Get the type name if explicit. */
703 if (*cp == '<')
704 {
705 type_name = ++cp;
706 while (*cp != '>')
707 ++cp;
708 *cp = '\0';
709 ++cp;
710 }
711
712 if (*cp == '$')
713 {
714 if (!type_name)
56c47203 715 type_name = symbol_list_n_type_name_get (current_rule, location, 0);
e9955c83 716 if (!type_name && typed)
56c47203 717 complain_at (location, _("$$ of `%s' has no declared type"),
97650f4e 718 current_rule->sym->tag);
e9955c83
AD
719 if (!type_name)
720 type_name = "";
721 obstack_fgrow1 (&string_obstack,
722 "]b4_lhs_value([%s])[", type_name);
723 }
d8d3f94a 724 else
e9955c83 725 {
d8d3f94a
PE
726 long num;
727 errno = 0;
728 num = strtol (cp, 0, 10);
e9955c83 729
d8d3f94a 730 if (INT_MIN <= num && num <= rule_length && ! errno)
e9955c83 731 {
d8d3f94a 732 int n = num;
e9955c83 733 if (!type_name && n > 0)
56c47203
AD
734 type_name = symbol_list_n_type_name_get (current_rule, location,
735 n);
e9955c83 736 if (!type_name && typed)
56c47203 737 complain_at (location, _("$%d of `%s' has no declared type"),
97650f4e 738 n, current_rule->sym->tag);
e9955c83
AD
739 if (!type_name)
740 type_name = "";
741 obstack_fgrow3 (&string_obstack,
742 "]b4_rhs_value([%d], [%d], [%s])[",
743 rule_length, n, type_name);
744 }
d8d3f94a 745 else
98f2caaa 746 complain_at (location, _("integer out of range: %s"), quote (text));
9280d3ef
AD
747 }
748}
749
750
366eea36 751/*---------------------------------------------------------------.
d8d3f94a 752| TEXT is expected to be $$ in some code associated to a symbol: |
366eea36
AD
753| destructor or printer. |
754`---------------------------------------------------------------*/
9280d3ef 755
f25bfb75 756static inline void
366eea36 757handle_symbol_code_dollar (char *text, location_t location)
9280d3ef 758{
366eea36 759 char *cp = text + 1;
9280d3ef 760 if (*cp == '$')
366eea36 761 obstack_sgrow (&string_obstack, "]b4_dollar_dollar[");
9280d3ef 762 else
c4d720cd 763 complain_at (location, _("invalid value: %s"), quote (text));
e9955c83
AD
764}
765
f25bfb75
AD
766
767/*-----------------------------------------------------------------.
768| Dispatch onto handle_action_dollar, or handle_destructor_dollar, |
769| depending upon CODE_KIND. |
770`-----------------------------------------------------------------*/
e9955c83
AD
771
772static void
f25bfb75
AD
773handle_dollar (braced_code_t braced_code_kind,
774 char *text, location_t location)
775{
776 switch (braced_code_kind)
777 {
778 case action_braced_code:
779 handle_action_dollar (text, location);
780 break;
781
782 case destructor_braced_code:
366eea36
AD
783 case printer_braced_code:
784 handle_symbol_code_dollar (text, location);
f25bfb75
AD
785 break;
786 }
787}
788
789
790/*------------------------------------------------------.
791| TEXT is a location token (i.e., a `@...'). Output to |
792| STRING_OBSTACK a reference to this location. |
793`------------------------------------------------------*/
794
795static inline void
796handle_action_at (char *text, location_t location)
e9955c83 797{
366eea36 798 char *cp = text + 1;
e9955c83 799 locations_flag = 1;
e9955c83 800
366eea36 801 if (*cp == '$')
e9955c83
AD
802 {
803 obstack_sgrow (&string_obstack, "]b4_lhs_location[");
804 }
d8d3f94a 805 else
e9955c83 806 {
d8d3f94a
PE
807 long num;
808 errno = 0;
809 num = strtol (cp, 0, 10);
dafdc66f 810
d8d3f94a
PE
811 if (INT_MIN <= num && num <= rule_length && ! errno)
812 {
813 int n = num;
814 obstack_fgrow2 (&string_obstack, "]b4_rhs_location([%d], [%d])[",
815 rule_length, n);
816 }
e9955c83 817 else
98f2caaa 818 complain_at (location, _("integer out of range: %s"), quote (text));
f25bfb75
AD
819 }
820}
821
822
366eea36 823/*---------------------------------------------------------------.
d8d3f94a 824| TEXT is expected to be @$ in some code associated to a symbol: |
366eea36
AD
825| destructor or printer. |
826`---------------------------------------------------------------*/
f25bfb75
AD
827
828static inline void
366eea36 829handle_symbol_code_at (char *text, location_t location)
f25bfb75 830{
366eea36
AD
831 char *cp = text + 1;
832 if (*cp == '$')
833 obstack_sgrow (&string_obstack, "]b4_at_dollar[");
f25bfb75 834 else
c4d720cd 835 complain_at (location, _("invalid value: %s"), quote (text));
e9955c83 836}
4cdb01db 837
f25bfb75
AD
838
839/*-------------------------------------------------------------------.
840| Dispatch onto handle_action_at, or handle_destructor_at, depending |
841| upon CODE_KIND. |
842`-------------------------------------------------------------------*/
843
844static void
845handle_at (braced_code_t braced_code_kind,
846 char *text, location_t location)
847{
848 switch (braced_code_kind)
849 {
850 case action_braced_code:
851 handle_action_at (text, location);
852 break;
853
854 case destructor_braced_code:
366eea36
AD
855 case printer_braced_code:
856 handle_symbol_code_at (text, location);
f25bfb75
AD
857 break;
858 }
859}
860
861
d8d3f94a
PE
862/*------------------------------------------------------------------.
863| Convert universal character name UCN to a single-byte character, |
864| and return that character. Return -1 if UCN does not correspond |
865| to a single-byte character. |
866`------------------------------------------------------------------*/
867
868static int
869convert_ucn_to_byte (char const *ucn)
870{
871 unsigned long code = strtoul (ucn + 2, 0, 16);
872
873 /* FIXME: Currently we assume Unicode-compatible unibyte characters
874 on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes). On
875 non-ASCII hosts we support only the portable C character set.
876 These limitations should be removed once we add support for
877 multibyte characters. */
878
879 if (UCHAR_MAX < code)
880 return -1;
881
882#if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e)
883 {
884 /* A non-ASCII host. Use CODE to index into a table of the C
885 basic execution character set, which is guaranteed to exist on
886 all Standard C platforms. This table also includes '$', '@',
8e6ef483 887 and '`', which are not in the basic execution character set but
d8d3f94a
PE
888 which are unibyte characters on all the platforms that we know
889 about. */
890 static signed char const table[] =
891 {
892 '\0', -1, -1, -1, -1, -1, -1, '\a',
893 '\b', '\t', '\n', '\v', '\f', '\r', -1, -1,
894 -1, -1, -1, -1, -1, -1, -1, -1,
895 -1, -1, -1, -1, -1, -1, -1, -1,
896 ' ', '!', '"', '#', '$', '%', '&', '\'',
897 '(', ')', '*', '+', ',', '-', '.', '/',
898 '0', '1', '2', '3', '4', '5', '6', '7',
899 '8', '9', ':', ';', '<', '=', '>', '?',
900 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
901 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
902 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
903 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
904 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
905 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
906 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
907 'x', 'y', 'z', '{', '|', '}', '~'
908 };
909
910 code = code < sizeof table ? table[code] : -1;
911 }
912#endif
c4d720cd 913
d8d3f94a
PE
914 return code;
915}
916
917
900c5db5
AD
918/*----------------------------------------------------------------.
919| Handle `#line INT "FILE"'. ARGS has already skipped `#line '. |
920`----------------------------------------------------------------*/
921
922static void
923handle_syncline (char *args, location_t *location)
924{
925 int lineno = strtol (args, &args, 10);
926 const char *file = NULL;
927 file = strchr (args, '"') + 1;
928 *strchr (file, '"') = 0;
929 /* FIXME: Leaking... Can't free, as some locations are still
930 pointing to the old file name. */
931 infile = xstrdup (file);
932 location->file = infile;
933 location->last_line = lineno;
934}
935
f25bfb75
AD
936/*-------------------------.
937| Initialize the scanner. |
938`-------------------------*/
939
1d6412ad
AD
940void
941scanner_initialize (void)
942{
943 obstack_init (&string_obstack);
944}
945
946
f25bfb75
AD
947/*-----------------------------------------------.
948| Free all the memory allocated to the scanner. |
949`-----------------------------------------------*/
950
4cdb01db
AD
951void
952scanner_free (void)
953{
954 obstack_free (&string_obstack, 0);
536545f3
AD
955 /* Reclaim Flex's buffers. */
956 yy_delete_buffer (YY_CURRENT_BUFFER);
4cdb01db 957}