bison-patches
[Top][All Lists]
Advanced

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

[PATCH 3/6] examples: bistromathic: don't use Flex


From: Akim Demaille
Subject: [PATCH 3/6] examples: bistromathic: don't use Flex
Date: Sun, 1 Mar 2020 12:31:01 +0100

This example will soon use GNU readline, so its scanner should be easy
to use (concurrently) on strings, not streams.  This is not a place
where Flex shines, and anyway, these are examples of Bison, not Flex.
There's already lexcalc and reccalc that demonstrate the use of Flex.

* examples/c/bistromathic/scan.l: Remove.
* examples/c/bistromathic/parse.y (yylex): New.
Adjust dependencies.
---
 examples/c/README.md              |  7 ++-
 examples/c/bistromathic/README.md |  7 ++-
 examples/c/bistromathic/local.mk  | 22 ++++----
 examples/c/bistromathic/parse.y   | 88 +++++++++++++++++++++++++++++--
 examples/c/bistromathic/scan.l    | 67 -----------------------
 5 files changed, 100 insertions(+), 91 deletions(-)
 delete mode 100644 examples/c/bistromathic/scan.l

diff --git a/examples/c/README.md b/examples/c/README.md
index 1a98d462..95e2bb2a 100644
--- a/examples/c/README.md
+++ b/examples/c/README.md
@@ -52,13 +52,12 @@ push-parser model.
 ## bistromathic - all the bells and whistles
 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.
+- Its hand-written scanner tracks locations.
+- It uses a custom syntax error with location, lookahead correction and
+  token internationalization.
 - 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.
-
 <!---
 
 Local Variables:
diff --git a/examples/c/bistromathic/README.md 
b/examples/c/bistromathic/README.md
index 9f672d14..8bef5136 100644
--- a/examples/c/bistromathic/README.md
+++ b/examples/c/bistromathic/README.md
@@ -1,13 +1,12 @@
 # bistromathic - all the bells and whistles
 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.
+- Its hand-written scanner tracks locations.
+- It uses a custom syntax error with location, lookahead correction and
+  token internationalization.
 - 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.
-
 <!---
 Local Variables:
 fill-column: 76
diff --git a/examples/c/bistromathic/local.mk b/examples/c/bistromathic/local.mk
index 78f2c937..0a805f9d 100644
--- a/examples/c/bistromathic/local.mk
+++ b/examples/c/bistromathic/local.mk
@@ -19,18 +19,16 @@ bistromathicdir = $(docdir)/%D%
 ## Bistromathics.  ##
 ## --------------- ##
 
-if FLEX_WORKS
-  check_PROGRAMS += %D%/bistromathic
-  TESTS += %D%/bistromathic.test
-  EXTRA_DIST += %D%/bistromathic.test
-  nodist_%C%_bistromathic_SOURCES = %D%/parse.y %D%/parse.h %D%/scan.l
-  %D%/calc.c: $(dependencies)
+check_PROGRAMS += %D%/bistromathic
+TESTS += %D%/bistromathic.test
+EXTRA_DIST += %D%/bistromathic.test
+nodist_%C%_bistromathic_SOURCES = %D%/parse.y %D%/parse.h
+%D%/calc.c: $(dependencies)
 
-  # Don't use gnulib's system headers.
-  %C%_bistromathic_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
-  %C%_bistromathic_LDADD = -lm
-endif FLEX_WORKS
+# Don't use gnulib's system headers.
+%C%_bistromathic_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
+%C%_bistromathic_LDADD = -lm
 
-dist_bistromathic_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md
-CLEANFILES += %D%/parse.[ch] %D%/scan.c %D%/parse.output
+dist_bistromathic_DATA = %D%/parse.y %D%/Makefile %D%/README.md
+CLEANFILES += %D%/parse.[ch] %D%/parse.output
 CLEANDIRS += %D%/*.dSYM
diff --git a/examples/c/bistromathic/parse.y b/examples/c/bistromathic/parse.y
index 709651c2..39244f95 100644
--- a/examples/c/bistromathic/parse.y
+++ b/examples/c/bistromathic/parse.y
@@ -31,10 +31,7 @@
 }
 
 %code provides {
-  #define YY_DECL \
-  int yylex (YYSTYPE *yylval, YYLTYPE *yylloc)
-  YY_DECL;
-
+  int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
   void yyerror (YYLTYPE *yylloc, char const *);
 }
 
@@ -137,6 +134,10 @@ exp:
 // End of grammar.
 %%
 
+/*------------.
+| Functions.  |
+`------------*/
+
 struct init
 {
   char const *name;
@@ -189,6 +190,80 @@ getsym (char const *name)
   return NULL;
 }
 
+
+/*----------.
+| Scanner.  |
+`----------*/
+
+int
+yylex (YYSTYPE *yylval, YYLTYPE *yylloc)
+{
+  int c;
+
+  // Ignore white space, get first nonwhite character.
+  do {
+    // Move the first position onto the last.
+    yylloc->first_line = yylloc->last_line;
+    yylloc->first_column = yylloc->last_column;
+
+    yylloc->last_column += 1;
+    c = getchar ();
+  } while (c == ' ' || c == '\t');
+
+  switch (c)
+    {
+    case '+': return TOK_PLUS;
+    case '-': return TOK_MINUS;
+    case '*': return TOK_STAR;
+    case '/': return TOK_SLASH;
+    case '^': return TOK_CARET;
+    case '=': return TOK_EQUAL;
+    case '(': return TOK_LPAREN;
+    case ')': return TOK_RPAREN;
+
+    case '\n':
+      yylloc->last_column = 1;
+      yylloc->last_line += 1;
+      return TOK_EOL;
+
+    case EOF: return TOK_EOF;
+
+      // Any other character is a token by itself.
+    default:
+      if (c == '.' || isdigit (c))
+        {
+          ungetc (c, stdin);
+          int nchars = 0;
+          scanf ("%lf%n", &yylval->TOK_NUM, &nchars);
+          yylloc->last_column += nchars - 1;
+          return TOK_NUM;
+        }
+      else if (islower (c))
+        {
+          ungetc (c, stdin);
+          int nchars = 0;
+          char buf[100];
+          scanf ("%99[a-z]%n", buf, &nchars);
+          symrec *s = getsym (buf);
+          if (!s)
+            s = putsym (buf, TOK_VAR);
+          yylval->TOK_VAR = s;
+          yylloc->last_column += nchars - 1;
+          return s->type;
+        }
+      else
+        {
+          yyerror (yylloc, "error: invalid character");
+          return yylex (yylval, yylloc);
+        }
+    }
+}
+
+
+/*---------.
+| Parser.  |
+`---------*/
+
 int
 yyreport_syntax_error (const yyparse_context_t *ctx)
 {
@@ -215,6 +290,11 @@ void yyerror (YYLTYPE *loc, char const *msg)
   fprintf (stderr, ": %s\n", msg);
 }
 
+
+/*-------.
+| Main.  |
+`-------*/
+
 int main (int argc, char const* argv[])
 {
   // Enable parse traces on option -p.
diff --git a/examples/c/bistromathic/scan.l b/examples/c/bistromathic/scan.l
deleted file mode 100644
index a0f60be5..00000000
--- a/examples/c/bistromathic/scan.l
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Prologue (directives).   -*- C -*- */
-
-/* Disable Flex features we don't need, to avoid warnings. */
-%option nodefault noinput nounput noyywrap
-
-%{
-#include <errno.h> /* errno, ERANGE */
-#include <limits.h> /* INT_MIN */
-#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;
-"-"      return TOK_MINUS;
-"*"      return TOK_STAR;
-"/"      return TOK_SLASH;
-"^"      return TOK_CARET;
-
-"("      return TOK_LPAREN;
-")"      return TOK_RPAREN;
-
-"="      return TOK_EQUAL;
-
- /* Scan an identifier.  */
-[a-z]+   {
-  symrec *s = getsym (yytext);
-  if (!s)
-    s = putsym (yytext, TOK_VAR);
-  yylval->TOK_VAR = s;
-  return s->type;
-}
-
- /* Scan a double precision number.  */
-[0-9]+(\.[0-9]*)?|(\.[0-9]+)   {
-  sscanf (yytext, "%lf", &yylval->TOK_NUM);
-  return TOK_NUM;
-}
-
-"\n"     yylloc->last_line++; yylloc->last_column = 1; return TOK_EOL;
-
- /* Ignore white spaces. */
-[ \t]+   LOCATION_STEP (); continue;
-
-<<EOF>>  return TOK_EOF;
-
-.        yyerror (yylloc, "error: invalid character");
-%%
-/* Epilogue (C code). */
-- 
2.25.1




reply via email to

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