1 /* Bison Grammar Scanner -*- C -*-
3 Copyright (C) 2002-2012 Free Software Foundation, Inc.
5 This file is part of Bison, the GNU Compiler Compiler.
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 %option debug nodefault noinput nounput noyywrap never-interactive
21 %option prefix="gram_" outfile="lex.yy.c"
24 /* Work around a bug in flex 2.5.31. See Debian bug 333231
25 <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */
29 #define FLEX_PREFIX(Id) gram_ ## Id
30 #include <src/flex-scanner.h>
32 #include <src/complain.h>
33 #include <src/files.h>
36 #include <src/reader.h>
37 #include <src/uniqstr.h>
43 #include <src/scan-gram.h>
45 #define YY_DECL GRAM_LEX_DECL
47 #define YY_USER_INIT \
48 code_start = scanner_cursor = loc->start; \
50 /* Location of scanner cursor. */
51 static boundary scanner_cursor;
53 #define YY_USER_ACTION location_compute (loc, &scanner_cursor, yytext, yyleng);
55 static size_t no_cr_read (FILE *, char *, size_t);
56 #define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size))
58 #define RETURN_PERCENT_PARAM(Value) \
59 RETURN_VALUE(PERCENT_PARAM, param, param_ ## Value)
61 #define RETURN_PERCENT_FLAG(Value) \
62 RETURN_VALUE(PERCENT_FLAG, uniqstr, uniqstr_new (Value))
64 #define RETURN_VALUE(Token, Field, Value) \
70 #define ROLLBACK_CURRENT_TOKEN \
72 scanner_cursor.column -= mbsnwidth (yytext, yyleng, 0); \
76 /* A string representing the most recently saved token. */
77 static char *last_string;
79 /* Bracketed identifier. */
80 static uniqstr bracketed_id_str = 0;
81 static location bracketed_id_loc;
82 static boundary bracketed_id_start;
83 static int bracketed_id_context_state = 0;
86 gram_scanner_last_string_free (void)
91 static void handle_syncline (char *, location);
92 static unsigned long int scan_integer (char const *p, int base, location loc);
93 static int convert_ucn_to_byte (char const *hex_text);
94 static void unexpected_eof (boundary, char const *);
95 static void unexpected_newline (boundary, char const *);
98 /* A C-like comment in directives/rules. */
100 /* Strings and characters in directives/rules. */
101 %x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
102 /* A identifier was just read in directives/rules. Special state
103 to capture the sequence 'identifier :'. */
104 %x SC_AFTER_IDENTIFIER
105 /* A complex tag, with nested angles brackets. */
108 /* Four types of user code:
109 - prologue (code between '%{' '%}' in the first section, before %%);
110 - actions, printers, union, etc, (between braced in the middle section);
111 - epilogue (everything after the second %%).
112 - predicate (code between '%?{' and '{' in middle section); */
113 %x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE SC_PREDICATE
114 /* C and C++ comments in code. */
115 %x SC_COMMENT SC_LINE_COMMENT
116 /* Strings and characters in code. */
117 %x SC_STRING SC_CHARACTER
118 /* Bracketed identifiers support. */
119 %x SC_BRACKETED_ID SC_RETURN_BRACKETED_ID
121 letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
122 id {letter}({letter}|[-0-9])*
126 /* POSIX says that a tag must be both an id and a C union member, but
127 historically almost any character is allowed in a tag. We disallow
128 NUL, as this simplifies our implementation. We disallow angle
129 bracket to match them in nested pairs: several languages use them
130 for generics/template types. */
133 /* Zero or more instances of backslash-newline. Following GCC, allow
134 white space between the backslash and the newline. */
135 splice (\\[ \f\t\v]*\n)*
139 /* Nesting level. Either for nested braces, or nested angle brackets
141 int nesting PACIFY_CC (= 0);
143 /* Parent context state, when applicable. */
144 int context_state PACIFY_CC (= 0);
146 /* Location of most recent identifier, when applicable. */
147 location id_loc PACIFY_CC (= empty_location);
149 /* Where containing code started, when applicable. Its initial
150 value is relevant only when yylex is invoked in the SC_EPILOGUE
152 boundary code_start = scanner_cursor;
154 /* Where containing comment or string or character literal started,
156 boundary token_start PACIFY_CC (= scanner_cursor);
160 /*-----------------------.
161 | Scanning white space. |
162 `-----------------------*/
164 <INITIAL,SC_AFTER_IDENTIFIER,SC_BRACKETED_ID,SC_RETURN_BRACKETED_ID>
166 /* Comments and white space. */
168 complain_at (*loc, Wother, _("stray ',' treated as white space"));
173 token_start = loc->start;
174 context_state = YY_START;
175 BEGIN SC_YACC_COMMENT;
178 /* #line directives are not documented, and may be withdrawn or
179 modified in future versions of Bison. */
180 ^"#line "{int}" \"".*"\"\n" {
181 handle_syncline (yytext + sizeof "#line " - 1, *loc);
186 /*----------------------------.
187 | Scanning Bison directives. |
188 `----------------------------*/
190 /* For directives that are also command line options, the regex must be
192 after "[-_]"s are removed, and the directive must match the --long
193 option name, with a single string argument. Otherwise, add exceptions
194 to ../build-aux/cross-options.pl. */
198 "%binary" return PERCENT_NONASSOC;
199 "%code" return PERCENT_CODE;
200 "%debug" RETURN_PERCENT_FLAG("parse.trace");
201 "%default"[-_]"prec" return PERCENT_DEFAULT_PREC;
202 "%define" return PERCENT_DEFINE;
203 "%defines" return PERCENT_DEFINES;
204 "%destructor" return PERCENT_DESTRUCTOR;
205 "%dprec" return PERCENT_DPREC;
206 "%error"[-_]"verbose" return PERCENT_ERROR_VERBOSE;
207 "%expect" return PERCENT_EXPECT;
208 "%expect"[-_]"rr" return PERCENT_EXPECT_RR;
209 "%file-prefix" return PERCENT_FILE_PREFIX;
210 "%fixed"[-_]"output"[-_]"files" return PERCENT_YACC;
211 "%initial-action" return PERCENT_INITIAL_ACTION;
212 "%glr-parser" return PERCENT_GLR_PARSER;
213 "%language" return PERCENT_LANGUAGE;
214 "%left" return PERCENT_LEFT;
215 "%lex-param" RETURN_PERCENT_PARAM(lex);
216 "%locations" RETURN_PERCENT_FLAG("locations");
217 "%merge" return PERCENT_MERGE;
218 "%name"[-_]"prefix" return PERCENT_NAME_PREFIX;
219 "%no"[-_]"default"[-_]"prec" return PERCENT_NO_DEFAULT_PREC;
220 "%no"[-_]"lines" return PERCENT_NO_LINES;
221 "%nonassoc" return PERCENT_NONASSOC;
222 "%nondeterministic-parser" return PERCENT_NONDETERMINISTIC_PARSER;
223 "%nterm" return PERCENT_NTERM;
224 "%output" return PERCENT_OUTPUT;
225 "%param" RETURN_PERCENT_PARAM(both);
226 "%parse-param" RETURN_PERCENT_PARAM(parse);
227 "%prec" return PERCENT_PREC;
228 "%precedence" return PERCENT_PRECEDENCE;
229 "%printer" return PERCENT_PRINTER;
230 "%pure"[-_]"parser" RETURN_PERCENT_FLAG("api.pure");
231 "%require" return PERCENT_REQUIRE;
232 "%right" return PERCENT_RIGHT;
233 "%skeleton" return PERCENT_SKELETON;
234 "%start" return PERCENT_START;
235 "%term" return PERCENT_TOKEN;
236 "%token" return PERCENT_TOKEN;
237 "%token"[-_]"table" return PERCENT_TOKEN_TABLE;
238 "%type" return PERCENT_TYPE;
239 "%union" return PERCENT_UNION;
240 "%verbose" return PERCENT_VERBOSE;
241 "%yacc" return PERCENT_YACC;
244 complain_at (*loc, complaint, _("invalid directive: %s"), quote (yytext));
249 ";" return SEMICOLON;
252 val->uniqstr = uniqstr_new (yytext);
254 bracketed_id_str = NULL;
255 BEGIN SC_AFTER_IDENTIFIER;
259 val->integer = scan_integer (yytext, 10, *loc);
262 0[xX][0-9abcdefABCDEF]+ {
263 val->integer = scan_integer (yytext, 16, *loc);
267 /* Identifiers may not start with a digit. Yet, don't silently
268 accept "1FOO" as "1 FOO". */
270 complain_at (*loc, complaint, _("invalid identifier: %s"), quote (yytext));
274 "'" token_start = loc->start; BEGIN SC_ESCAPED_CHARACTER;
277 "\"" token_start = loc->start; BEGIN SC_ESCAPED_STRING;
280 "%{" code_start = loc->start; BEGIN SC_PROLOGUE;
282 /* Code in between braces. */
286 code_start = loc->start;
287 BEGIN SC_BRACED_CODE;
290 /* Semantic predicate. */
291 "%?"[ \f\n\t\v]*"{" {
293 code_start = loc->start;
298 "<*>" return TAG_ANY;
299 "<>" return TAG_NONE;
301 obstack_grow (&obstack_for_string, yytext + 1, yyleng - 2);
303 val->uniqstr = uniqstr_new (last_string);
309 token_start = loc->start;
314 static int percent_percent_count;
315 if (++percent_percent_count == 2)
317 return PERCENT_PERCENT;
321 bracketed_id_str = NULL;
322 bracketed_id_start = loc->start;
323 bracketed_id_context_state = YY_START;
324 BEGIN SC_BRACKETED_ID;
328 complain_at (*loc, complaint, _("invalid character: %s"), quote (yytext));
332 loc->start = loc->end = scanner_cursor;
338 /*--------------------------------------------------------------.
339 | Supporting \0 complexifies our implementation for no expected |
341 `--------------------------------------------------------------*/
343 <SC_ESCAPED_CHARACTER,SC_ESCAPED_STRING,SC_TAG>
345 \0 complain_at (*loc, complaint, _("invalid null character"));
349 /*-----------------------------------------------------------------.
350 | Scanning after an identifier, checking whether a colon is next. |
351 `-----------------------------------------------------------------*/
353 <SC_AFTER_IDENTIFIER>
356 if (bracketed_id_str)
358 ROLLBACK_CURRENT_TOKEN;
359 BEGIN SC_RETURN_BRACKETED_ID;
365 bracketed_id_start = loc->start;
366 bracketed_id_context_state = YY_START;
367 BEGIN SC_BRACKETED_ID;
371 BEGIN (bracketed_id_str ? SC_RETURN_BRACKETED_ID : INITIAL);
376 ROLLBACK_CURRENT_TOKEN;
377 BEGIN (bracketed_id_str ? SC_RETURN_BRACKETED_ID : INITIAL);
382 BEGIN (bracketed_id_str ? SC_RETURN_BRACKETED_ID : INITIAL);
388 /*--------------------------------.
389 | Scanning bracketed identifiers. |
390 `--------------------------------*/
395 if (bracketed_id_str)
397 complain_at (*loc, complaint,
398 _("unexpected identifier in bracketed name: %s"),
403 bracketed_id_str = uniqstr_new (yytext);
404 bracketed_id_loc = *loc;
408 BEGIN bracketed_id_context_state;
409 if (bracketed_id_str)
411 if (INITIAL == bracketed_id_context_state)
413 val->uniqstr = bracketed_id_str;
414 bracketed_id_str = 0;
415 *loc = bracketed_id_loc;
420 complain_at (*loc, complaint, _("an identifier expected"));
423 complain_at (*loc, complaint, _("invalid character in bracketed name: %s"),
427 BEGIN bracketed_id_context_state;
428 unexpected_eof (bracketed_id_start, "]");
432 <SC_RETURN_BRACKETED_ID>
435 ROLLBACK_CURRENT_TOKEN;
436 val->uniqstr = bracketed_id_str;
437 bracketed_id_str = 0;
438 *loc = bracketed_id_loc;
445 /*---------------------------------------------------------------.
446 | Scanning a Yacc comment. The initial '/ *' is already eaten. |
447 `---------------------------------------------------------------*/
451 "*/" BEGIN context_state;
453 <<EOF>> unexpected_eof (token_start, "*/"); BEGIN context_state;
457 /*------------------------------------------------------------.
458 | Scanning a C comment. The initial '/ *' is already eaten. |
459 `------------------------------------------------------------*/
463 "*"{splice}"/" STRING_GROW; BEGIN context_state;
464 <<EOF>> unexpected_eof (token_start, "*/"); BEGIN context_state;
468 /*--------------------------------------------------------------.
469 | Scanning a line comment. The initial '//' is already eaten. |
470 `--------------------------------------------------------------*/
474 "\n" STRING_GROW; BEGIN context_state;
475 {splice} STRING_GROW;
476 <<EOF>> BEGIN context_state;
480 /*------------------------------------------------.
481 | Scanning a Bison string, including its escapes. |
482 | The initial quote is already eaten. |
483 `------------------------------------------------*/
488 if (yytext[0] == '\n')
489 unexpected_newline (token_start, "\"");
491 loc->start = token_start;
492 val->chars = last_string;
497 unexpected_eof (token_start, "\"");
499 loc->start = token_start;
500 val->chars = last_string;
506 /*----------------------------------------------------------.
507 | Scanning a Bison character literal, decoding its escapes. |
508 | The initial quote is already eaten. |
509 `----------------------------------------------------------*/
511 <SC_ESCAPED_CHARACTER>
515 loc->start = token_start;
516 val->character = last_string[0];
518 /* FIXME: Eventually, make these errors. */
519 if (last_string[0] == '\0')
521 complain_at (*loc, Wother, _("empty character literal"));
522 /* '\0' seems dangerous even if we are about to complain. */
523 val->character = '\'';
525 else if (last_string[1] != '\0')
526 complain_at (*loc, Wother,
527 _("extra characters in character literal"));
529 if (yytext[0] == '\n')
530 unexpected_newline (token_start, "'");
537 loc->start = token_start;
538 val->character = last_string[0];
540 /* FIXME: Eventually, make these errors. */
541 if (last_string[0] == '\0')
543 complain_at (*loc, Wother, _("empty character literal"));
544 /* '\0' seems dangerous even if we are about to complain. */
545 val->character = '\'';
547 else if (last_string[1] != '\0')
548 complain_at (*loc, Wother,
549 _("extra characters in character literal"));
551 unexpected_eof (token_start, "'");
558 /*-----------------------------------------------------------.
559 | Scanning a Bison nested tag. The initial angle bracket is |
561 `-----------------------------------------------------------*/
570 loc->start = token_start;
571 val->uniqstr = uniqstr_new (last_string);
580 "<"+ STRING_GROW; nesting += yyleng;
583 unexpected_eof (token_start, ">");
585 loc->start = token_start;
586 val->uniqstr = uniqstr_new (last_string);
593 /*----------------------------.
594 | Decode escaped characters. |
595 `----------------------------*/
597 <SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
600 unsigned long int c = strtoul (yytext + 1, NULL, 8);
601 if (!c || UCHAR_MAX < c)
602 complain_at (*loc, complaint, _("invalid number after \\-escape: %s"),
605 obstack_1grow (&obstack_for_string, c);
608 \\x[0-9abcdefABCDEF]+ {
609 verify (UCHAR_MAX < ULONG_MAX);
610 unsigned long int c = strtoul (yytext + 2, NULL, 16);
611 if (!c || UCHAR_MAX < c)
612 complain_at (*loc, complaint, _("invalid number after \\-escape: %s"),
615 obstack_1grow (&obstack_for_string, c);
618 \\a obstack_1grow (&obstack_for_string, '\a');
619 \\b obstack_1grow (&obstack_for_string, '\b');
620 \\f obstack_1grow (&obstack_for_string, '\f');
621 \\n obstack_1grow (&obstack_for_string, '\n');
622 \\r obstack_1grow (&obstack_for_string, '\r');
623 \\t obstack_1grow (&obstack_for_string, '\t');
624 \\v obstack_1grow (&obstack_for_string, '\v');
626 /* \\[\"\'?\\] would be shorter, but it confuses xgettext. */
627 \\("\""|"'"|"?"|"\\") obstack_1grow (&obstack_for_string, yytext[1]);
629 \\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} {
630 int c = convert_ucn_to_byte (yytext);
632 complain_at (*loc, complaint, _("invalid number after \\-escape: %s"),
635 obstack_1grow (&obstack_for_string, c);
638 char const *p = yytext + 1;
639 /* Quote only if escaping won't make the character visible. */
640 if (c_isspace ((unsigned char) *p) && c_isprint ((unsigned char) *p))
643 p = quotearg_style_mem (escape_quoting_style, p, 1);
644 complain_at (*loc, complaint, _("invalid character after \\-escape: %s"),
649 /*--------------------------------------------.
650 | Scanning user-code characters and strings. |
651 `--------------------------------------------*/
653 <SC_CHARACTER,SC_STRING>
655 {splice}|\\{splice}[^\n\[\]] STRING_GROW;
660 "'" STRING_GROW; BEGIN context_state;
661 \n unexpected_newline (token_start, "'"); BEGIN context_state;
662 <<EOF>> unexpected_eof (token_start, "'"); BEGIN context_state;
667 "\"" STRING_GROW; BEGIN context_state;
668 \n unexpected_newline (token_start, "\""); BEGIN context_state;
669 <<EOF>> unexpected_eof (token_start, "\""); BEGIN context_state;
673 /*---------------------------------------------------.
674 | Strings, comments etc. can be found in user code. |
675 `---------------------------------------------------*/
677 <SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_PREDICATE>
681 context_state = YY_START;
682 token_start = loc->start;
687 context_state = YY_START;
688 token_start = loc->start;
693 context_state = YY_START;
694 token_start = loc->start;
699 context_state = YY_START;
700 BEGIN SC_LINE_COMMENT;
706 /*-----------------------------------------------------------.
707 | Scanning some code in braces (actions, predicates). The |
708 | initial "{" is already eaten. |
709 `-----------------------------------------------------------*/
711 <SC_BRACED_CODE,SC_PREDICATE>
713 "{"|"<"{splice}"%" STRING_GROW; nesting++;
714 "%"{splice}">" STRING_GROW; nesting--;
716 /* Tokenize '<<%' correctly (as '<<' '%') rather than incorrrectly
718 "<"{splice}"<" STRING_GROW;
721 int token = (YY_START == SC_BRACED_CODE) ? BRACED_CODE : BRACED_PREDICATE;
722 unexpected_eof (code_start, "}");
724 loc->start = code_start;
725 val->code = last_string;
734 obstack_1grow (&obstack_for_string, '}');
740 loc->start = code_start;
741 val->code = last_string;
755 loc->start = code_start;
756 val->code = last_string;
758 return BRACED_PREDICATE;
761 obstack_1grow (&obstack_for_string, '}');
765 /*--------------------------------------------------------------.
766 | Scanning some prologue: from "%{" (already scanned) to "%}". |
767 `--------------------------------------------------------------*/
773 loc->start = code_start;
774 val->chars = last_string;
780 unexpected_eof (code_start, "%}");
782 loc->start = code_start;
783 val->chars = last_string;
790 /*---------------------------------------------------------------.
791 | Scanning the epilogue (everything after the second "%%", which |
792 | has already been eaten). |
793 `---------------------------------------------------------------*/
799 loc->start = code_start;
800 val->chars = last_string;
807 /*-----------------------------------------------------.
808 | By default, grow the string obstack with the input. |
809 `-----------------------------------------------------*/
811 <SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>. |
812 <SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE>\n STRING_GROW;
816 /* Read bytes from FP into buffer BUF of size SIZE. Return the
817 number of bytes read. Remove '\r' from input, treating \r\n
818 and isolated \r as \n. */
821 no_cr_read (FILE *fp, char *buf, size_t size)
823 size_t bytes_read = fread (buf, 1, size, fp);
826 char *w = memchr (buf, '\r', bytes_read);
830 char const *lim = buf + bytes_read;
834 /* Found an '\r'. Treat it like '\n', but ignore any
835 '\n' that immediately follows. */
840 if (ch != '\n' && ungetc (ch, fp) != ch)
846 /* Copy until the next '\r'. */
852 while ((*w++ = *r++) != '\r');
864 /*------------------------------------------------------.
865 | Scan NUMBER for a base-BASE integer at location LOC. |
866 `------------------------------------------------------*/
868 static unsigned long int
869 scan_integer (char const *number, int base, location loc)
871 verify (INT_MAX < ULONG_MAX);
872 unsigned long int num = strtoul (number, NULL, base);
876 complain_at (loc, complaint, _("integer out of range: %s"),
885 /*------------------------------------------------------------------.
886 | Convert universal character name UCN to a single-byte character, |
887 | and return that character. Return -1 if UCN does not correspond |
888 | to a single-byte character. |
889 `------------------------------------------------------------------*/
892 convert_ucn_to_byte (char const *ucn)
894 verify (UCHAR_MAX <= INT_MAX);
895 unsigned long int code = strtoul (ucn + 2, NULL, 16);
897 /* FIXME: Currently we assume Unicode-compatible unibyte characters
898 on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes). On
899 non-ASCII hosts we support only the portable C character set.
900 These limitations should be removed once we add support for
901 multibyte characters. */
903 if (UCHAR_MAX < code)
906 #if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e)
908 /* A non-ASCII host. Use CODE to index into a table of the C
909 basic execution character set, which is guaranteed to exist on
910 all Standard C platforms. This table also includes '$', '@',
911 and '`', which are not in the basic execution character set but
912 which are unibyte characters on all the platforms that we know
914 static signed char const table[] =
916 '\0', -1, -1, -1, -1, -1, -1, '\a',
917 '\b', '\t', '\n', '\v', '\f', '\r', -1, -1,
918 -1, -1, -1, -1, -1, -1, -1, -1,
919 -1, -1, -1, -1, -1, -1, -1, -1,
920 ' ', '!', '"', '#', '$', '%', '&', '\'',
921 '(', ')', '*', '+', ',', '-', '.', '/',
922 '0', '1', '2', '3', '4', '5', '6', '7',
923 '8', '9', ':', ';', '<', '=', '>', '?',
924 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
925 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
926 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
927 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
928 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
929 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
930 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
931 'x', 'y', 'z', '{', '|', '}', '~'
934 code = code < sizeof table ? table[code] : -1;
942 /*----------------------------------------------------------------.
943 | Handle '#line INT "FILE"'. ARGS has already skipped '#line '. |
944 `----------------------------------------------------------------*/
947 handle_syncline (char *args, location loc)
950 unsigned long int lineno = strtoul (args, &after_num, 10);
951 char *file = strchr (after_num, '"') + 1;
952 *strchr (file, '"') = '\0';
953 if (INT_MAX <= lineno)
955 complain_at (loc, Wother, _("line number overflow"));
958 current_file = uniqstr_new (file);
959 boundary_set (&scanner_cursor, current_file, lineno, 1);
963 /*----------------------------------------------------------------.
964 | For a token or comment starting at START, report message MSGID, |
965 | which should say that an end marker was found before |
966 | the expected TOKEN_END. |
967 `----------------------------------------------------------------*/
970 unexpected_end (boundary start, char const *msgid, char const *token_end)
974 loc.end = scanner_cursor;
975 token_end = quote (token_end);
976 // Instead of '\'', display "'".
977 if (STREQ (token_end, "'\\''"))
979 complain_at (loc, complaint, _(msgid), token_end);
983 /*------------------------------------------------------------------------.
984 | Report an unexpected EOF in a token or comment starting at START. |
985 | An end of file was encountered and the expected TOKEN_END was missing. |
986 `------------------------------------------------------------------------*/
989 unexpected_eof (boundary start, char const *token_end)
991 unexpected_end (start, N_("missing %s at end of file"), token_end);
995 /*----------------------------------------.
996 | Likewise, but for unexpected newlines. |
997 `----------------------------------------*/
1000 unexpected_newline (boundary start, char const *token_end)
1002 unexpected_end (start, N_("missing %s at end of line"), token_end);
1006 /*-------------------------.
1007 | Initialize the scanner. |
1008 `-------------------------*/
1011 gram_scanner_initialize (void)
1013 obstack_init (&obstack_for_string);
1017 /*-----------------------------------------------.
1018 | Free all the memory allocated to the scanner. |
1019 `-----------------------------------------------*/
1022 gram_scanner_free (void)
1024 obstack_free (&obstack_for_string, 0);
1025 /* Reclaim Flex's buffers. */