bug-bison
[Top][All Lists]
Advanced

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

Re: I need simpler examples (was: RE: Enhancement request: enabling Vari


From: Akim Demaille
Subject: Re: I need simpler examples (was: RE: Enhancement request: enabling Variant in C parsers)
Date: Sun, 9 Dec 2018 15:17:22 +0100


> Le 9 déc. 2018 à 06:53, Akim Demaille <address@hidden> a écrit :
> 
>> I still think that the manual should give at least one C+Flex+Bison example 
>> without locations and at least one "C++"+Flex+Bison example without 
>> locations.
> 
> I will not agree for two, but if you keep on insisting, then I guess the 
> example in C will be without locations, ok.
> 
>> Just because the user should have something simple to begin with.
> 
> That's not so obvious.
> 
> Bison+Flex require way too much boilerplate, granted.  But in my experience, 
> it's easier in the long run to start from a fully featured full example 
> rather than starting with something smaller, and have to retrofit things like 
> locations.
> 
> So I still believe the documentation, with rpcalc and mfcalc are the simple 
> examples you are asking for, and then the flex example (in examples/c, not in 
> the documentation) should be good starting points, with locations.

This should match your expectations.  Locations are not tracked,
which is quite painful to do, so I'm still not convinced we are
helping users by not showing how it works.

But at least that's a starting point, something we can discuss upon.

commit fa96bb7f3b338f2f58fd3cc270a94edb74834b20
Author: Akim Demaille <address@hidden>
Date:   Sun Dec 9 14:19:00 2018 +0100

    examples: add a simple Flex+Bison example in C
    
    Suggested by Askar Safin.
    http://lists.gnu.org/archive/html/bug-bison/2018-12/msg00003.html
    
    * examples/c/lexcalc/Makefile, examples/c/lexcalc/README.md,
    * examples/c/lexcalc/lexcalc.test, examples/c/lexcalc/local.mk,
    * examples/c/lexcalc/parse.y, examples/c/lexcalc/scan.l:
    New.

diff --git a/NEWS b/NEWS
index 9c49fe84..3b714d6a 100644
--- a/NEWS
+++ b/NEWS
@@ -142,7 +142,8 @@ GNU Bison NEWS
   README and a Makefile.  Not only can they be used to toy with Bison, they
   can also be starting points for your own grammars.
 
-  There is now a Java example.
+  There is now a Java example, and a simple example in C based on Flex and
+  Bison (examples/c/lexcalc/).
 
 ** Changes
 
diff --git a/examples/c++/calc++/README.md b/examples/c++/calc++/README.md
index d4d5154f..02e0d681 100644
--- a/examples/c++/calc++/README.md
+++ b/examples/c++/calc++/README.md
@@ -1,6 +1,10 @@
-This directory contains calc++, a simple Bison grammar file in C++.
+# calc++ - A Flex+Bison calculator
 
-Please, read the corresponding chapter in the documentation: "A Complete C++
+This directory contains calc++, a Bison grammar file in C++.  If you never
+saw the traditional implementation in C, please first read
+examples/c/lexcalc, which can be seen as a C precursor of this example.
+
+Read the corresponding chapter in the documentation: "A Complete C++
 Example".  It is also available on line (maybe with a different version of
 Bison):
 
https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html
@@ -27,7 +31,6 @@ You may pass `-p` to activate the parser debug traces, and 
`-s` to activate
 the scanner's.
 
 <!---
-
 Local Variables:
 fill-column: 76
 ispell-dictionary: "american"
@@ -50,5 +53,5 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# LocalWords:  mfcalc calc parsers yy MERCHANTABILITY Ctrl ispell american
+# LocalWords:  calc parsers yy MERCHANTABILITY Ctrl ispell american
 --->
diff --git a/examples/c/lexcalc/Makefile b/examples/c/lexcalc/Makefile
new file mode 100644
index 00000000..e7c798cd
--- /dev/null
+++ b/examples/c/lexcalc/Makefile
@@ -0,0 +1,34 @@
+# This Makefile is designed to be simple and readable.  It does not
+# aim at portability.  It requires GNU Make.
+
+BASE = lexcalc
+BISON = bison
+FLEX = flex
+XSLTPROC = xsltproc
+
+all: $(BASE)
+
+%.c %.h %.xml %.gv: %.y
+       $(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $<
+
+%.c: %.l
+       $(FLEX) $(FLEXFLAGS) -o$@ $<
+
+scan.o: parse.h
+lexcalc: parse.o scan.o
+       $(CC) $(CFLAGS) -o $@ $^
+
+run: $(BASE)
+       @echo "Type arithmetic expressions.  Quit with ctrl-d."
+       ./$<
+
+html: parse.html
+%.html: %.xml
+       $(XSLTPROC) $(XSLTPROCFLAGS) -o $@ $$($(BISON) 
--print-datadir)/xslt/xml2xhtml.xsl $<
+
+CLEANFILES =                                           \
+  $(BASE) *.o                                          \
+  parse.[ch] parse.output parse.xml parse.html parse.gv        \
+  scan.c
+clean:
+       rm -f $(CLEANFILES)
diff --git a/examples/c/lexcalc/README.md b/examples/c/lexcalc/README.md
new file mode 100644
index 00000000..32e6d534
--- /dev/null
+++ b/examples/c/lexcalc/README.md
@@ -0,0 +1,28 @@
+# lexcalc - calculator with Flex and Bison
+
+This directory contains lexcalc, the traditional example of using Flex and
+Bison to build a simple calculator.
+
+<!---
+Local Variables:
+fill-column: 76
+ispell-dictionary: "american"
+End:
+
+Copyright (C) 2018 Free Software Foundation, Inc.
+
+This file is part of Bison, the GNU Compiler Compiler.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--->
diff --git a/examples/c/lexcalc/lexcalc.test b/examples/c/lexcalc/lexcalc.test
new file mode 100644
index 00000000..0df4e38c
--- /dev/null
+++ b/examples/c/lexcalc/lexcalc.test
@@ -0,0 +1,27 @@
+#! /bin/sh
+
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+cat >input <<EOF
+1+2*3
+EOF
+run 0 7
+
+cat >input <<EOF
+(1+2) * 3
+EOF
+run 0 9
+run -noerr 0 9 -p
diff --git a/examples/c/lexcalc/local.mk b/examples/c/lexcalc/local.mk
new file mode 100644
index 00000000..55fb995f
--- /dev/null
+++ b/examples/c/lexcalc/local.mk
@@ -0,0 +1,31 @@
+## Copyright (C) 2018 Free Software Foundation, Inc.
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+lexcalcdir = $(docdir)/%D%
+
+## ------ ##
+## Calc.  ##
+## ------ ##
+
+check_PROGRAMS += %D%/lexcalc
+TESTS += %D%/lexcalc.test
+EXTRA_DIST += %D%/lexcalc.test
+%C%_lexcalc_SOURCES = %D%/parse.y %D%/parse.h %D%/scan.l
+
+# Don't use gnulib's system headers.
+%C%_lexcalc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
+
+dist_lexcalc_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md
+CLEANFILES += %D%/lexcalc %D%/*.o %D%/parse.c %D%/scan.c
diff --git a/examples/c/lexcalc/parse.y b/examples/c/lexcalc/parse.y
new file mode 100644
index 00000000..5306de30
--- /dev/null
+++ b/examples/c/lexcalc/parse.y
@@ -0,0 +1,95 @@
+// Prologue (directives).
+%expect 0
+
+// Emitted in the header file, after the definition of YYSTYPE.
+%code provides
+{
+  // Tell Flex the expected prototype of yylex.
+#define YY_DECL                                 \
+  enum yytokentype yylex (YYSTYPE* yylval, int *nerrs)
+  YY_DECL;
+
+  void yyerror (int *nerrs, const char *msg);
+}
+
+// Emitted on top of the implementation file.
+%code top
+{
+#include <stdio.h>  /* printf. */
+#include <stdlib.h> /* getenv. */
+}
+
+%define api.pure full
+%define api.token.prefix {TOK_}
+%define api.value.type union
+%define parse.error verbose
+%define parse.trace
+ // Error count, exchanged between main, yyparse and yylex.
+%param {int *nerrs}
+
+%token
+  PLUS   "+"
+  MINUS  "-"
+  STAR   "*"
+  SLASH  "/"
+  LPAREN "("
+  RPAREN ")"
+  EOL    "end-of-line"
+  EOF 0  "end-of-file"
+;
+
+%token <int> NUM "number"
+%type <int> exp line
+%printer { fprintf (yyo, "%d", $$); } <int>
+
+// Precedence (from lowest to highest) and associativity.
+%left "+" "-"
+%left "*" "/"
+
+%%
+// Rules.
+input:
+  %empty
+| input line  { printf ("%d\n", $line); }
+;
+
+line:
+  exp EOL   { $$ = $1; }
+| error EOL { yyerrok; }
+;
+
+exp:
+  exp "+" exp   { $$ = $1 + $3;  }
+| exp "-" exp   { $$ = $1 - $3;  }
+| exp "*" exp   { $$ = $1 * $3;  }
+| exp "/" exp
+  {
+    if ($3 == 0)
+      {
+        yyerror (nerrs, "invalid division by zero");
+        YYERROR;
+      }
+    else
+      $$ = $1 / $3;
+  }
+| "(" exp ")"   { $$ = $2;       }
+| NUM           { $$ = $1; }
+;
+%%
+// Epilogue (C code).
+void yyerror(int *nerrs, const char *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+  ++nerrs;
+}
+
+int main (void)
+{
+  int nerrs = 0;
+  // Enable parser runtime debugging.
+  if (!!getenv ("YYDEBUG"))
+    yydebug = 1;
+  yyparse (&nerrs);
+  // Exit on failure if there were errors.
+  return !!nerrs;
+}
diff --git a/examples/c/lexcalc/scan.l b/examples/c/lexcalc/scan.l
new file mode 100644
index 00000000..fc73f3b0
--- /dev/null
+++ b/examples/c/lexcalc/scan.l
@@ -0,0 +1,43 @@
+/* Prologue (directives).   -*- C++ -*- */
+
+/* Disable Flex features we don't need, to avoid warnings. */
+%option nodefault noinput nounput noyywrap
+
+%{
+#include <limits.h> /* INT_MIN */
+#include <stdlib.h> /* strtol */
+
+#include "parse.h"
+%}
+
+%%
+ /* Rules.  */
+
+"+"      return TOK_PLUS;
+"-"      return TOK_MINUS;
+"*"      return TOK_STAR;
+"/"      return TOK_SLASH;
+
+"("      return TOK_LPAREN;
+")"      return TOK_RPAREN;
+
+ /* Scan an integer.  */
+[0-9]+   {
+  errno = 0;
+  long n = strtol (yytext, NULL, 10);
+  if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
+    yyerror (nerrs, "integer is out of range");
+  yylval->TOK_NUM = (int) n;
+  return TOK_NUM;
+}
+
+ /* Ignore white spaces. */
+[ \t]+   continue;
+
+"\n"     return TOK_EOL;
+
+.        yyerror (nerrs, "syntax error, invalid character");
+
+<<EOF>>  return TOK_EOF;
+%%
+/* Epilogue (C code). */
diff --git a/examples/c/local.mk b/examples/c/local.mk
index dcd90424..fb1c33d1 100644
--- a/examples/c/local.mk
+++ b/examples/c/local.mk
@@ -16,5 +16,6 @@
 cdir = $(docdir)/%D%
 dist_c_DATA = %D%/README.md
 
+include %D%/lexcalc/local.mk
 include %D%/mfcalc/local.mk
 include %D%/rpcalc/local.mk
diff --git a/examples/c/rpcalc/Makefile b/examples/c/rpcalc/Makefile
index 87e18f34..624f247b 100644
--- a/examples/c/rpcalc/Makefile
+++ b/examples/c/rpcalc/Makefile
@@ -14,7 +14,7 @@ all: $(BASE)
        $(CC) $(CFLAGS) -o $@ $<
 
 run: $(BASE)
-       @echo "Type arithmetic expressions in reverse polish notation.  Quit 
with ctrl-d."
+       @echo "Type arithmetic expressions in Reverse Polish Notation.  Quit 
with ctrl-d."
        ./$<
 
 html: $(BASE).html




reply via email to

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