mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
examples: clean up
* examples/c/calc/calc.y: Restore to its original state, with parse.error=detailed instead of parse.error=custom (this example should be simple). * examples/c/calc/calc.test: Check syntax errors. * examples/c/lexcalc/parse.y: Add comments.
This commit is contained in:
@@ -34,4 +34,10 @@ cat >input <<EOF
|
|||||||
(1+2) * 3
|
(1+2) * 3
|
||||||
EOF
|
EOF
|
||||||
run 0 9
|
run 0 9
|
||||||
|
# Check the traces.
|
||||||
run -noerr 0 9 -p
|
run -noerr 0 9 -p
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
1++2
|
||||||
|
EOF
|
||||||
|
run 0 "err: syntax error, unexpected '+', expecting number or '('"
|
||||||
|
|||||||
@@ -1,50 +1,35 @@
|
|||||||
%code top {
|
%code top {
|
||||||
#include <ctype.h> /* isdigit. */
|
#include <ctype.h> /* isdigit. */
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h> /* For printf, etc. */
|
#include <stdio.h> /* For printf, etc. */
|
||||||
#include <string.h> /* strcmp. */
|
#include <string.h> /* strcmp. */
|
||||||
|
|
||||||
int yylex (void);
|
int yylex (void);
|
||||||
void yyerror (char const *);
|
void yyerror (char const *);
|
||||||
|
|
||||||
bool show_expected = false;
|
|
||||||
|
|
||||||
#define PRINT_EXPECTED_TOKENS() \
|
|
||||||
do { \
|
|
||||||
if (show_expected) \
|
|
||||||
{ \
|
|
||||||
yyparse_context_t ctx \
|
|
||||||
= {yyssp, yytoken, yyesa, &yyes, &yyes_capacity}; \
|
|
||||||
int tokens[YYNTOKENS]; \
|
|
||||||
int cnt = yyexpected_tokens (&ctx, tokens, YYNTOKENS); \
|
|
||||||
fprintf (stderr, "expected tokens in state %d rule %d (%d):", \
|
|
||||||
*yyssp, yyn - 1, cnt); \
|
|
||||||
for (int i = 0; i < cnt; ++i) \
|
|
||||||
fprintf (stderr, " %s", yysymbol_name(tokens[i])); \
|
|
||||||
fprintf (stderr, "\n"); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
%define api.header.include {"calc.h"}
|
%define api.header.include {"calc.h"}
|
||||||
%define api.value.type union /* Generate YYSTYPE from these types: */
|
|
||||||
%define parse.error custom
|
/* Generate YYSTYPE from the types used in %token and %type. */
|
||||||
%define parse.lac full
|
%define api.value.type union
|
||||||
%token <double> NUM "number"
|
%token <double> NUM "number"
|
||||||
%type <double> expr term fact
|
%type <double> expr term fact
|
||||||
|
|
||||||
/* Generate the parser description file. */
|
/* Generate the parser description file (calc.output). */
|
||||||
%verbose
|
%verbose
|
||||||
|
|
||||||
|
/* Nice error messages with details. */
|
||||||
|
%define parse.error detailed
|
||||||
|
|
||||||
/* Enable run-time traces (yydebug). */
|
/* Enable run-time traces (yydebug). */
|
||||||
%define parse.trace
|
%define parse.trace
|
||||||
|
|
||||||
/* Formatting semantic values. */
|
/* Formatting semantic values in debug traces. */
|
||||||
%printer { fprintf (yyo, "%g", $$); } <double>;
|
%printer { fprintf (yyo, "%g", $$); } <double>;
|
||||||
|
|
||||||
%% /* The grammar follows. */
|
%% /* The grammar follows. */
|
||||||
input:
|
input:
|
||||||
%empty { PRINT_EXPECTED_TOKENS (); }
|
%empty
|
||||||
| input line { PRINT_EXPECTED_TOKENS (); }
|
| input line
|
||||||
;
|
;
|
||||||
|
|
||||||
line:
|
line:
|
||||||
@@ -66,34 +51,12 @@ term:
|
|||||||
;
|
;
|
||||||
|
|
||||||
fact:
|
fact:
|
||||||
"number" { PRINT_EXPECTED_TOKENS (); }
|
"number"
|
||||||
| '(' expr { PRINT_EXPECTED_TOKENS (); } ')' { $$ = $expr; }
|
| '(' expr ')' { $$ = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
int
|
|
||||||
yyreport_syntax_error (const yyparse_context_t *ctx)
|
|
||||||
{
|
|
||||||
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 10 };
|
|
||||||
/* Arguments of yyformat: reported tokens (one for the "unexpected",
|
|
||||||
one per "expected"). */
|
|
||||||
int arg[YYERROR_VERBOSE_ARGS_MAXIMUM];
|
|
||||||
int n = yysyntax_error_arguments (ctx, arg, sizeof arg / sizeof *arg);
|
|
||||||
if (n == -2)
|
|
||||||
return 2;
|
|
||||||
fprintf (stderr, "SYNTAX ERROR on token [%s]", yysymbol_name (arg[0]));
|
|
||||||
if (1 < n)
|
|
||||||
{
|
|
||||||
fprintf (stderr, " (expected:");
|
|
||||||
for (int i = 1; i < n; ++i)
|
|
||||||
fprintf (stderr, " [%s]", yysymbol_name (arg[i]));
|
|
||||||
fprintf (stderr, ")");
|
|
||||||
}
|
|
||||||
fprintf (stderr, "\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
yylex (void)
|
yylex (void)
|
||||||
{
|
{
|
||||||
@@ -130,9 +93,7 @@ main (int argc, char const* argv[])
|
|||||||
{
|
{
|
||||||
/* Enable parse traces on option -p. */
|
/* Enable parse traces on option -p. */
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
if (!strcmp (argv[i], "-e"))
|
if (!strcmp (argv[i], "-p"))
|
||||||
show_expected = 1;
|
|
||||||
else if (!strcmp (argv[i], "-p"))
|
|
||||||
yydebug = 1;
|
yydebug = 1;
|
||||||
return yyparse ();
|
return yyparse ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,23 @@
|
|||||||
#include <stdlib.h> // getenv.
|
#include <stdlib.h> // getenv.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't share global variables between the scanner and the parser.
|
||||||
%define api.pure full
|
%define api.pure full
|
||||||
|
|
||||||
|
// To avoid name clashes (e.g., with C's EOF) prefix token definitions
|
||||||
|
// with TOK_ (e.g., TOK_EOF).
|
||||||
%define api.token.prefix {TOK_}
|
%define api.token.prefix {TOK_}
|
||||||
|
|
||||||
|
// %token and %type use genuine types (e.g., "%token <int>"). Let
|
||||||
|
// %bison define YYSTYPE as a union of all these types.
|
||||||
%define api.value.type union
|
%define api.value.type union
|
||||||
%define parse.error verbose
|
|
||||||
|
// Generate detailed error messages.
|
||||||
|
%define parse.error detailed
|
||||||
|
|
||||||
|
// Enable debug traces (see yydebug in main).
|
||||||
%define parse.trace
|
%define parse.trace
|
||||||
|
|
||||||
// Error count, exchanged between main, yyparse and yylex.
|
// Error count, exchanged between main, yyparse and yylex.
|
||||||
%param {int *nerrs}
|
%param {int *nerrs}
|
||||||
|
|
||||||
@@ -77,6 +89,7 @@ exp:
|
|||||||
;
|
;
|
||||||
%%
|
%%
|
||||||
// Epilogue (C code).
|
// Epilogue (C code).
|
||||||
|
|
||||||
void yyerror (int *nerrs, const char *msg)
|
void yyerror (int *nerrs, const char *msg)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s\n", msg);
|
fprintf (stderr, "%s\n", msg);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Prologue (directives). -*- C++ -*- */
|
/* Prologue (directives). -*- C -*- */
|
||||||
|
|
||||||
/* Disable Flex features we don't need, to avoid warnings. */
|
/* Disable Flex features we don't need, to avoid warnings. */
|
||||||
%option nodefault noinput nounput noyywrap
|
%option nodefault noinput nounput noyywrap
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Prologue (directives). -*- C++ -*- */
|
/* Prologue (directives). -*- C -*- */
|
||||||
|
|
||||||
/* Disable Flex features we don't need, to avoid warnings. */
|
/* Disable Flex features we don't need, to avoid warnings. */
|
||||||
%option nodefault noinput nounput noyywrap
|
%option nodefault noinput nounput noyywrap
|
||||||
@@ -17,10 +17,14 @@
|
|||||||
|
|
||||||
%%
|
%%
|
||||||
%{
|
%{
|
||||||
|
// Number of opened parentheses.
|
||||||
int nesting = 0;
|
int nesting = 0;
|
||||||
|
// A buffer storing the text inside the outer parentheses.
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
int size = 0;
|
// Its allocated size.
|
||||||
int capacity = 0;
|
int capacity = 0;
|
||||||
|
// Its used size.
|
||||||
|
int size = 0;
|
||||||
#define STR_APPEND() \
|
#define STR_APPEND() \
|
||||||
do { \
|
do { \
|
||||||
if (capacity < size + yyleng + 1) \
|
if (capacity < size + yyleng + 1) \
|
||||||
|
|||||||
Reference in New Issue
Block a user