mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
Discussed starting at
<http://lists.gnu.org/archive/html/bison-patches/2009-08/msg00036.html>.
* src/scan-gram.l (SC_ESCAPED_STRING, SC_ESCAPED_CHARACTER):
For a \0 and similar escape sequences meaning the null
character, report an invalid escape sequence instead of an
invalid null character because the latter does not actually
appear in the user's input.
In all escape sequence complaints, don't escape the initial
backslash, and don't quote when the sequence appears at the end
of the complaint line unless there's whitespace that quotearg
won't escape.
Consistently say "invalid" not "unrecognized".
Consistently prefer "empty character literal" over "extra
characters in character literal" warning for invalid escape
sequences; that is, consistently discard those sequences.
* tests/input.at (Bad escapes in literals): New.
(cherry picked from commit c2724603c9)
1260 lines
32 KiB
Plaintext
1260 lines
32 KiB
Plaintext
# Checking the Bison scanner. -*- Autotest -*-
|
|
# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
|
# Free Software Foundation, Inc.
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
AT_BANNER([[Input Processing.]])
|
|
|
|
# Mostly test that we are robust to mistakes.
|
|
|
|
|
|
## ------------ ##
|
|
## Invalid $n. ##
|
|
## ------------ ##
|
|
|
|
AT_SETUP([Invalid $n and @n])
|
|
|
|
AT_DATA([input.y],
|
|
[[%%
|
|
exp: { $$ = $1 ; };
|
|
exp: { @$ = @1 ; };
|
|
]])
|
|
|
|
AT_BISON_CHECK([input.y], [1], [],
|
|
[[input.y:2.13-14: integer out of range: `$1'
|
|
input.y:3.13-14: integer out of range: `@1'
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## -------------- ##
|
|
## Type Clashes. ##
|
|
## -------------- ##
|
|
|
|
AT_SETUP([Type Clashes])
|
|
|
|
AT_DATA([input.y],
|
|
[[%union { int bar; }
|
|
%token foo
|
|
%type <bar> exp
|
|
%%
|
|
exp: foo { $$; } foo { $2; } foo
|
|
| foo
|
|
| /* Empty. */
|
|
;
|
|
]])
|
|
|
|
AT_BISON_CHECK([input.y], [1], [],
|
|
[[input.y:5.12-13: $$ for the midrule at $2 of `exp' has no declared type
|
|
input.y:5.24-25: $2 of `exp' has no declared type
|
|
input.y:5.6-32: warning: type clash on default action: <bar> != <>
|
|
input.y:6.6-8: warning: type clash on default action: <bar> != <>
|
|
input.y:7.5: warning: empty rule for typed nonterminal, and no action
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
# _AT_UNUSED_VALUES_DECLARATIONS()
|
|
# --------------------------------------------
|
|
# Generate the token, type, and destructor
|
|
# declarations for the unused values tests.
|
|
|
|
m4_define([_AT_UNUSED_VALUES_DECLARATIONS],
|
|
[[[%token <integer> INT;
|
|
%type <integer> a b c d e f g h i j k l;
|
|
%destructor { destroy ($$); } INT a b c d e f g h i j k l;]]])
|
|
|
|
|
|
# AT_CHECK_UNUSED_VALUES(DECLARATIONS_AFTER, CHECK_MIDRULE_VALUES)
|
|
# ------------------------------------------------------------------
|
|
# Generate a grammar to test unused values,
|
|
# compile it, run it. If DECLARATIONS_AFTER
|
|
# is set, then the token, type, and destructor
|
|
# declarations are generated after the rules
|
|
# rather than before. If CHECK_MIDRULE_VALUES
|
|
# is set, then --warnings=midrule-values is
|
|
# set.
|
|
|
|
m4_define([AT_CHECK_UNUSED_VALUES],
|
|
[AT_DATA([input.y],
|
|
m4_ifval($1, [
|
|
|
|
|
|
], [_AT_UNUSED_VALUES_DECLARATIONS
|
|
])[[%%
|
|
start:
|
|
'a' a { $]2[; } | 'b' b { $]2[; } | 'c' c { $]2[; } | 'd' d { $]2[; }
|
|
| 'e' e { $]2[; } | 'f' f { $]2[; } | 'g' g { $]2[; } | 'h' h { $]2[; }
|
|
| 'i' i { $]2[; } | 'j' j { $]2[; } | 'k' k { $]2[; } | 'l' l { $]2[; }
|
|
;
|
|
|
|
a: INT | INT { } INT { } INT { };
|
|
b: INT | /* empty */;
|
|
c: INT | INT { $]1[; } INT { $<integer>2; } INT { $<integer>4; };
|
|
d: INT | INT { } INT { $]1[; } INT { $<integer>2; };
|
|
e: INT | INT { } INT { } INT { $]1[; };
|
|
f: INT | INT { } INT { } INT { $]$[ = $]1[ + $]3[ + $]5[; };
|
|
g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
|
|
h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { };
|
|
i: INT | INT INT { } { $]$[ = $]1[ + $]2[; };
|
|
j: INT | INT INT { $<integer>$ = 1; } { $]$[ = $]1[ + $]2[; };
|
|
k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { };
|
|
l: INT | INT { $<integer>$ = $<integer>1; } INT { $<integer>$ = $<integer>2 + $<integer>3; } INT { $<integer>$ = $<integer>4 + $<integer>5; };]]m4_ifval($1, [
|
|
_AT_UNUSED_VALUES_DECLARATIONS])
|
|
)
|
|
|
|
AT_BISON_CHECK(m4_ifval($2, [ --warnings=midrule-values ])[ input.y], [0], [],
|
|
[[input.y:11.10-32: warning: unset value: $]$[
|
|
input.y:11.10-32: warning: unused value: $]1[
|
|
input.y:11.10-32: warning: unused value: $]3[
|
|
input.y:11.10-32: warning: unused value: $]5[
|
|
input.y:12.9: warning: empty rule for typed nonterminal, and no action
|
|
]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $$
|
|
input.y:13.26-41: warning: unset value: $$
|
|
]]])[[input.y:13.10-62: warning: unset value: $]$[
|
|
input.y:13.10-62: warning: unused value: $]3[
|
|
input.y:13.10-62: warning: unused value: $]5[
|
|
]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $$
|
|
]]])[[input.y:14.10-49: warning: unset value: $]$[
|
|
input.y:14.10-49: warning: unused value: $]3[
|
|
input.y:14.10-49: warning: unused value: $]5[
|
|
input.y:15.10-37: warning: unset value: $]$[
|
|
input.y:15.10-37: warning: unused value: $]3[
|
|
input.y:15.10-37: warning: unused value: $]5[
|
|
input.y:17.10-58: warning: unset value: $]$[
|
|
input.y:17.10-58: warning: unused value: $]1[
|
|
]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]2[
|
|
]]])[[input.y:17.10-58: warning: unused value: $]3[
|
|
]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]4[
|
|
]]])[[input.y:17.10-58: warning: unused value: $]5[
|
|
input.y:18.10-72: warning: unset value: $]$[
|
|
input.y:18.10-72: warning: unused value: $]1[
|
|
input.y:18.10-72: warning: unused value: $]3[
|
|
]]m4_ifval($2, [[[input.y:18.10-72: warning: unused value: $]4[
|
|
]]])[[input.y:18.10-72: warning: unused value: $]5[
|
|
]]m4_ifval($2, [[[input.y:20.10-55: warning: unused value: $]3[
|
|
]]])[[input.y:21.10-68: warning: unset value: $]$[
|
|
input.y:21.10-68: warning: unused value: $]1[
|
|
input.y:21.10-68: warning: unused value: $]2[
|
|
]]m4_ifval($2, [[[input.y:21.10-68: warning: unused value: $]4[
|
|
]]]))])
|
|
|
|
|
|
## --------------- ##
|
|
## Unused values. ##
|
|
## --------------- ##
|
|
|
|
AT_SETUP([Unused values])
|
|
AT_CHECK_UNUSED_VALUES
|
|
AT_CHECK_UNUSED_VALUES(, [1])
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------------------------------------ ##
|
|
## Unused values before symbol declarations. ##
|
|
## ------------------------------------------ ##
|
|
|
|
AT_SETUP([Unused values before symbol declarations])
|
|
AT_CHECK_UNUSED_VALUES([1])
|
|
AT_CHECK_UNUSED_VALUES([1], [1])
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------------------------------------------- ##
|
|
## Default %printer and %destructor redeclared. ##
|
|
## --------------------------------------------- ##
|
|
|
|
AT_SETUP([Default %printer and %destructor redeclared])
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%destructor { destroy ($$); } <*> <*>
|
|
%printer { destroy ($$); } <*> <*>
|
|
|
|
%destructor { destroy ($$); } <*>
|
|
%printer { destroy ($$); } <*>
|
|
|
|
%destructor { destroy ($$); } <> <>
|
|
%printer { destroy ($$); } <> <>
|
|
|
|
%destructor { destroy ($$); } <>
|
|
%printer { destroy ($$); } <>
|
|
|
|
%%
|
|
|
|
start: ;
|
|
|
|
%destructor { destroy ($$); } <*>;
|
|
%printer { destroy ($$); } <*>;
|
|
|
|
%destructor { destroy ($$); } <>;
|
|
%printer { destroy ($$); } <>;
|
|
]])
|
|
|
|
AT_BISON_CHECK([input.y], [1], [],
|
|
[[input.y:1.13-29: redeclaration for default tagged %destructor
|
|
input.y:1.13-29: previous declaration
|
|
input.y:2.10-26: redeclaration for default tagged %printer
|
|
input.y:2.10-26: previous declaration
|
|
input.y:4.13-29: redeclaration for default tagged %destructor
|
|
input.y:1.13-29: previous declaration
|
|
input.y:5.10-26: redeclaration for default tagged %printer
|
|
input.y:2.10-26: previous declaration
|
|
input.y:7.13-29: redeclaration for default tagless %destructor
|
|
input.y:7.13-29: previous declaration
|
|
input.y:8.10-26: redeclaration for default tagless %printer
|
|
input.y:8.10-26: previous declaration
|
|
input.y:10.13-29: redeclaration for default tagless %destructor
|
|
input.y:7.13-29: previous declaration
|
|
input.y:11.10-26: redeclaration for default tagless %printer
|
|
input.y:8.10-26: previous declaration
|
|
input.y:17.13-29: redeclaration for default tagged %destructor
|
|
input.y:4.13-29: previous declaration
|
|
input.y:18.10-26: redeclaration for default tagged %printer
|
|
input.y:5.10-26: previous declaration
|
|
input.y:20.13-29: redeclaration for default tagless %destructor
|
|
input.y:10.13-29: previous declaration
|
|
input.y:21.10-26: redeclaration for default tagless %printer
|
|
input.y:11.10-26: previous declaration
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------------------------------------------- ##
|
|
## Per-type %printer and %destructor redeclared. ##
|
|
## ---------------------------------------------- ##
|
|
|
|
AT_SETUP([Per-type %printer and %destructor redeclared])
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%destructor { destroy ($$); } <field1> <field2>
|
|
%printer { destroy ($$); } <field1> <field2>
|
|
|
|
%destructor { destroy ($$); } <field1> <field1>
|
|
%printer { destroy ($$); } <field2> <field2>
|
|
|
|
%%
|
|
|
|
start: ;
|
|
|
|
%destructor { destroy ($$); } <field2> <field1>;
|
|
%printer { destroy ($$); } <field2> <field1>;
|
|
]])
|
|
|
|
AT_BISON_CHECK([input.y], [1], [],
|
|
[[input.y:4.13-29: %destructor redeclaration for <field1>
|
|
input.y:1.13-29: previous declaration
|
|
input.y:4.13-29: %destructor redeclaration for <field1>
|
|
input.y:4.13-29: previous declaration
|
|
input.y:5.10-26: %printer redeclaration for <field2>
|
|
input.y:2.10-26: previous declaration
|
|
input.y:5.10-26: %printer redeclaration for <field2>
|
|
input.y:5.10-26: previous declaration
|
|
input.y:11.13-29: %destructor redeclaration for <field1>
|
|
input.y:4.13-29: previous declaration
|
|
input.y:11.13-29: %destructor redeclaration for <field2>
|
|
input.y:1.13-29: previous declaration
|
|
input.y:12.10-26: %printer redeclaration for <field1>
|
|
input.y:2.10-26: previous declaration
|
|
input.y:12.10-26: %printer redeclaration for <field2>
|
|
input.y:5.10-26: previous declaration
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------------------------------------- ##
|
|
## Unused values with default %destructor. ##
|
|
## ---------------------------------------- ##
|
|
|
|
AT_SETUP([Unused values with default %destructor])
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%destructor { destroy ($$); } <>
|
|
%type <tag> tagged
|
|
|
|
%%
|
|
|
|
start: end end tagged tagged { $<tag>1; $3; } ;
|
|
end: { } ;
|
|
tagged: { } ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([input.y], [0], [],
|
|
[[input.y:6.8-45: warning: unset value: $$
|
|
input.y:6.8-45: warning: unused value: $2
|
|
input.y:7.6-8: warning: unset value: $$
|
|
]])
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%destructor { destroy ($$); } <*>
|
|
%type <tag> tagged
|
|
|
|
%%
|
|
|
|
start: end end tagged tagged { $<tag>1; $3; } ;
|
|
end: { } ;
|
|
tagged: { } ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([input.y], [0], [],
|
|
[[input.y:6.8-45: warning: unused value: $4
|
|
input.y:8.9-11: warning: unset value: $$
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------------------------------------- ##
|
|
## Unused values with per-type %destructor. ##
|
|
## ----------------------------------------- ##
|
|
|
|
AT_SETUP([Unused values with per-type %destructor])
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%destructor { destroy ($$); } <field1>
|
|
%type <field1> start end
|
|
|
|
%%
|
|
|
|
start: end end { $1; } ;
|
|
end: { } ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([input.y], [0], [],
|
|
[[input.y:6.8-22: warning: unset value: $$
|
|
input.y:6.8-22: warning: unused value: $2
|
|
input.y:7.6-8: warning: unset value: $$
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------------------- ##
|
|
## Incompatible Aliases. ##
|
|
## ---------------------- ##
|
|
|
|
AT_SETUP([Incompatible Aliases])
|
|
|
|
AT_DATA([input.y],
|
|
[[%token foo "foo"
|
|
|
|
%type <bar> foo
|
|
%printer {bar} foo
|
|
%destructor {bar} foo
|
|
%left foo
|
|
|
|
%type <baz> "foo"
|
|
%printer {baz} "foo"
|
|
%destructor {baz} "foo"
|
|
%left "foo"
|
|
|
|
%%
|
|
exp: foo;
|
|
]])
|
|
|
|
AT_BISON_CHECK([input.y], [1], [],
|
|
[[input.y:8.7-11: %type redeclaration for foo
|
|
input.y:3.7-11: previous declaration
|
|
input.y:10.13-17: %destructor redeclaration for foo
|
|
input.y:5.13-17: previous declaration
|
|
input.y:9.10-14: %printer redeclaration for foo
|
|
input.y:4.10-14: previous declaration
|
|
input.y:11.1-5: %left redeclaration for foo
|
|
input.y:6.1-5: previous declaration
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
|
|
## ----------------------- ##
|
|
## Torturing the Scanner. ##
|
|
## ----------------------- ##
|
|
|
|
# Be sure to compile and run, so that the C compiler checks what
|
|
# we do.
|
|
|
|
AT_SETUP([Torturing the Scanner])
|
|
|
|
|
|
AT_DATA([input.y], [])
|
|
AT_BISON_CHECK([input.y], [1], [],
|
|
[[input.y:1.1: syntax error, unexpected end of file
|
|
]])
|
|
|
|
|
|
AT_DATA([input.y],
|
|
[{}
|
|
])
|
|
AT_BISON_CHECK([input.y], [1], [],
|
|
[[input.y:1.1-2: syntax error, unexpected {...}
|
|
]])
|
|
|
|
|
|
AT_DATA_GRAMMAR([input.y],
|
|
[[%{
|
|
/* This is seen in GCC: a %{ and %} in middle of a comment. */
|
|
const char *foo = "So %{ and %} can be here too.";
|
|
|
|
#if 0
|
|
/* These examples test Bison while not stressing C compilers too much.
|
|
Many C compilers mishandle backslash-newlines, so this part of the
|
|
test is inside "#if 0". The comment and string are written so that
|
|
the "#endif" will be seen regardless of the C compiler bugs that we
|
|
know about, namely:
|
|
|
|
HP C (as of late 2002) mishandles *\[newline]\[newline]/ within a
|
|
comment.
|
|
|
|
The Apple Darwin compiler (as of late 2002) mishandles
|
|
\\[newline]' within a character constant.
|
|
|
|
*/
|
|
|
|
/\
|
|
* A comment with backslash-newlines in it. %} *\
|
|
\
|
|
/
|
|
/* { Close the above comment, if the C compiler mishandled it. */
|
|
|
|
char str[] = "\\
|
|
" A string with backslash-newlines in it %{ %} \\
|
|
\
|
|
"";
|
|
|
|
char apostrophe = '\'';
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
%}
|
|
/* %{ and %} can be here too. */
|
|
|
|
%{
|
|
/* Exercise pre-prologue dependency to %union. */
|
|
typedef int value;
|
|
%}
|
|
|
|
/* Exercise M4 quoting: '@:>@@:>@', 0. */
|
|
|
|
/* Also exercise %union. */
|
|
%union
|
|
{
|
|
value ival; /* A comment to exercise an old bug. */
|
|
};
|
|
|
|
|
|
/* Exercise post-prologue dependency to %union. */
|
|
%{
|
|
static YYSTYPE value_as_yystype (value val);
|
|
|
|
/* Exercise quotes in declarations. */
|
|
char quote[] = "@:>@@:>@,";
|
|
%}
|
|
|
|
%{
|
|
static void yyerror (const char *s);
|
|
static int yylex (void);
|
|
%}
|
|
|
|
%type <ival> '@<:@'
|
|
|
|
/* Exercise quotes in strings. */
|
|
%token FAKE "fake @<:@@:>@ \a\b\f\n\r\t\v\"\'\?\\\u005B\U0000005c ??!??'??(??)??-??/??<??=??> \x1\1"
|
|
|
|
%%
|
|
/* Exercise M4 quoting: '@:>@@:>@', @<:@, 1. */
|
|
exp: '@<:@' '\1' two '$' '@' '{' oline output.or.oline.opt
|
|
{
|
|
/* Exercise quotes in braces. */
|
|
char tmp[] = "@<:@%c@:>@,\n";
|
|
printf (tmp, $1);
|
|
}
|
|
;
|
|
|
|
two: '\x000000000000000000000000000000000000000000000000000000000000000000002';
|
|
oline: '@' 'o' 'l' 'i' 'n' 'e' '@' '_' '_' 'o' 'l' 'i' 'n' 'e' '_' '_';
|
|
output.or.oline.opt: ;|oline;;|output;;;
|
|
output: '#' 'o' 'u' 't' 'p' 'u' 't' ' ';
|
|
%%
|
|
/* Exercise M4 quoting: '@:>@@:>@', @<:@, 2. */
|
|
|
|
static YYSTYPE
|
|
value_as_yystype (value val)
|
|
{
|
|
YYSTYPE res;
|
|
res.ival = val;
|
|
return res;
|
|
}
|
|
|
|
static int
|
|
yylex (void)
|
|
{
|
|
static char const input[] = "@<:@\1\2$@{@oline@__@&t@oline__\
|
|
#output "; /* "
|
|
*/
|
|
static size_t toknum;
|
|
if (! (toknum < sizeof input))
|
|
abort ();
|
|
yylval = value_as_yystype (input[toknum]);
|
|
return input[toknum++];
|
|
}
|
|
|
|
static void
|
|
yyerror (const char *msg)
|
|
{
|
|
fprintf (stderr, "%s\n", msg);
|
|
}
|
|
]])
|
|
|
|
# Pacify Emacs'font-lock-mode: "
|
|
|
|
AT_DATA([main.c],
|
|
[[typedef int value;
|
|
#include "input.h"
|
|
|
|
int yyparse (void);
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
return yyparse ();
|
|
}
|
|
]])
|
|
|
|
AT_BISON_CHECK([-d -v -o input.c input.y])
|
|
AT_COMPILE([input.o], [-c input.c])
|
|
AT_COMPILE([main.o], [-c main.c])
|
|
AT_COMPILE([input], [input.o main.o])
|
|
AT_PARSER_CHECK([./input], 0,
|
|
[[[@<:@],
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------------------- ##
|
|
## Typed symbol aliases. ##
|
|
## ---------------------- ##
|
|
|
|
AT_SETUP([Typed symbol aliases])
|
|
|
|
# Bison 2.0 broke typed symbol aliases - ensure they work.
|
|
|
|
AT_DATA_GRAMMAR([input.y],
|
|
[[%union
|
|
{
|
|
int val;
|
|
};
|
|
%token <val> MY_TOKEN "MY TOKEN"
|
|
%type <val> exp
|
|
%%
|
|
exp: "MY TOKEN";
|
|
%%
|
|
]])
|
|
|
|
AT_BISON_CHECK([-o input.c input.y])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------- ##
|
|
## Require. ##
|
|
## --------- ##
|
|
|
|
m4_define([AT_CHECK_REQUIRE],
|
|
[AT_SETUP([Require $1])
|
|
AT_DATA_GRAMMAR([input.y],
|
|
[[%require "$1";
|
|
%%
|
|
empty_file:;
|
|
]])
|
|
AT_BISON_CHECK([-o input.c input.y], $2, [], ignore)
|
|
AT_CLEANUP
|
|
])
|
|
|
|
AT_CHECK_REQUIRE(1.0, 0)
|
|
AT_CHECK_REQUIRE(AT_PACKAGE_VERSION, 0)
|
|
## FIXME: Some day augment this version number.
|
|
AT_CHECK_REQUIRE(100.0, 63)
|
|
|
|
|
|
## ------------------------------------- ##
|
|
## String aliases for character tokens. ##
|
|
## ------------------------------------- ##
|
|
|
|
AT_SETUP([String aliases for character tokens])
|
|
|
|
# Bison once thought a character token and its alias were different symbols
|
|
# with the same user token number.
|
|
|
|
AT_DATA_GRAMMAR([input.y],
|
|
[[%token 'a' "a"
|
|
%%
|
|
start: 'a';
|
|
%%
|
|
]])
|
|
|
|
AT_BISON_CHECK([-o input.c input.y])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## -------------- ##
|
|
## Symbol names. ##
|
|
## -------------- ##
|
|
|
|
AT_SETUP([Symbols])
|
|
|
|
AT_DATA_GRAMMAR([input.y],
|
|
[[%token WITH-DASH
|
|
%token WITHOUT_DASH "WITHOUT-DASH"
|
|
%token WITH.PERIOD
|
|
%token WITHOUT_PERIOD "WITHOUT.PERIOD"
|
|
%code {
|
|
void yyerror (char const *);
|
|
int yylex (void);
|
|
}
|
|
%%
|
|
start: with-dash without_dash with.period without_period;
|
|
with-dash: WITH-DASH;
|
|
without_dash: "WITHOUT-DASH";
|
|
with.period: WITH.PERIOD;
|
|
without_period: "WITHOUT.PERIOD";
|
|
%%
|
|
]])
|
|
|
|
# POSIX Yacc accept periods, but not dashes.
|
|
AT_BISON_CHECK([--yacc input.y], [1], [],
|
|
[[input.y:9.8-16: POSIX Yacc forbids dashes in symbol names: WITH-DASH
|
|
input.y:18.8-16: POSIX Yacc forbids dashes in symbol names: with-dash
|
|
]])
|
|
|
|
# So warn about them.
|
|
AT_BISON_CHECK([-Wyacc input.y], [], [],
|
|
[[input.y:9.8-16: warning: POSIX Yacc forbids dashes in symbol names: WITH-DASH
|
|
input.y:18.8-16: warning: POSIX Yacc forbids dashes in symbol names: with-dash
|
|
]])
|
|
|
|
# Dashes are fine for GNU Bison.
|
|
AT_BISON_CHECK([-o input.c input.y])
|
|
|
|
# Make sure we don't export silly token identifiers with periods or dashes.
|
|
AT_COMPILE([input.o], [-c input.c])
|
|
|
|
|
|
# Periods and dashes are genuine letters, they can start identifiers.
|
|
# Digits cannot.
|
|
AT_DATA_GRAMMAR([input.y],
|
|
[[%token .GOOD
|
|
-GOOD
|
|
1NV4L1D
|
|
%%
|
|
start: .GOOD -GOOD
|
|
]])
|
|
AT_BISON_CHECK([-o input.c input.y], [1], [],
|
|
[[input.y:11.10-16: invalid identifier: `1NV4L1D'
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------------- ##
|
|
## Numbered tokens. ##
|
|
## ----------------- ##
|
|
|
|
AT_SETUP([Numbered tokens])
|
|
|
|
AT_DATA_GRAMMAR([redecl.y],
|
|
[[%token DECIMAL_1 11259375
|
|
HEXADECIMAL_1 0xabcdef
|
|
HEXADECIMAL_2 0xFEDCBA
|
|
DECIMAL_2 16702650
|
|
%%
|
|
start: DECIMAL_1 HEXADECIMAL_2;
|
|
]])
|
|
|
|
AT_BISON_CHECK([redecl.y], [1], [],
|
|
[[redecl.y:10.10-22: user token number 11259375 redeclaration for HEXADECIMAL_1
|
|
redecl.y:9.8-16: previous declaration for DECIMAL_1
|
|
redecl.y:12.10-18: user token number 16702650 redeclaration for DECIMAL_2
|
|
redecl.y:11.10-22: previous declaration for HEXADECIMAL_2
|
|
]])
|
|
|
|
AT_DATA_GRAMMAR([too-large.y],
|
|
[[%token TOO_LARGE_DEC 999999999999999999999
|
|
TOO_LARGE_HEX 0xFFFFFFFFFFFFFFFFFFF
|
|
%%
|
|
start: TOO_LARGE_DEC TOO_LARGE_HEX
|
|
%%
|
|
]])
|
|
|
|
AT_BISON_CHECK([too-large.y], [1], [],
|
|
[[too-large.y:9.22-42: integer out of range: `999999999999999999999'
|
|
too-large.y:10.24-44: integer out of range: `0xFFFFFFFFFFFFFFFFFFF'
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------------------- ##
|
|
## Unclosed constructs. ##
|
|
## --------------------- ##
|
|
|
|
AT_SETUP([Unclosed constructs])
|
|
|
|
# Bison's scan-gram.l once forgot to STRING_FINISH some unclosed constructs, so
|
|
# they were prepended to whatever it STRING_GROW'ed next. It also threw them
|
|
# away rather than returning them to the parser. The effect was confusing
|
|
# subsequent error messages.
|
|
|
|
AT_DATA([input.y],
|
|
[[%token A "a
|
|
%token B "b"
|
|
%token AB "ab" // Used to complain that "ab" was already used.
|
|
%token C '1
|
|
%token TWO "2"
|
|
%token TICK_TWELVE "'12" // Used to complain that "'12" was already used.
|
|
|
|
%%
|
|
|
|
start: ;
|
|
|
|
// Used to report a syntax error because it didn't see any kind of symbol
|
|
// identifier.
|
|
%type <f> 'a
|
|
;
|
|
%type <f> "a
|
|
;
|
|
// Used to report a syntax error because it didn't see braced code.
|
|
%destructor { free ($$)
|
|
]])
|
|
|
|
AT_BISON_CHECK([-o input.c input.y], 1, [],
|
|
[[input.y:1.10-2.0: missing `"' at end of line
|
|
input.y:4.10-5.0: missing `'' at end of line
|
|
input.y:14.11-15.0: missing `'' at end of line
|
|
input.y:16.11-17.0: missing `"' at end of line
|
|
input.y:19.13-20.0: missing `}' at end of file
|
|
input.y:20.1: syntax error, unexpected end of file
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------------------- ##
|
|
## %start after first rule. ##
|
|
## ------------------------- ##
|
|
|
|
AT_SETUP([%start after first rule])
|
|
|
|
# Bison once complained that a %start after the first rule was a redeclaration
|
|
# of the start symbol.
|
|
|
|
AT_DATA([input.y],
|
|
[[%%
|
|
false_start: ;
|
|
start: false_start ;
|
|
%start start;
|
|
]])
|
|
|
|
AT_BISON_CHECK([-o input.c input.y])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------------------- ##
|
|
## %prec takes a token. ##
|
|
## --------------------- ##
|
|
|
|
AT_SETUP([%prec takes a token])
|
|
|
|
# Bison once allowed %prec sym where sym was a nonterminal.
|
|
|
|
AT_DATA([input.y],
|
|
[[%%
|
|
start: PREC %prec PREC ;
|
|
PREC: ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([input.y], [1], [],
|
|
[[input.y:3.1-4: rule given for PREC, which is a token
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## -------------------------------- ##
|
|
## Reject unused %code qualifiers. ##
|
|
## -------------------------------- ##
|
|
|
|
AT_SETUP([Reject unused %code qualifiers])
|
|
|
|
AT_DATA([input-c.y],
|
|
[[%code q {}
|
|
%code bad {}
|
|
%code bad {}
|
|
%code format {}
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[input-c.y]], [0], [],
|
|
[[input-c.y:1.7: warning: %code qualifier `q' is not used
|
|
input-c.y:2.7-9: warning: %code qualifier `bad' is not used
|
|
input-c.y:3.7-9: warning: %code qualifier `bad' is not used
|
|
input-c.y:4.7-12: warning: %code qualifier `format' is not used
|
|
]])
|
|
|
|
AT_DATA([input-c-glr.y],
|
|
[[%code q {}
|
|
%code bad {}
|
|
%code bad {}
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[input-c-glr.y]], [0], [],
|
|
[[input-c-glr.y:1.7: warning: %code qualifier `q' is not used
|
|
input-c-glr.y:2.7-9: warning: %code qualifier `bad' is not used
|
|
input-c-glr.y:3.8-10: warning: %code qualifier `bad' is not used
|
|
]])
|
|
|
|
AT_DATA([input-c++.y],
|
|
[[%code q {}
|
|
%code bad {}
|
|
%code q {}
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[input-c++.y]], [0], [],
|
|
[[input-c++.y:1.7: warning: %code qualifier `q' is not used
|
|
input-c++.y:2.7-9: warning: %code qualifier `bad' is not used
|
|
input-c++.y:3.8: warning: %code qualifier `q' is not used
|
|
]])
|
|
|
|
AT_DATA([input-c++-glr.y],
|
|
[[%code bad {}
|
|
%code q {}
|
|
%code q {}
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[input-c++-glr.y]], [0], [],
|
|
[[input-c++-glr.y:1.7-9: warning: %code qualifier `bad' is not used
|
|
input-c++-glr.y:2.7: warning: %code qualifier `q' is not used
|
|
input-c++-glr.y:3.7: warning: %code qualifier `q' is not used
|
|
]])
|
|
|
|
AT_DATA([special-char-@@.y],
|
|
[[%code bad {}
|
|
%code q {}
|
|
%code q {}
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[special-char-@@.y]], [0], [],
|
|
[[special-char-@@.y:1.7-9: warning: %code qualifier `bad' is not used
|
|
special-char-@@.y:2.7: warning: %code qualifier `q' is not used
|
|
special-char-@@.y:3.7: warning: %code qualifier `q' is not used
|
|
]])
|
|
|
|
AT_DATA([special-char-@:>@.y],
|
|
[[%code bad {}
|
|
%code q {}
|
|
%code q {}
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[special-char-@:>@.y]], [0], [],
|
|
[[special-char-@:>@.y:1.7-9: warning: %code qualifier `bad' is not used
|
|
special-char-@:>@.y:2.7: warning: %code qualifier `q' is not used
|
|
special-char-@:>@.y:3.7: warning: %code qualifier `q' is not used
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------------- ##
|
|
## %define errors. ##
|
|
## ---------------- ##
|
|
|
|
AT_SETUP([%define errors])
|
|
|
|
AT_DATA([input-redefined.y],
|
|
[[%define var "value1"
|
|
%define var "value1"
|
|
%define var "value2"
|
|
%define special1 "@:>@"
|
|
%define special2 "@<:@"
|
|
%%
|
|
start: ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([[input-redefined.y]], [[1]], [],
|
|
[[input-redefined.y:2.9-11: %define variable `var' redefined
|
|
input-redefined.y:1.9-11: previous definition
|
|
input-redefined.y:3.10-12: %define variable `var' redefined
|
|
input-redefined.y:2.9-11: previous definition
|
|
]])
|
|
|
|
AT_DATA([input-unused.y],
|
|
[[%define var "value"
|
|
%%
|
|
start: ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([[input-unused.y]], [[0]], [],
|
|
[[input-unused.y:1.9-11: warning: %define variable `var' is not used
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------------------------------- ##
|
|
## %define, --define, --force-define. ##
|
|
## ----------------------------------- ##
|
|
|
|
AT_SETUP([%define, --define, --force-define])
|
|
|
|
AT_DATA([skel.c],
|
|
[[m4@&t@_divert_push(0)@
|
|
@output(b4_parser_file_name@)@
|
|
[var-dd: ]b4_percent_define_get([[var-dd]])[
|
|
var-ff: ]b4_percent_define_get([[var-ff]])[
|
|
var-dfg: ]b4_percent_define_get([[var-dfg]])[
|
|
var-fd: ]b4_percent_define_get([[var-fd]])
|
|
m4@&t@_divert_pop(0)
|
|
]])
|
|
|
|
AT_DATA([input.y],
|
|
[[%define var-dfg "gram"
|
|
%%
|
|
start: ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([[-Dvar-dd=cmd-d1 -Dvar-dd=cmd-d2 \
|
|
-Fvar-ff=cmd-f1 -Fvar-ff=cmd-f2 \
|
|
-Dvar-dfg=cmd-d -Fvar-dfg=cmd-f \
|
|
-Fvar-fd=cmd-f -Dvar-fd=cmd-d \
|
|
-Dunused-d -Funused-f \
|
|
--skeleton ./skel.c input.y]], [[0]], [],
|
|
[[<command line>:10: warning: %define variable `unused-d' is not used
|
|
<command line>:11: warning: %define variable `unused-f' is not used
|
|
]])
|
|
|
|
AT_CHECK([[cat input.tab.c]], [[0]],
|
|
[[var-dd: cmd-d2
|
|
var-ff: cmd-f2
|
|
var-dfg: cmd-f
|
|
var-fd: cmd-d
|
|
]])
|
|
|
|
AT_DATA([input-dg.y],
|
|
[[%define var "gram"
|
|
%%
|
|
start: ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [],
|
|
[[input-dg.y:1.9-11: %define variable `var' redefined
|
|
<command line>:2: previous definition
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## --------------------------- ##
|
|
## %define Boolean variables. ##
|
|
## --------------------------- ##
|
|
|
|
AT_SETUP([[%define Boolean variables]])
|
|
|
|
AT_DATA([Input.y],
|
|
[[%language "Java"
|
|
%define public "maybe"
|
|
%define parser_class_name "Input"
|
|
%%
|
|
start: ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([[Input.y]], [1], [],
|
|
[[Input.y:2.9-14: invalid value for %define Boolean variable `public'
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ------------------------ ##
|
|
## %define enum variables. ##
|
|
## ------------------------ ##
|
|
|
|
AT_SETUP([[%define enum variables]])
|
|
|
|
# Front-end.
|
|
AT_DATA([[input.y]],
|
|
[[%define lr.default-reductions "bogus"
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[input.y]], [[1]], [[]],
|
|
[[input.y:1.9-29: invalid value for %define variable `lr.default-reductions': `bogus'
|
|
input.y:1.9-29: accepted value: `all'
|
|
input.y:1.9-29: accepted value: `consistent'
|
|
input.y:1.9-29: accepted value: `accepting'
|
|
]])
|
|
|
|
# Back-end.
|
|
AT_DATA([[input.y]],
|
|
[[%define api.push-pull "neither"
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[input.y]], [1], [],
|
|
[[input.y:1.9-21: invalid value for %define variable `api.push-pull': `neither'
|
|
input.y:1.9-21: accepted value: `pull'
|
|
input.y:1.9-21: accepted value: `push'
|
|
input.y:1.9-21: accepted value: `both'
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## -------------------------------- ##
|
|
## %define backward compatibility. ##
|
|
## -------------------------------- ##
|
|
|
|
AT_SETUP([[%define backward compatibility]])
|
|
|
|
# The error messages tell us whether underscores in these variables are
|
|
# being converted to dashes.
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%define api.push_pull "neither"
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[input.y]], [1], [],
|
|
[[input.y:1.9-21: invalid value for %define variable `api.push-pull': `neither'
|
|
input.y:1.9-21: accepted value: `pull'
|
|
input.y:1.9-21: accepted value: `push'
|
|
input.y:1.9-21: accepted value: `both'
|
|
]])
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%define lr.keep_unreachable_states "maybe"
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[input.y]], [1], [],
|
|
[[input.y:1.9-34: invalid value for %define Boolean variable `lr.keep-unreachable-states'
|
|
]])
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%define foo_bar "baz"
|
|
%%
|
|
start: ;
|
|
]])
|
|
AT_BISON_CHECK([[input.y]], [0], [],
|
|
[[input.y:1.9-15: warning: %define variable `foo_bar' is not used
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ------------------------- ##
|
|
## Unused %define api.pure. ##
|
|
## ------------------------- ##
|
|
|
|
AT_SETUP([[Unused %define api.pure]])
|
|
|
|
# AT_CHECK_API_PURE(DECLS, VALUE)
|
|
# -------------------------------
|
|
# Make sure Bison reports that `%define api.pure VALUE' is unused when DECLS
|
|
# are specified.
|
|
m4_define([AT_CHECK_API_PURE],
|
|
[
|
|
AT_DATA([[input.y]],
|
|
[[%define api.pure ]$2[
|
|
]$1[
|
|
%%
|
|
start: ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([[input.y]], [0], [],
|
|
[[input.y:1.9-16: warning: %define variable `api.pure' is not used
|
|
]])
|
|
])
|
|
|
|
AT_CHECK_API_PURE([[%language "c++" %defines]], [[]])
|
|
AT_CHECK_API_PURE([[%language "c++" %defines]], [["false"]])
|
|
AT_CHECK_API_PURE([[%language "c++" %defines %glr-parser]], [[""]])
|
|
AT_CHECK_API_PURE([[%language "c++" %defines %glr-parser]], [["false"]])
|
|
AT_CHECK_API_PURE([[%language "java"]], [["true"]])
|
|
AT_CHECK_API_PURE([[%language "java"]], [["false"]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## -------------------------------- ##
|
|
## C++ namespace reference errors. ##
|
|
## -------------------------------- ##
|
|
|
|
AT_SETUP([[C++ namespace reference errors]])
|
|
|
|
# AT_CHECK_NAMESPACE_ERROR(NAMESPACE-DECL, ERROR, [ERROR], ...)
|
|
# -------------------------------------------------------------
|
|
# Make sure Bison reports all ERROR's for %define namespace "NAMESPACE-DECL".
|
|
m4_define([AT_CHECK_NAMESPACE_ERROR],
|
|
[
|
|
AT_DATA([[input.y]],
|
|
[[%language "C++"
|
|
%defines
|
|
%define namespace "]$1["
|
|
%%
|
|
start: ;
|
|
]])
|
|
|
|
AT_BISON_CHECK([[input.y]], [1], [],
|
|
[m4_foreach([b4_arg], m4_dquote(m4_shift($@)),
|
|
[[input.y:3.9-17: ]b4_arg[
|
|
]])])
|
|
])
|
|
|
|
AT_CHECK_NAMESPACE_ERROR([[]],
|
|
[[namespace reference is empty]])
|
|
AT_CHECK_NAMESPACE_ERROR([[ ]],
|
|
[[namespace reference is empty]])
|
|
AT_CHECK_NAMESPACE_ERROR([[foo::::bar]],
|
|
[[namespace reference has consecutive "::"]])
|
|
AT_CHECK_NAMESPACE_ERROR([[foo:: ::bar]],
|
|
[[namespace reference has consecutive "::"]])
|
|
AT_CHECK_NAMESPACE_ERROR([[::::bar]],
|
|
[[namespace reference has consecutive "::"]])
|
|
AT_CHECK_NAMESPACE_ERROR([[:: ::bar]],
|
|
[[namespace reference has consecutive "::"]])
|
|
AT_CHECK_NAMESPACE_ERROR([[foo::bar:: ::]],
|
|
[[namespace reference has consecutive "::"]],
|
|
[[namespace reference has a trailing "::"]])
|
|
AT_CHECK_NAMESPACE_ERROR([[foo::bar::]],
|
|
[[namespace reference has a trailing "::"]])
|
|
AT_CHECK_NAMESPACE_ERROR([[foo::bar:: ]],
|
|
[[namespace reference has a trailing "::"]])
|
|
AT_CHECK_NAMESPACE_ERROR([[::]],
|
|
[[namespace reference has a trailing "::"]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ------------------------ ##
|
|
## Bad character literals. ##
|
|
## ------------------------ ##
|
|
|
|
# Bison used to accept character literals that were empty or contained
|
|
# too many characters.
|
|
|
|
# FIXME: $ECHO_N and $ECHO_C are not very portable according to the
|
|
# Autoconf manual. Switch to AS_ECHO_N when Autoconf 2.64 is released?
|
|
# Even better, AT_DATA or some variant of AT_DATA may eventually permit
|
|
# a trailing newline. See the threads starting at
|
|
# <http://lists.gnu.org/archive/html/bison-patches/2009-07/msg00019.html>.
|
|
|
|
AT_SETUP([[Bad character literals]])
|
|
|
|
AT_DATA([empty.y],
|
|
[[%%
|
|
start: '';
|
|
start: '
|
|
]])
|
|
echo $ECHO_N "start: '$ECHO_C" >> empty.y
|
|
|
|
AT_BISON_CHECK([empty.y], [1], [],
|
|
[[empty.y:2.8-9: warning: empty character literal
|
|
empty.y:3.8-4.0: warning: empty character literal
|
|
empty.y:3.8-4.0: missing `'' at end of line
|
|
empty.y:4.8: warning: empty character literal
|
|
empty.y:4.8: missing `'' at end of file
|
|
]])
|
|
|
|
AT_DATA([two.y],
|
|
[[%%
|
|
start: 'ab';
|
|
start: 'ab
|
|
]])
|
|
echo $ECHO_N "start: 'ab$ECHO_C" >> two.y
|
|
|
|
AT_BISON_CHECK([two.y], [1], [],
|
|
[[two.y:2.8-11: warning: extra characters in character literal
|
|
two.y:3.8-4.0: warning: extra characters in character literal
|
|
two.y:3.8-4.0: missing `'' at end of line
|
|
two.y:4.8-10: warning: extra characters in character literal
|
|
two.y:4.8-10: missing `'' at end of file
|
|
]])
|
|
|
|
AT_DATA([three.y],
|
|
[[%%
|
|
start: 'abc';
|
|
start: 'abc
|
|
]])
|
|
echo $ECHO_N "start: 'abc$ECHO_C" >> three.y
|
|
|
|
AT_BISON_CHECK([three.y], [1], [],
|
|
[[three.y:2.8-12: warning: extra characters in character literal
|
|
three.y:3.8-4.0: warning: extra characters in character literal
|
|
three.y:3.8-4.0: missing `'' at end of line
|
|
three.y:4.8-11: warning: extra characters in character literal
|
|
three.y:4.8-11: missing `'' at end of file
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ------------------------- ##
|
|
## Bad escapes in literals. ##
|
|
## ------------------------- ##
|
|
|
|
AT_SETUP([[Bad escapes in literals]])
|
|
|
|
AT_DATA([input.y],
|
|
[[%%
|
|
start: '\777' '\0' '\xfff' '\x0'
|
|
'\uffff' '\u0000' '\Uffffffff' '\U00000000'
|
|
'\ ' '\A';
|
|
]])
|
|
echo 'start: "\T\F\0\1" ;' | tr 'TF01' '\011\014\0\1' >> input.y
|
|
|
|
AT_BISON_CHECK([input.y], [1], [],
|
|
[[input.y:2.9-12: invalid number after \-escape: 777
|
|
input.y:2.8-13: warning: empty character literal
|
|
input.y:2.16-17: invalid number after \-escape: 0
|
|
input.y:2.15-18: warning: empty character literal
|
|
input.y:2.21-25: invalid number after \-escape: xfff
|
|
input.y:2.20-26: warning: empty character literal
|
|
input.y:2.29-31: invalid number after \-escape: x0
|
|
input.y:2.28-32: warning: empty character literal
|
|
input.y:3.9-14: invalid number after \-escape: uffff
|
|
input.y:3.8-15: warning: empty character literal
|
|
input.y:3.18-23: invalid number after \-escape: u0000
|
|
input.y:3.17-24: warning: empty character literal
|
|
input.y:3.27-36: invalid number after \-escape: Uffffffff
|
|
input.y:3.26-37: warning: empty character literal
|
|
input.y:3.40-49: invalid number after \-escape: U00000000
|
|
input.y:3.39-50: warning: empty character literal
|
|
input.y:4.9-10: invalid character after \-escape: ` '
|
|
input.y:4.8-11: warning: empty character literal
|
|
input.y:4.14-15: invalid character after \-escape: A
|
|
input.y:4.13-16: warning: empty character literal
|
|
input.y:5.9-16: invalid character after \-escape: \t
|
|
input.y:5.17: invalid character after \-escape: \f
|
|
input.y:5.18: invalid character after \-escape: \0
|
|
input.y:5.19: invalid character after \-escape: \001
|
|
]])
|
|
|
|
AT_CLEANUP
|