mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
glr.c: example: several improvements
* examples/c/glr/c++-types.y (node_print): New. Use YY_LOCATION_PRINT instead of duplicating it. And actually use it in the action instead of badly duplicating it. (main): Add proper option support. * examples/c/glr/c++-types.test: Adjust expectations on locations. * examples/c++/glr/c++-types.yy: Fix bad iteration.
This commit is contained in:
4
TODO
4
TODO
@@ -1,4 +1,8 @@
|
|||||||
* Soon
|
* Soon
|
||||||
|
** YY_LOCATION_PRINT
|
||||||
|
This is an internal detail. But it's very handy, we should make it public.
|
||||||
|
It already has leaked in the documentation by accident.
|
||||||
|
|
||||||
** glr
|
** glr
|
||||||
There is no test with "Parse on stack %ld rejected by rule %d" in it.
|
There is no test with "Parse on stack %ld rejected by rule %d" in it.
|
||||||
|
|
||||||
|
|||||||
@@ -192,11 +192,11 @@ main (int argc, char **argv)
|
|||||||
bool ran = false;
|
bool ran = false;
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
// Enable parse traces on option -p.
|
// Enable parse traces on option -p.
|
||||||
if (strcmp (argv[1], "-p") == 0)
|
if (strcmp (argv[i], "-p") == 0)
|
||||||
parse.set_debug_level (1);
|
parse.set_debug_level (1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int status = process (parse, argv[1]);
|
int status = process (parse, argv[i]);
|
||||||
ran = true;
|
ran = true;
|
||||||
if (!status)
|
if (!status)
|
||||||
return status;
|
return status;
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ T (y y) = z + q;
|
|||||||
z + q;
|
z + q;
|
||||||
EOF
|
EOF
|
||||||
run 0 "\
|
run 0 "\
|
||||||
1.0-1.5: +(z,q)
|
1.0-4: +(z,q)
|
||||||
3.0-3.3: <declare>(T,x)
|
3.0-2: <declare>(T,x)
|
||||||
5.0-5.7: <init-declare>(T,x,y)
|
5.0-6: <init-declare>(T,x,y)
|
||||||
7.0-7.5: =(x,y)
|
7.0-4: =(x,y)
|
||||||
9.0-9.9: +(<cast>(x,T),y)
|
9.0-8: +(<cast>(x,T),y)
|
||||||
11.0-11.5: <OR>(<declare>(T,x),<cast>(x,T))
|
11.0-4: <OR>(<declare>(T,x),<cast>(x,T))
|
||||||
13.0-13.13: <OR>(<init-declare>(T,y,+(z,q)),=(<cast>(y,T),+(z,q)))
|
13.0-12: <OR>(<init-declare>(T,y,+(z,q)),=(<cast>(y,T),+(z,q)))
|
||||||
15.0-15.15: <error>
|
15.0-14: <error>
|
||||||
17.0-17.5: +(z,q)
|
17.0-4: +(z,q)
|
||||||
err: 15.5: syntax error, unexpected identifier, expecting '=' or '+' or ')'"
|
err: 15.5: syntax error, unexpected identifier, expecting '=' or '+' or ')'"
|
||||||
|
|||||||
@@ -1,4 +1,22 @@
|
|||||||
/* Simplified C++ Type and Expression Grammar. */
|
/* -*- C -*-
|
||||||
|
Copyright (C) 2020 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Simplified C++ Type and Expression Grammar.
|
||||||
|
Written by Paul Hilfinger for Bison's test suite. */
|
||||||
|
|
||||||
%define api.pure
|
%define api.pure
|
||||||
%header
|
%header
|
||||||
@@ -47,9 +65,9 @@
|
|||||||
static Node *new_term (char *);
|
static Node *new_term (char *);
|
||||||
static void free_node (Node *);
|
static void free_node (Node *);
|
||||||
static char *node_to_string (Node *);
|
static char *node_to_string (Node *);
|
||||||
|
static void node_print (FILE *, Node *);
|
||||||
static Node *stmtMerge (YYSTYPE x0, YYSTYPE x1);
|
static Node *stmtMerge (YYSTYPE x0, YYSTYPE x1);
|
||||||
|
|
||||||
static int location_print (FILE *yyo, YYLTYPE const * const yylocp);
|
|
||||||
static void yyerror (YYLTYPE const * const llocp, const char *msg);
|
static void yyerror (YYLTYPE const * const llocp, const char *msg);
|
||||||
static yytoken_kind_t yylex (YYSTYPE *lvalp, YYLTYPE *llocp);
|
static yytoken_kind_t yylex (YYSTYPE *lvalp, YYLTYPE *llocp);
|
||||||
}
|
}
|
||||||
@@ -67,17 +85,16 @@
|
|||||||
|
|
||||||
%type <Node*> stmt expr decl declarator TYPENAME ID
|
%type <Node*> stmt expr decl declarator TYPENAME ID
|
||||||
%destructor { free_node ($$); } <Node*>
|
%destructor { free_node ($$); } <Node*>
|
||||||
|
%printer { node_print (yyo, $$); } <Node*>
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
prog : %empty
|
prog : %empty
|
||||||
| prog stmt {
|
| prog stmt {
|
||||||
char *output = node_to_string ($2);
|
YY_LOCATION_PRINT (stdout, @2);
|
||||||
printf ("%d.%d-%d.%d: %s\n",
|
fputs (": ", stdout);
|
||||||
@2.first_line, @2.first_column,
|
node_print (stdout, $2);
|
||||||
@2.last_line, @2.last_column,
|
putc ('\n', stdout);
|
||||||
output);
|
|
||||||
free (output);
|
|
||||||
free_node ($2);
|
free_node ($2);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@@ -108,51 +125,17 @@ declarator
|
|||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
int
|
|
||||||
main (int argc, char **argv)
|
|
||||||
{
|
|
||||||
// Enable parse traces on option -p.
|
|
||||||
if (1 < argc && strcmp (argv[1], "-p") == 0)
|
|
||||||
yydebug = 1;
|
|
||||||
return yyparse ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Print *YYLOCP on YYO. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
location_print (FILE *yyo, YYLTYPE const * const yylocp)
|
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
|
|
||||||
if (0 <= yylocp->first_line)
|
|
||||||
{
|
|
||||||
res += fprintf (yyo, "%d", yylocp->first_line);
|
|
||||||
if (0 <= yylocp->first_column)
|
|
||||||
res += fprintf (yyo, ".%d", yylocp->first_column);
|
|
||||||
}
|
|
||||||
if (0 <= yylocp->last_line)
|
|
||||||
{
|
|
||||||
if (yylocp->first_line < yylocp->last_line)
|
|
||||||
{
|
|
||||||
res += fprintf (yyo, "-%d", yylocp->last_line);
|
|
||||||
if (0 <= end_col)
|
|
||||||
res += fprintf (yyo, ".%d", end_col);
|
|
||||||
}
|
|
||||||
else if (0 <= end_col && yylocp->first_column < end_col)
|
|
||||||
res += fprintf (yyo, "-%d", end_col);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A C error reporting function. */
|
/* A C error reporting function. */
|
||||||
static
|
static
|
||||||
void yyerror (YYLTYPE const * const llocp, const char *msg)
|
void yyerror (YYLTYPE const * const llocp, const char *msg)
|
||||||
{
|
{
|
||||||
location_print (stderr, llocp);
|
YY_LOCATION_PRINT (stderr, *llocp);
|
||||||
fprintf (stderr, ": %s\n", msg);
|
fprintf (stderr, ": %s\n", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The input file. */
|
||||||
|
FILE * input = NULL;
|
||||||
|
|
||||||
yytoken_kind_t
|
yytoken_kind_t
|
||||||
yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
|
yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
|
||||||
{
|
{
|
||||||
@@ -162,8 +145,8 @@ yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
|
|||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
assert (!feof (stdin));
|
assert (!feof (input));
|
||||||
c = getchar ();
|
c = getc (input);
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case EOF:
|
case EOF:
|
||||||
@@ -193,11 +176,11 @@ yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
|
|||||||
buffer[i++] = (char) c;
|
buffer[i++] = (char) c;
|
||||||
colNum += 1;
|
colNum += 1;
|
||||||
assert (i != sizeof buffer - 1);
|
assert (i != sizeof buffer - 1);
|
||||||
c = getchar ();
|
c = getc (input);
|
||||||
}
|
}
|
||||||
while (isalnum (c) || c == '_');
|
while (isalnum (c) || c == '_');
|
||||||
|
|
||||||
ungetc (c, stdin);
|
ungetc (c, input);
|
||||||
buffer[i++] = 0;
|
buffer[i++] = 0;
|
||||||
if (isupper ((unsigned char) buffer[0]))
|
if (isupper ((unsigned char) buffer[0]))
|
||||||
{
|
{
|
||||||
@@ -297,9 +280,59 @@ node_to_string (Node *node)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void node_print (FILE *out, Node *n)
|
||||||
|
{
|
||||||
|
char *str = node_to_string (n);
|
||||||
|
fputs (str, out);
|
||||||
|
free (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static Node*
|
static Node*
|
||||||
stmtMerge (YYSTYPE x0, YYSTYPE x1)
|
stmtMerge (YYSTYPE x0, YYSTYPE x1)
|
||||||
{
|
{
|
||||||
return new_nterm ("<OR>(%s,%s)", x0.stmt, x1.stmt, NULL);
|
return new_nterm ("<OR>(%s,%s)", x0.stmt, x1.stmt, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
process (const char *file)
|
||||||
|
{
|
||||||
|
int is_stdin = !file || strcmp (file, "-") == 0;
|
||||||
|
if (is_stdin)
|
||||||
|
input = stdin;
|
||||||
|
else
|
||||||
|
input = fopen (file, "r");
|
||||||
|
assert (input);
|
||||||
|
int status = yyparse ();
|
||||||
|
if (!is_stdin)
|
||||||
|
fclose (input);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (getenv ("YYDEBUG"))
|
||||||
|
yydebug = 1;
|
||||||
|
|
||||||
|
int ran = 0;
|
||||||
|
for (int i = 1; i < argc; ++i)
|
||||||
|
// Enable parse traces on option -p.
|
||||||
|
if (strcmp (argv[i], "-p") == 0)
|
||||||
|
yydebug = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int status = process (argv[i]);
|
||||||
|
ran = 1;
|
||||||
|
if (!status)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ran)
|
||||||
|
{
|
||||||
|
int status = process (NULL);
|
||||||
|
if (!status)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user