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