mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
See http://www.gnu.org/prep/maintain/maintain.html#Copyright-Notices * HACKING, Makefile.am, NEWS, PACKAGING, README, README-alpha: * TODO, bootstrap, bootstrap.conf: * build-aux/update-b4-copyright, cfg.mk, configure.ac: * data/README, data/bison.m4, data/c++-skel.m4, data/c++.m4: * data/c-skel.m4, data/c.m4, data/glr.c, data/glr.cc: * data/java-skel.m4, data/java.m4, data/lalr1.cc: * data/lalr1.java, data/location.cc: * data/xslt/bison.xsl: * data/xslt/xml2dot.xsl, data/xslt/xml2text.xsl: * data/xslt/xml2xhtml.xsl, data/yacc.c, djgpp/Makefile.maint: * djgpp/README.in, djgpp/config.bat, djgpp/config.sed: * djgpp/config.site, djgpp/config_h.sed, djgpp/djunpack.bat: * djgpp/subpipe.c, djgpp/subpipe.h: * djgpp/testsuite.sed, doc/bison.texinfo: * doc/refcard.tex, etc/README, etc/bench.pl.in: * examples/calc++/Makefile.am, examples/extexi: * lib/abitset.c, lib/abitset.h: * lib/bbitset.h, lib/bitset.c, lib/bitset.h: * lib/bitset_stats.c, lib/bitset_stats.h, lib/bitsetv-print.c: * lib/bitsetv-print.h, lib/bitsetv.c, lib/bitsetv.h: * lib/ebitset.c, lib/ebitset.h, lib/get-errno.c: * lib/get-errno.h, lib/lbitset.c, lib/lbitset.h: * lib/libiberty.h, lib/main.c, lib/timevar.c: * lib/timevar.def, lib/timevar.h, lib/vbitset.c: * lib/vbitset.h, lib/yyerror.c, m4/bison-i18n.m4: * m4/c-working.m4, m4/cxx.m4, m4/subpipe.m4, m4/timevar.m4: * src/AnnotationList.c, src/AnnotationList.h: * src/InadequacyList.c, src/InadequacyList.h, src/LR0.c: * src/LR0.h, src/Sbitset.c, src/Sbitset.h, src/assoc.c: * src/assoc.h, src/closure.c, src/closure.h, src/complain.c: * src/complain.h, src/conflicts.c, src/conflicts.h: * src/derives.c, src/derives.h, src/files.c, src/files.h: * src/flex-scanner.h, src/getargs.c, src/getargs.h: * src/gram.c, src/gram.h, src/graphviz.c, src/ielr.c: * src/ielr.h, src/lalr.c, src/lalr.h: * src/location.c, src/location.h, src/main.c: * src/muscle-tab.c, src/muscle-tab.h, src/named-ref.c: * src/named-ref.h, src/nullable.c, src/nullable.h: * src/output.c, src/output.h, src/parse-gram.y: * src/print-xml.c, src/print-xml.h, src/print.c, src/print.h: * src/print_graph.c, src/print_graph.h, src/reader.c: * src/reader.h, src/reduce.c, src/reduce.h, src/relation.c: * src/relation.h, src/scan-code.h, src/scan-code.l: * src/scan-gram.h, src/scan-gram.l, src/scan-skel.h: * src/scan-skel.l, src/state.c, src/state.h, src/symlist.c: * src/symlist.h, src/symtab.c, src/symtab.h, src/system.h: * src/tables.c, src/tables.h, src/uniqstr.c, src/uniqstr.h: * tests/actions.at, tests/atlocal.in, tests/c++.at: * tests/calc.at, tests/conflicts.at, tests/cxx-type.at: * tests/existing.at, tests/glr-regression.at: * tests/headers.at, tests/input.at, tests/java.at: * tests/local.at, tests/named-refs.at: * tests/output.at, tests/push.at, tests/reduce.at: * tests/regression.at, tests/sets.at, tests/skeletons.at: * tests/synclines.at, tests/testsuite.at, tests/torture.at: * data/Makefile.am, data/location.cc, doc/Makefile.am, src/Makefile.am: * tests/Makefile.am, lib/Makefile.am, examples/Makefile.am: * etc/Makefile.am: Don't use date ranges in copyright notices. Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
474 lines
11 KiB
Plaintext
474 lines
11 KiB
Plaintext
# Checking GLR Parsing. -*- Autotest -*-
|
|
|
|
# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
|
# 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([[C++ Type Syntax (GLR).]])
|
|
|
|
# _AT_TEST_GLR_CXXTYPES(DECL, RESOLVE1, RESOLVE2)
|
|
# -----------------------------------------------
|
|
# Store into types.y the calc program, with DECL inserted as a declaration,
|
|
# and with RESOLVE1 and RESOLVE2 as annotations on the conflicted rule for
|
|
# stmt. Then compile the result.
|
|
m4_define([_AT_TEST_GLR_CXXTYPES],
|
|
[
|
|
AT_BISON_OPTION_PUSHDEFS([$1])
|
|
|
|
AT_DATA_GRAMMAR([types.y],
|
|
[[/* Simplified C++ Type and Expression Grammar. */
|
|
|
|
$1
|
|
|
|
%{
|
|
#include <stdio.h>
|
|
union Node {
|
|
struct {
|
|
int isNterm;
|
|
int parents;
|
|
} nodeInfo;
|
|
struct {
|
|
int isNterm; /* 1 */
|
|
int parents;
|
|
char const *form;
|
|
union Node *children[3];
|
|
} nterm;
|
|
struct {
|
|
int isNterm; /* 0 */
|
|
int parents;
|
|
char *text;
|
|
} term;
|
|
};
|
|
typedef union Node Node;
|
|
static Node *new_nterm (char const *, Node *, Node *, Node *);
|
|
static Node *new_term (char *);
|
|
static void free_node (Node *);
|
|
static char *node_to_string (Node *);
|
|
#define YYSTYPE Node *
|
|
]m4_bmatch([$2], [stmtMerge],
|
|
[ static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);])[
|
|
#define YYINITDEPTH 10
|
|
#define YYSTACKEXPANDABLE 1
|
|
struct YYLTYPE;
|
|
#if YYPURE
|
|
# if YYLSP_NEEDED
|
|
# define LEX_PARAMETERS YYSTYPE *lvalp, struct YYLTYPE *llocp
|
|
# define ERROR_PARAMETERS struct YYLTYPE *llocp, char const *s
|
|
# else
|
|
# define LEX_PARAMETERS YYSTYPE *lvalp
|
|
# endif
|
|
#endif
|
|
#ifndef LEX_PARAMETERS
|
|
# define LEX_PARAMETERS void
|
|
#endif
|
|
#ifndef ERROR_PARAMETERS
|
|
# define ERROR_PARAMETERS char const *s
|
|
#endif
|
|
int yylex (LEX_PARAMETERS);
|
|
void yyerror (ERROR_PARAMETERS);
|
|
%}
|
|
|
|
%token TYPENAME ID
|
|
|
|
%right '='
|
|
%left '+'
|
|
|
|
%glr-parser
|
|
|
|
%destructor { free_node ($$); } stmt expr decl declarator TYPENAME ID
|
|
|
|
%%
|
|
|
|
prog :
|
|
| prog stmt {
|
|
char *output;]AT_LOCATION_IF([
|
|
printf ("%d.%d-%d.%d: ",
|
|
@2.first_line, @2.first_column,
|
|
@2.last_line, @2.last_column);])[
|
|
output = node_to_string (]$[2);
|
|
printf ("%s\n", output);
|
|
free (output);
|
|
free_node (]$[2);
|
|
}
|
|
;
|
|
|
|
stmt : expr ';' $2 { $$ = ]$[1; }
|
|
| decl $3
|
|
| error ';' { $$ = new_nterm ("<error>", 0, 0, 0); }
|
|
| '@' { YYACCEPT; }
|
|
;
|
|
|
|
expr : ID
|
|
| TYPENAME '(' expr ')'
|
|
{ $$ = new_nterm ("<cast>(%s,%s)", ]$[3, ]$[1, 0); }
|
|
| expr '+' expr { $$ = new_nterm ("+(%s,%s)", ]$[1, ]$[3, 0); }
|
|
| expr '=' expr { $$ = new_nterm ("=(%s,%s)", ]$[1, ]$[3, 0); }
|
|
;
|
|
|
|
decl : TYPENAME declarator ';'
|
|
{ $$ = new_nterm ("<declare>(%s,%s)", ]$[1, ]$[2, 0); }
|
|
| TYPENAME declarator '=' expr ';'
|
|
{ $$ = new_nterm ("<init-declare>(%s,%s,%s)", ]$[1,
|
|
]$[2, ]$[4); }
|
|
;
|
|
|
|
declarator : ID
|
|
| '(' declarator ')' { $$ = ]$[2; }
|
|
;
|
|
|
|
%%
|
|
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
if (argc != 2)
|
|
abort ();
|
|
if (!freopen (argv[1], "r", stdin))
|
|
return 3;
|
|
return yyparse ();
|
|
}
|
|
|
|
int
|
|
yylex (LEX_PARAMETERS)
|
|
{
|
|
char buffer[256];
|
|
int c;
|
|
unsigned int i;
|
|
static int lineNum = 1;
|
|
static int colNum = 0;
|
|
|
|
#if YYPURE
|
|
# undef yylloc
|
|
# define yylloc (*llocp)
|
|
# undef yylval
|
|
# define yylval (*lvalp)
|
|
#endif
|
|
|
|
while (1)
|
|
{
|
|
if (feof (stdin))
|
|
abort ();
|
|
c = getchar ();
|
|
switch (c)
|
|
{
|
|
case EOF:
|
|
return 0;
|
|
case '\t':
|
|
colNum = (colNum + 7) & ~7;
|
|
break;
|
|
case ' ': case '\f':
|
|
colNum += 1;
|
|
break;
|
|
case '\n':
|
|
lineNum += 1;
|
|
colNum = 0;
|
|
break;
|
|
default:
|
|
{
|
|
int tok;
|
|
#if YYLSP_NEEDED
|
|
yylloc.first_line = yylloc.last_line = lineNum;
|
|
yylloc.first_column = colNum;
|
|
#endif
|
|
if (isalpha (c))
|
|
{
|
|
i = 0;
|
|
|
|
do
|
|
{
|
|
buffer[i++] = c;
|
|
colNum += 1;
|
|
if (i == sizeof buffer - 1)
|
|
abort ();
|
|
c = getchar ();
|
|
}
|
|
while (isalnum (c) || c == '_');
|
|
|
|
ungetc (c, stdin);
|
|
buffer[i++] = 0;
|
|
tok = isupper ((unsigned char) buffer[0]) ? TYPENAME : ID;
|
|
yylval = new_term (strcpy ((char *) malloc (i), buffer));
|
|
}
|
|
else
|
|
{
|
|
colNum += 1;
|
|
tok = c;
|
|
yylval = 0;
|
|
}
|
|
#if YYLSP_NEEDED
|
|
yylloc.last_column = colNum-1;
|
|
#endif
|
|
return tok;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
yyerror (ERROR_PARAMETERS)
|
|
{
|
|
#if YYPURE && YYLSP_NEEDED
|
|
/* Pacify GCC by using llocp. */
|
|
if (! llocp)
|
|
abort ();
|
|
#endif
|
|
fprintf (stderr, "%s\n", s);
|
|
}
|
|
|
|
static Node *
|
|
new_nterm (char const *form, Node *child0, Node *child1, Node *child2)
|
|
{
|
|
Node *node = (Node *) malloc (sizeof (Node));
|
|
node->nterm.isNterm = 1;
|
|
node->nterm.parents = 0;
|
|
node->nterm.form = form;
|
|
node->nterm.children[0] = child0;
|
|
if (child0)
|
|
child0->nodeInfo.parents += 1;
|
|
node->nterm.children[1] = child1;
|
|
if (child1)
|
|
child1->nodeInfo.parents += 1;
|
|
node->nterm.children[2] = child2;
|
|
if (child2)
|
|
child2->nodeInfo.parents += 1;
|
|
return node;
|
|
}
|
|
|
|
static Node *
|
|
new_term (char *text)
|
|
{
|
|
Node *node = (Node *) malloc (sizeof (Node));
|
|
node->term.isNterm = 0;
|
|
node->term.parents = 0;
|
|
node->term.text = text;
|
|
return node;
|
|
}
|
|
|
|
static void
|
|
free_node (Node *node)
|
|
{
|
|
if (!node)
|
|
return;
|
|
node->nodeInfo.parents -= 1;
|
|
/* Free only if 0 (last parent) or -1 (no parents). */
|
|
if (node->nodeInfo.parents > 0)
|
|
return;
|
|
if (node->nodeInfo.isNterm == 1)
|
|
{
|
|
free_node (node->nterm.children[0]);
|
|
free_node (node->nterm.children[1]);
|
|
free_node (node->nterm.children[2]);
|
|
}
|
|
else
|
|
free (node->term.text);
|
|
free (node);
|
|
}
|
|
|
|
static char *
|
|
node_to_string (Node *node)
|
|
{
|
|
char *child0;
|
|
char *child1;
|
|
char *child2;
|
|
char *buffer;
|
|
if (!node)
|
|
{
|
|
buffer = (char *) malloc (1);
|
|
buffer[0] = 0;
|
|
}
|
|
else if (node->nodeInfo.isNterm == 1)
|
|
{
|
|
child0 = node_to_string (node->nterm.children[0]);
|
|
child1 = node_to_string (node->nterm.children[1]);
|
|
child2 = node_to_string (node->nterm.children[2]);
|
|
buffer = (char *) malloc (strlen (node->nterm.form) + strlen (child0)
|
|
+ strlen (child1) + strlen (child2) + 1);
|
|
sprintf (buffer, node->nterm.form, child0, child1, child2);
|
|
free (child0);
|
|
free (child1);
|
|
free (child2);
|
|
}
|
|
else
|
|
buffer = strdup (node->term.text);
|
|
return buffer;
|
|
}
|
|
|
|
]]
|
|
m4_bmatch([$2], [stmtMerge],
|
|
[[static YYSTYPE
|
|
stmtMerge (YYSTYPE x0, YYSTYPE x1)
|
|
{
|
|
return new_nterm ("<OR>(%s,%s)", x0, x1, 0);
|
|
}
|
|
]])
|
|
)
|
|
|
|
AT_DATA([test-input],
|
|
[[
|
|
|
|
z + q;
|
|
|
|
T x;
|
|
|
|
T x = y;
|
|
|
|
x = y;
|
|
|
|
T (x) + y;
|
|
|
|
T (x);
|
|
|
|
T (y) = z + q;
|
|
|
|
T (y y) = z + q;
|
|
|
|
z + q;
|
|
|
|
@
|
|
|
|
This is total garbage, but it should be ignored.
|
|
]])
|
|
|
|
AT_BISON_CHECK([-o types.c types.y], 0, [], ignore)
|
|
AT_COMPILE([types])
|
|
AT_BISON_OPTION_POPDEFS
|
|
])
|
|
|
|
m4_define([_AT_RESOLVED_GLR_OUTPUT],
|
|
[[[+(z,q)
|
|
<declare>(T,x)
|
|
<init-declare>(T,x,y)
|
|
=(x,y)
|
|
+(<cast>(x,T),y)
|
|
<declare>(T,x)
|
|
<init-declare>(T,y,+(z,q))
|
|
<error>
|
|
+(z,q)
|
|
]]])
|
|
|
|
m4_define([_AT_RESOLVED_GLR_OUTPUT_WITH_LOC],
|
|
[[[3.0-3.5: +(z,q)
|
|
5.0-5.3: <declare>(T,x)
|
|
7.0-7.7: <init-declare>(T,x,y)
|
|
9.0-9.5: =(x,y)
|
|
11.0-11.9: +(<cast>(x,T),y)
|
|
13.0-13.5: <declare>(T,x)
|
|
15.0-15.13: <init-declare>(T,y,+(z,q))
|
|
17.0-17.15: <error>
|
|
19.0-19.5: +(z,q)
|
|
]]])
|
|
|
|
m4_define([_AT_AMBIG_GLR_OUTPUT],
|
|
[[[+(z,q)
|
|
<declare>(T,x)
|
|
<init-declare>(T,x,y)
|
|
=(x,y)
|
|
+(<cast>(x,T),y)
|
|
<OR>(<declare>(T,x),<cast>(x,T))
|
|
<OR>(<init-declare>(T,y,+(z,q)),=(<cast>(y,T),+(z,q)))
|
|
<error>
|
|
+(z,q)
|
|
]]])
|
|
|
|
m4_define([_AT_AMBIG_GLR_OUTPUT_WITH_LOC],
|
|
[[[3.0-3.5: +(z,q)
|
|
5.0-5.3: <declare>(T,x)
|
|
7.0-7.7: <init-declare>(T,x,y)
|
|
9.0-9.5: =(x,y)
|
|
11.0-11.9: +(<cast>(x,T),y)
|
|
13.0-13.5: <OR>(<declare>(T,x),<cast>(x,T))
|
|
15.0-15.13: <OR>(<init-declare>(T,y,+(z,q)),=(<cast>(y,T),+(z,q)))
|
|
17.0-17.15: <error>
|
|
19.0-19.5: +(z,q)
|
|
]]])
|
|
|
|
m4_define([_AT_GLR_STDERR],
|
|
[[[syntax error
|
|
]]])
|
|
|
|
m4_define([_AT_VERBOSE_GLR_STDERR],
|
|
[[[syntax error, unexpected ID, expecting '=' or '+' or ')'
|
|
]]])
|
|
|
|
## ---------------------------------------------------- ##
|
|
## Compile the grammar described in the documentation. ##
|
|
## ---------------------------------------------------- ##
|
|
|
|
AT_SETUP([GLR: Resolve ambiguity, impure, no locations])
|
|
_AT_TEST_GLR_CXXTYPES([],
|
|
[%dprec 1], [%dprec 2])
|
|
AT_PARSER_CHECK([[./types test-input]], 0,
|
|
_AT_RESOLVED_GLR_OUTPUT, _AT_GLR_STDERR)
|
|
AT_CLEANUP
|
|
|
|
AT_SETUP([GLR: Resolve ambiguity, impure, locations])
|
|
_AT_TEST_GLR_CXXTYPES([%locations],[%dprec 1],[%dprec 2])
|
|
AT_PARSER_CHECK([[./types test-input]], 0,
|
|
_AT_RESOLVED_GLR_OUTPUT_WITH_LOC, _AT_GLR_STDERR)
|
|
AT_CLEANUP
|
|
|
|
AT_SETUP([GLR: Resolve ambiguity, pure, no locations])
|
|
_AT_TEST_GLR_CXXTYPES([%define api.pure],
|
|
[%dprec 1], [%dprec 2])
|
|
AT_PARSER_CHECK([[./types test-input]], 0,
|
|
_AT_RESOLVED_GLR_OUTPUT, _AT_GLR_STDERR)
|
|
AT_CLEANUP
|
|
|
|
AT_SETUP([GLR: Resolve ambiguity, pure, locations])
|
|
_AT_TEST_GLR_CXXTYPES([%define api.pure %locations],
|
|
[%dprec 1], [%dprec 2])
|
|
AT_PARSER_CHECK([[./types test-input]], 0,
|
|
_AT_RESOLVED_GLR_OUTPUT_WITH_LOC, _AT_GLR_STDERR)
|
|
AT_CLEANUP
|
|
|
|
AT_SETUP([GLR: Merge conflicting parses, impure, no locations])
|
|
_AT_TEST_GLR_CXXTYPES([],
|
|
[%merge <stmtMerge>], [%merge <stmtMerge>])
|
|
AT_PARSER_CHECK([[./types test-input]], 0,
|
|
_AT_AMBIG_GLR_OUTPUT, _AT_GLR_STDERR)
|
|
AT_CLEANUP
|
|
|
|
AT_SETUP([GLR: Merge conflicting parses, impure, locations])
|
|
_AT_TEST_GLR_CXXTYPES([%locations],
|
|
[%merge <stmtMerge>], [%merge <stmtMerge>])
|
|
AT_PARSER_CHECK([[./types test-input]], 0,
|
|
_AT_AMBIG_GLR_OUTPUT_WITH_LOC, _AT_GLR_STDERR)
|
|
AT_CLEANUP
|
|
|
|
AT_SETUP([GLR: Merge conflicting parses, pure, no locations])
|
|
_AT_TEST_GLR_CXXTYPES([%define api.pure],
|
|
[%merge <stmtMerge>], [%merge <stmtMerge>])
|
|
AT_PARSER_CHECK([[./types test-input]], 0,
|
|
_AT_AMBIG_GLR_OUTPUT, _AT_GLR_STDERR)
|
|
AT_CLEANUP
|
|
AT_SETUP([GLR: Merge conflicting parses, pure, locations])
|
|
_AT_TEST_GLR_CXXTYPES([%define api.pure %locations],
|
|
[%merge <stmtMerge>],[%merge <stmtMerge>])
|
|
AT_PARSER_CHECK([[./types test-input]], 0,
|
|
_AT_AMBIG_GLR_OUTPUT_WITH_LOC, _AT_GLR_STDERR)
|
|
AT_CLEANUP
|
|
|
|
AT_SETUP([GLR: Verbose messages, resolve ambiguity, impure, no locations])
|
|
_AT_TEST_GLR_CXXTYPES([%error-verbose],
|
|
[%merge <stmtMerge>], [%merge <stmtMerge>])
|
|
AT_PARSER_CHECK([[./types test-input]], 0,
|
|
_AT_AMBIG_GLR_OUTPUT, _AT_VERBOSE_GLR_STDERR)
|
|
AT_CLEANUP
|