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
|
||||
EOF
|
||||
run 0 9
|
||||
# Check the traces.
|
||||
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 {
|
||||
#include <ctype.h> /* isdigit. */
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h> /* For printf, etc. */
|
||||
#include <string.h> /* strcmp. */
|
||||
|
||||
int yylex (void);
|
||||
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.value.type union /* Generate YYSTYPE from these types: */
|
||||
%define parse.error custom
|
||||
%define parse.lac full
|
||||
|
||||
/* Generate YYSTYPE from the types used in %token and %type. */
|
||||
%define api.value.type union
|
||||
%token <double> NUM "number"
|
||||
%type <double> expr term fact
|
||||
|
||||
/* Generate the parser description file. */
|
||||
/* Generate the parser description file (calc.output). */
|
||||
%verbose
|
||||
|
||||
/* Nice error messages with details. */
|
||||
%define parse.error detailed
|
||||
|
||||
/* Enable run-time traces (yydebug). */
|
||||
%define parse.trace
|
||||
|
||||
/* Formatting semantic values. */
|
||||
/* Formatting semantic values in debug traces. */
|
||||
%printer { fprintf (yyo, "%g", $$); } <double>;
|
||||
|
||||
%% /* The grammar follows. */
|
||||
input:
|
||||
%empty { PRINT_EXPECTED_TOKENS (); }
|
||||
| input line { PRINT_EXPECTED_TOKENS (); }
|
||||
%empty
|
||||
| input line
|
||||
;
|
||||
|
||||
line:
|
||||
@@ -66,34 +51,12 @@ term:
|
||||
;
|
||||
|
||||
fact:
|
||||
"number" { PRINT_EXPECTED_TOKENS (); }
|
||||
| '(' expr { PRINT_EXPECTED_TOKENS (); } ')' { $$ = $expr; }
|
||||
"number"
|
||||
| '(' 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
|
||||
yylex (void)
|
||||
{
|
||||
@@ -130,9 +93,7 @@ main (int argc, char const* argv[])
|
||||
{
|
||||
/* Enable parse traces on option -p. */
|
||||
for (int i = 1; i < argc; ++i)
|
||||
if (!strcmp (argv[i], "-e"))
|
||||
show_expected = 1;
|
||||
else if (!strcmp (argv[i], "-p"))
|
||||
if (!strcmp (argv[i], "-p"))
|
||||
yydebug = 1;
|
||||
return yyparse ();
|
||||
}
|
||||
|
||||
@@ -19,12 +19,24 @@
|
||||
#include <stdlib.h> // getenv.
|
||||
}
|
||||
|
||||
// Don't share global variables between the scanner and the parser.
|
||||
%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_}
|
||||
|
||||
// %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 parse.error verbose
|
||||
|
||||
// Generate detailed error messages.
|
||||
%define parse.error detailed
|
||||
|
||||
// Enable debug traces (see yydebug in main).
|
||||
%define parse.trace
|
||||
// Error count, exchanged between main, yyparse and yylex.
|
||||
|
||||
// Error count, exchanged between main, yyparse and yylex.
|
||||
%param {int *nerrs}
|
||||
|
||||
%token
|
||||
@@ -77,6 +89,7 @@ exp:
|
||||
;
|
||||
%%
|
||||
// Epilogue (C code).
|
||||
|
||||
void yyerror (int *nerrs, const char *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. */
|
||||
%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. */
|
||||
%option nodefault noinput nounput noyywrap
|
||||
@@ -17,10 +17,14 @@
|
||||
|
||||
%%
|
||||
%{
|
||||
// Number of opened parentheses.
|
||||
int nesting = 0;
|
||||
// A buffer storing the text inside the outer parentheses.
|
||||
char *str = NULL;
|
||||
int size = 0;
|
||||
// Its allocated size.
|
||||
int capacity = 0;
|
||||
// Its used size.
|
||||
int size = 0;
|
||||
#define STR_APPEND() \
|
||||
do { \
|
||||
if (capacity < size + yyleng + 1) \
|
||||
|
||||
Reference in New Issue
Block a user