summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/c/calc/calc.test6
-rw-r--r--examples/c/calc/calc.y67
-rw-r--r--examples/c/lexcalc/parse.y17
-rw-r--r--examples/c/lexcalc/scan.l2
-rw-r--r--examples/c/reccalc/scan.l8
5 files changed, 42 insertions, 58 deletions
diff --git a/examples/c/calc/calc.test b/examples/c/calc/calc.test
index 9f3c9e2f..d778cf75 100644
--- a/examples/c/calc/calc.test
+++ b/examples/c/calc/calc.test
@@ -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 '('"
diff --git a/examples/c/calc/calc.y b/examples/c/calc/calc.y
index 20f000a2..7757648d 100644
--- a/examples/c/calc/calc.y
+++ b/examples/c/calc/calc.y
@@ -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,35 +51,13 @@ 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)
{
int c;
@@ -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 ();
}
diff --git a/examples/c/lexcalc/parse.y b/examples/c/lexcalc/parse.y
index 68b1b175..060af4ab 100644
--- a/examples/c/lexcalc/parse.y
+++ b/examples/c/lexcalc/parse.y
@@ -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);
diff --git a/examples/c/lexcalc/scan.l b/examples/c/lexcalc/scan.l
index 815f7782..e0b68504 100644
--- a/examples/c/lexcalc/scan.l
+++ b/examples/c/lexcalc/scan.l
@@ -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
diff --git a/examples/c/reccalc/scan.l b/examples/c/reccalc/scan.l
index fbb781aa..0bf5210c 100644
--- a/examples/c/reccalc/scan.l
+++ b/examples/c/reccalc/scan.l
@@ -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) \