bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/6] examples: lexcalc: demonstrate location tracking


From: Akim Demaille
Subject: [PATCH 1/6] examples: lexcalc: demonstrate location tracking
Date: Sun, 1 Mar 2020 12:30:59 +0100

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.
---
 NEWS                              |  3 +++
 examples/c/README.md              |  5 +++--
 examples/c/bistromathic/README.md |  2 +-
 examples/c/bistromathic/parse.y   |  4 ++--
 examples/c/lexcalc/README.md      |  2 ++
 examples/c/lexcalc/lexcalc.test   |  7 ++++++-
 examples/c/lexcalc/parse.y        | 14 +++++++++-----
 examples/c/lexcalc/scan.l         | 25 ++++++++++++++++++++-----
 8 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/NEWS b/NEWS
index 0daa3048..b94ccaf0 100644
--- a/NEWS
+++ b/NEWS
@@ -101,6 +101,9 @@ GNU Bison NEWS
   There are now two examples in examples/java: a very simple calculator, and
   one that tracks locations to provide acurate error messages.
 
+  The lexcalc example (a simple example in C based on Flex and Bison) now
+  also demonstrates location tracking.
+
   A new C example, bistromathic, is a fully featured calculator using many
   Bison features: pure interface, location tracking, internationalized
   custom error messages, lookahead-correction, rich debug traces, etc.
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;
 %%
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]