X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/06ec0105b12cdfa2994283e345154e6720354808..89ff1b5e71a6d8aa34b3578282528adb43b198cd:/src/scan-gram.l diff --git a/src/scan-gram.l b/src/scan-gram.l index 98124556..665e80de 100644 --- a/src/scan-gram.l +++ b/src/scan-gram.l @@ -1,6 +1,6 @@ /* Bison Grammar Scanner -*- C -*- - Copyright (C) 2002-2012 Free Software Foundation, Inc. + Copyright (C) 2002-2013 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -77,9 +77,7 @@ static size_t no_cr_read (FILE *, char *, size_t); #define DEPRECATED(Msg) \ do { \ size_t i; \ - complain (loc, Wdeprecated, \ - _("deprecated directive: %s, use %s"), \ - quote (yytext), quote_n (1, Msg)); \ + deprecated_directive (loc, yytext, Msg); \ scanner_cursor.column -= mbsnwidth (Msg, strlen (Msg), 0); \ for (i = strlen (Msg); i != 0; --i) \ unput (Msg[i - 1]); \ @@ -114,7 +112,12 @@ static void unexpected_newline (boundary, char const *); /* A identifier was just read in directives/rules. Special state to capture the sequence 'identifier :'. */ %x SC_AFTER_IDENTIFIER - /* A complex tag, with nested angles brackets. */ + + /* POSIX says that a tag must be both an id and a C union member, but + historically almost any character is allowed in a tag. We + disallow NUL, as this simplifies our implementation. We match + angle brackets in nested pairs: several languages use them for + generics/template types. */ %x SC_TAG /* Four types of user code: @@ -131,17 +134,10 @@ static void unexpected_newline (boundary, char const *); %x SC_BRACKETED_ID SC_RETURN_BRACKETED_ID letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_] +notletter [^.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]{-}[%\{] id {letter}({letter}|[-0-9])* -directive %{id} int [0-9]+ -/* POSIX says that a tag must be both an id and a C union member, but - historically almost any character is allowed in a tag. We disallow - NUL, as this simplifies our implementation. We disallow angle - bracket to match them in nested pairs: several languages use them - for generics/template types. */ -tag [^\0<>]+ - /* Zero or more instances of backslash-newline. Following GCC, allow white space between the backslash and the newline. */ splice (\\[ \f\t\v]*\n)* @@ -184,7 +180,7 @@ eqopt ([[:space:]]*=)? complain (loc, Wother, _("stray ',' treated as white space")); } [ \f\n\t\v] | - "//".* ; + "//".* continue; "/*" { token_start = loc->start; context_state = YY_START; @@ -193,7 +189,7 @@ eqopt ([[:space:]]*=)? /* #line directives are not documented, and may be withdrawn or modified in future versions of Bison. */ - ^"#line "{int}" \"".*"\"\n" { + ^"#line "{int}(" \"".*"\"")?"\n" { handle_syncline (yytext + sizeof "#line " - 1, *loc); } } @@ -219,6 +215,7 @@ eqopt ([[:space:]]*=)? "%defines" return PERCENT_DEFINES; "%destructor" return PERCENT_DESTRUCTOR; "%dprec" return PERCENT_DPREC; + "%empty" return PERCENT_EMPTY; "%error-verbose" return PERCENT_ERROR_VERBOSE; "%expect" return PERCENT_EXPECT; "%expect-rr" return PERCENT_EXPECT_RR; @@ -269,7 +266,7 @@ eqopt ([[:space:]]*=)? "%pure"[-_]"parser" DEPRECATED("%pure-parser"); "%token"[-_]"table" DEPRECATED("%token-table"); - {directive} { + "%"{id}|"%"{notletter}([[:graph:]])+ { complain (loc, complaint, _("invalid directive: %s"), quote (yytext)); } @@ -326,13 +323,6 @@ eqopt ([[:space:]]*=)? /* A type. */ "<*>" return TAG_ANY; "<>" return TAG_NONE; - "<"{tag}">" { - obstack_grow (&obstack_for_string, yytext + 1, yyleng - 2); - STRING_FINISH; - val->uniqstr = uniqstr_new (last_string); - STRING_FREE; - return TAG; - } "<" { nesting = 0; token_start = loc->start; @@ -353,8 +343,9 @@ eqopt ([[:space:]]*=)? BEGIN SC_BRACKETED_ID; } - . { - complain (loc, complaint, _("invalid character: %s"), + [^\[%A-Za-z0-9_<>{}\"\'*;|=/, \f\n\t\v]+|. { + complain (loc, complaint, "%s: %s", + ngettext ("invalid character", "invalid characters", yyleng), quote_mem (yytext, yyleng)); } @@ -449,10 +440,14 @@ eqopt ([[:space:]]*=)? else complain (loc, complaint, _("an identifier expected")); } - . { - complain (loc, complaint, _("invalid character in bracketed name: %s"), + + [^\].A-Za-z0-9_/ \f\n\t\v]+|. { + complain (loc, complaint, "%s: %s", + ngettext ("invalid character in bracketed name", + "invalid characters in bracketed name", yyleng), quote_mem (yytext, yyleng)); } + <> { BEGIN bracketed_id_context_state; unexpected_eof (bracketed_id_start, "]"); @@ -479,7 +474,7 @@ eqopt ([[:space:]]*=)? { "*/" BEGIN context_state; - .|\n ; + .|\n continue; <> unexpected_eof (token_start, "*/"); BEGIN context_state; } @@ -514,23 +509,15 @@ eqopt ([[:space:]]*=)? { - "\""|"\n" { - if (yytext[0] == '\n') - unexpected_newline (token_start, "\""); - STRING_FINISH; - loc->start = token_start; - val->chars = last_string; - BEGIN INITIAL; - return STRING; - } - <> { - unexpected_eof (token_start, "\""); + "\"" { STRING_FINISH; loc->start = token_start; - val->chars = last_string; + val->code = last_string; BEGIN INITIAL; return STRING; } + <> unexpected_eof (token_start, "\""); + "\n" unexpected_newline (token_start, "\""); } /*----------------------------------------------------------. @@ -540,55 +527,34 @@ eqopt ([[:space:]]*=)? { - "'"|"\n" { - STRING_FINISH; - loc->start = token_start; - val->character = last_string[0]; - { - /* FIXME: Eventually, make these errors. */ - if (last_string[0] == '\0') - { - complain (loc, Wother, _("empty character literal")); - /* '\0' seems dangerous even if we are about to complain. */ - val->character = '\''; - } - else if (last_string[1] != '\0') - complain (loc, Wother, - _("extra characters in character literal")); - } - if (yytext[0] == '\n') - unexpected_newline (token_start, "'"); - STRING_FREE; - BEGIN INITIAL; - return CHAR; - } - <> { + "'" { STRING_FINISH; loc->start = token_start; val->character = last_string[0]; + + /* FIXME: Eventually, make these errors. */ + if (last_string[0] == '\0') { - /* FIXME: Eventually, make these errors. */ - if (last_string[0] == '\0') - { - complain (loc, Wother, _("empty character literal")); - /* '\0' seems dangerous even if we are about to complain. */ - val->character = '\''; - } - else if (last_string[1] != '\0') - complain (loc, Wother, - _("extra characters in character literal")); + complain (loc, Wother, _("empty character literal")); + /* '\0' seems dangerous even if we are about to complain. */ + val->character = '\''; } - unexpected_eof (token_start, "'"); + else if (last_string[1] != '\0') + complain (loc, Wother, + _("extra characters in character literal")); STRING_FREE; BEGIN INITIAL; return CHAR; } + "\n" unexpected_newline (token_start, "'"); + <> unexpected_eof (token_start, "'"); } - /*-----------------------------------------------------------. - | Scanning a Bison nested tag. The initial angle bracket is | - | already eaten. | - `-----------------------------------------------------------*/ + + + /*--------------------------------------------------------------. + | Scanning a tag. The initial angle bracket is already eaten. | + `--------------------------------------------------------------*/ { @@ -606,18 +572,10 @@ eqopt ([[:space:]]*=)? STRING_GROW; } - [^<>]+ STRING_GROW; + ([^<>]|->)+ STRING_GROW; "<"+ STRING_GROW; nesting += yyleng; - <> { - unexpected_eof (token_start, ">"); - STRING_FINISH; - loc->start = token_start; - val->uniqstr = uniqstr_new (last_string); - STRING_FREE; - BEGIN INITIAL; - return TAG; - } + <> unexpected_eof (token_start, ">"); } /*----------------------------. @@ -688,15 +646,15 @@ eqopt ([[:space:]]*=)? { "'" STRING_GROW; BEGIN context_state; - \n unexpected_newline (token_start, "'"); BEGIN context_state; - <> unexpected_eof (token_start, "'"); BEGIN context_state; + \n unexpected_newline (token_start, "'"); + <> unexpected_eof (token_start, "'"); } { "\"" STRING_GROW; BEGIN context_state; - \n unexpected_newline (token_start, "\""); BEGIN context_state; - <> unexpected_eof (token_start, "\""); BEGIN context_state; + \n unexpected_newline (token_start, "\""); + <> unexpected_eof (token_start, "\""); } @@ -747,15 +705,7 @@ eqopt ([[:space:]]*=)? (as '<' '<%'). */ "<"{splice}"<" STRING_GROW; - <> { - int token = (YY_START == SC_BRACED_CODE) ? BRACED_CODE : BRACED_PREDICATE; - unexpected_eof (code_start, "}"); - STRING_FINISH; - loc->start = code_start; - val->code = last_string; - BEGIN INITIAL; - return token; - } + <> unexpected_eof (code_start, "}"); } @@ -801,19 +751,12 @@ eqopt ([[:space:]]*=)? "%}" { STRING_FINISH; loc->start = code_start; - val->chars = last_string; + val->code = last_string; BEGIN INITIAL; return PROLOGUE; } - <> { - unexpected_eof (code_start, "%}"); - STRING_FINISH; - loc->start = code_start; - val->chars = last_string; - BEGIN INITIAL; - return PROLOGUE; - } + <> unexpected_eof (code_start, "%}"); } @@ -827,7 +770,7 @@ eqopt ([[:space:]]*=)? <> { STRING_FINISH; loc->start = code_start; - val->chars = last_string; + val->code = last_string; BEGIN INITIAL; return EPILOGUE; } @@ -969,31 +912,35 @@ convert_ucn_to_byte (char const *ucn) } -/*----------------------------------------------------------------. -| Handle '#line INT "FILE"'. ARGS has already skipped '#line '. | -`----------------------------------------------------------------*/ +/*---------------------------------------------------------------------. +| Handle '#line INT( "FILE")?\n'. ARGS has already skipped '#line '. | +`---------------------------------------------------------------------*/ static void handle_syncline (char *args, location loc) { - char *after_num; - unsigned long int lineno = strtoul (args, &after_num, 10); - char *file = strchr (after_num, '"') + 1; - *strchr (file, '"') = '\0'; + char *file; + unsigned long int lineno = strtoul (args, &file, 10); if (INT_MAX <= lineno) { complain (&loc, Wother, _("line number overflow")); lineno = INT_MAX; } - current_file = uniqstr_new (file); + + file = strchr (file, '"'); + if (file) + { + *strchr (file + 1, '"') = '\0'; + current_file = uniqstr_new (file + 1); + } boundary_set (&scanner_cursor, current_file, lineno, 1); } /*----------------------------------------------------------------. | For a token or comment starting at START, report message MSGID, | -| which should say that an end marker was found before | -| the expected TOKEN_END. | +| which should say that an end marker was found before the | +| expected TOKEN_END. Then, pretend that TOKEN_END was found. | `----------------------------------------------------------------*/ static void @@ -1002,8 +949,17 @@ unexpected_end (boundary start, char const *msgid, char const *token_end) location loc; loc.start = start; loc.end = scanner_cursor; + size_t i = strlen (token_end); + +/* Adjust scanner cursor so that any later message does not count + the characters about to be inserted. */ + scanner_cursor.column -= i; + + while (i != 0) + unput (token_end[--i]); + token_end = quote (token_end); - // Instead of '\'', display "'". + /* Instead of '\'', display "'". */ if (STREQ (token_end, "'\\''")) token_end = "\"'\""; complain (&loc, complaint, _(msgid), token_end); @@ -1013,6 +969,7 @@ unexpected_end (boundary start, char const *msgid, char const *token_end) /*------------------------------------------------------------------------. | Report an unexpected EOF in a token or comment starting at START. | | An end of file was encountered and the expected TOKEN_END was missing. | +| After reporting the problem, pretend that TOKEN_END was found. | `------------------------------------------------------------------------*/ static void