diff options
author | Akim Demaille <akim.demaille@gmail.com> | 2020-02-29 09:54:34 +0100 |
---|---|---|
committer | Akim Demaille <akim.demaille@gmail.com> | 2020-02-29 12:15:19 +0100 |
commit | 388e12ac0f79317d5d8caea84931a900d9d91f7f (patch) | |
tree | 713013254daf21202b6d12939d9b29f72d1c4217 /examples | |
parent | b870d5fee40e0bf815e8750452f30b3b3d0067a3 (diff) | |
download | bison-388e12ac0f79317d5d8caea84931a900d9d91f7f.tar.gz |
examples: lexcalc: demonstrate location tracking
The bistromathic example should not use Flex, it makes it too complex.
But it was the only example to show location tracking with Flex.
* examples/c/lexcalc/lexcalc.test, examples/c/lexcalc/parse.y,
* examples/c/lexcalc/scan.l: Demonstrate location tracking as is done
in bistromathic.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/c/README.md | 5 | ||||
-rw-r--r-- | examples/c/bistromathic/README.md | 2 | ||||
-rw-r--r-- | examples/c/bistromathic/parse.y | 4 | ||||
-rw-r--r-- | examples/c/lexcalc/README.md | 2 | ||||
-rw-r--r-- | examples/c/lexcalc/lexcalc.test | 7 | ||||
-rw-r--r-- | examples/c/lexcalc/parse.y | 14 | ||||
-rw-r--r-- | examples/c/lexcalc/scan.l | 25 |
7 files changed, 43 insertions, 16 deletions
diff --git a/examples/c/README.md b/examples/c/README.md index 893dfe2f..1a98d462 100644 --- a/examples/c/README.md +++ b/examples/c/README.md @@ -28,7 +28,8 @@ Extracted from the documentation: "Multi-Function Calculator: mfcalc". https://www.gnu.org/software/bison/manual/html_node/Multi_002dfunction-Calc.html ## lexcalc - calculator with Flex and Bison -The calculator, redux. This time using a scanner generated by Flex. +The calculator with precedence directives and location tracking. It uses +Flex to generate the scanner. ## reccalc - recursive calculator with Flex and Bison The example builds on top of the previous one to provide a reentrant parser. @@ -53,7 +54,7 @@ This example demonstrates the best practices when using Bison. - Its interface is pure. - It uses a custom syntax error with location tracking, lookahead correction and token internationalization. -- It enables debug trace support with formatting of semantic values. +- It supports debug traces with semantic values. - It uses named references instead of the traditional $1, $2, etc. It also uses Flex to generate the scanner. diff --git a/examples/c/bistromathic/README.md b/examples/c/bistromathic/README.md index 25411867..9f672d14 100644 --- a/examples/c/bistromathic/README.md +++ b/examples/c/bistromathic/README.md @@ -3,7 +3,7 @@ This example demonstrates the best practices when using Bison. - Its interface is pure. - It uses a custom syntax error with location tracking, lookahead correction and token internationalization. -- It enables debug trace support with formatting of semantic values. +- It supports debug traces with semantic values. - It uses named references instead of the traditional $1, $2, etc. It also uses Flex to generate the scanner. diff --git a/examples/c/bistromathic/parse.y b/examples/c/bistromathic/parse.y index 373bc074..9698161f 100644 --- a/examples/c/bistromathic/parse.y +++ b/examples/c/bistromathic/parse.y @@ -209,10 +209,10 @@ yyreport_syntax_error (const yyparse_context_t *ctx) } // Called by yyparse on error. -void yyerror (YYLTYPE *loc, char const *s) +void yyerror (YYLTYPE *loc, char const *msg) { YY_LOCATION_PRINT (stderr, *loc); - fprintf (stderr, ": %s\n", s); + fprintf (stderr, ": %s\n", msg); } int main (int argc, char const* argv[]) diff --git a/examples/c/lexcalc/README.md b/examples/c/lexcalc/README.md index ddf693c4..58d9d9aa 100644 --- a/examples/c/lexcalc/README.md +++ b/examples/c/lexcalc/README.md @@ -3,6 +3,8 @@ This directory contains lexcalc, the traditional example of using Flex and Bison to build a simple calculator. +It features detailed syntax errors with locations. + <!--- Local Variables: fill-column: 76 diff --git a/examples/c/lexcalc/lexcalc.test b/examples/c/lexcalc/lexcalc.test index cfc5d83f..c9eb62f1 100644 --- a/examples/c/lexcalc/lexcalc.test +++ b/examples/c/lexcalc/lexcalc.test @@ -29,4 +29,9 @@ run -noerr 0 9 -p cat >input <<EOF (1+2) * EOF -run 1 'err: syntax error, unexpected end-of-line, expecting ( or number' +run 1 'err: 1.8-2.0: syntax error, unexpected end-of-line, expecting ( or number' + +cat >input <<EOF +1 / (2 - 2) +EOF +run 1 'err: 1.1-11: error: division by zero" diff --git a/examples/c/lexcalc/parse.y b/examples/c/lexcalc/parse.y index 060af4ab..62201a16 100644 --- a/examples/c/lexcalc/parse.y +++ b/examples/c/lexcalc/parse.y @@ -6,10 +6,10 @@ { // Tell Flex the expected prototype of yylex. #define YY_DECL \ - enum yytokentype yylex (YYSTYPE* yylval, int *nerrs) + enum yytokentype yylex (YYSTYPE* yylval, YYLTYPE *yylloc, int *nerrs) YY_DECL; - void yyerror (int *nerrs, const char *msg); + void yyerror (YYLTYPE *loc, int *nerrs, const char *msg); } // Emitted on top of the implementation file. @@ -33,6 +33,9 @@ // Generate detailed error messages. %define parse.error detailed +// with locations. +%locations + // Enable debug traces (see yydebug in main). %define parse.trace @@ -78,7 +81,7 @@ exp: { if ($3 == 0) { - yyerror (nerrs, "invalid division by zero"); + yyerror (&@$, nerrs, "error: division by zero"); YYERROR; } else @@ -90,9 +93,10 @@ exp: %% // Epilogue (C code). -void yyerror (int *nerrs, const char *msg) +void yyerror (YYLTYPE *loc, int *nerrs, const char *msg) { - fprintf (stderr, "%s\n", msg); + YY_LOCATION_PRINT (stderr, *loc); + fprintf (stderr, ": %s\n", msg); ++*nerrs; } diff --git a/examples/c/lexcalc/scan.l b/examples/c/lexcalc/scan.l index e0b68504..8be67cae 100644 --- a/examples/c/lexcalc/scan.l +++ b/examples/c/lexcalc/scan.l @@ -9,9 +9,24 @@ #include <stdlib.h> /* strtol */ #include "parse.h" + + // Each time a rule is matched, advance the end cursor/position. +#define YY_USER_ACTION \ + yylloc->last_column += yyleng; + + // Move the first position onto the last. +#define LOCATION_STEP() \ + do { \ + yylloc->first_line = yylloc->last_line; \ + yylloc->first_column = yylloc->last_column; \ + } while (0) %} %% +%{ + // Each time yylex is called, move the head position to the end one. + LOCATION_STEP (); +%} /* Rules. */ "+" return TOK_PLUS; @@ -27,17 +42,17 @@ errno = 0; long n = strtol (yytext, NULL, 10); if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE)) - yyerror (nerrs, "integer is out of range"); + yyerror (yylloc, nerrs, "integer is out of range"); yylval->TOK_NUM = (int) n; return TOK_NUM; } - /* Ignore white spaces. */ -[ \t]+ continue; +"\n" yylloc->last_line++; yylloc->last_column = 1; return TOK_EOL; -"\n" return TOK_EOL; + /* Ignore white spaces. */ +[ \t]+ LOCATION_STEP (); continue; -. yyerror (nerrs, "syntax error, invalid character"); +. yyerror (yylloc, nerrs, "syntax error, invalid character"); continue; <<EOF>> return TOK_EOF; %% |