mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
examples: add a simple infix calculator in C
Currently we have no simple example: rpcalc in reverse Polish, mfcalc has functions, and lexcalc is using lex. * examples/c/calc/Makefile, examples/c/calc/calc.y, * examples/c/calc/calc.test, examples/c/calc/local.mk: New.
This commit is contained in:
5
NEWS
5
NEWS
@@ -9,6 +9,11 @@ GNU Bison NEWS
|
||||
When given -fsyntax-only, the diagnostics are reported, but no output is
|
||||
generated.
|
||||
|
||||
** Documentation
|
||||
|
||||
A new example in C shows an simple infix calculator with a hand-written
|
||||
scanner (examples/c/calc).
|
||||
|
||||
* Noteworthy changes in release 3.3.2 (2019-02-03) [stable]
|
||||
|
||||
** Bug fixes
|
||||
|
||||
8
TODO
8
TODO
@@ -1,4 +1,12 @@
|
||||
* Bison 3.4
|
||||
** doc
|
||||
I feel its ugly to use the GNU style to declare functions in the doc. It
|
||||
generates tons of white space in the page, and may contribute to bad page
|
||||
breaks.
|
||||
|
||||
Also, we seem to teach YYPRINT very early on, although it should be
|
||||
considered deprecated: %printer is superior.
|
||||
|
||||
** injection rules
|
||||
** glr.cc
|
||||
move glr.c into the yy namespace
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
This directory contains examples of Bison grammar files.
|
||||
# Examples in C
|
||||
|
||||
This directory contains simple examples of Bison grammar files in C.
|
||||
|
||||
Most of them come from the documentation, which should be installed together
|
||||
with Bison. The URLs are provided for convenience.
|
||||
|
||||
# rpcalc - Reverse Polish Notation Calculator
|
||||
## rpcalc - Reverse Polish Notation Calculator
|
||||
The first example is that of a simple double-precision Reverse Polish
|
||||
Notation calculator (a calculator using postfix operators). This example
|
||||
provides a good starting point, since operator precedence is not an issue.
|
||||
@@ -11,12 +13,23 @@ provides a good starting point, since operator precedence is not an issue.
|
||||
Extracted from the documentation: "Reverse Polish Notation Calculator"
|
||||
https://www.gnu.org/software/bison/manual/html_node/RPN-Calc.html
|
||||
|
||||
# mfcalc - Multi-Function Calculator
|
||||
A more complete C example: a multi-function calculator.
|
||||
## calc - Simple Calculator
|
||||
This example is slightly more complex than rpcalc: it features infix
|
||||
operators (`1 + 2`, instead of `1 2 +` in rpcalc), but it does so using a
|
||||
unambiguous grammar of the arithmetics instead of using precedence
|
||||
directives (%left, etc.).
|
||||
|
||||
## mfcalc - Multi-Function Calculator
|
||||
A more complete C example: a multi-function calculator. More complex than
|
||||
the previous example. Using precedence directives to support infix
|
||||
operators.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
<!---
|
||||
|
||||
|
||||
28
examples/c/calc/Makefile
Normal file
28
examples/c/calc/Makefile
Normal file
@@ -0,0 +1,28 @@
|
||||
# This Makefile is designed to be simple and readable. It does not
|
||||
# aim at portability. It requires GNU Make.
|
||||
|
||||
BASE = calc
|
||||
BISON = bison
|
||||
XSLTPROC = xsltproc
|
||||
|
||||
all: $(BASE)
|
||||
|
||||
%.c %.h %.xml %.gv: %.y
|
||||
$(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $<
|
||||
|
||||
$(BASE): $(BASE).o
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
run: $(BASE)
|
||||
@echo "Type arithmetic expressions. Quit with ctrl-d."
|
||||
./$<
|
||||
|
||||
html: $(BASE).html
|
||||
%.html: %.xml
|
||||
$(XSLTPROC) $(XSLTPROCFLAGS) -o $@ $$($(BISON) --print-datadir)/xslt/xml2xhtml.xsl $<
|
||||
|
||||
CLEANFILES = \
|
||||
$(BASE) *.o $(BASE).[ch] $(BASE).output $(BASE).xml $(BASE).html $(BASE).gv
|
||||
|
||||
clean:
|
||||
rm -f $(CLEANFILES)
|
||||
28
examples/c/calc/README.md
Normal file
28
examples/c/calc/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# calc - calculator with Bison
|
||||
|
||||
This directory contains calc, the traditional example of using Bison to
|
||||
build a simple calculator.
|
||||
|
||||
<!---
|
||||
Local Variables:
|
||||
fill-column: 76
|
||||
ispell-dictionary: "american"
|
||||
End:
|
||||
|
||||
Copyright (C) 2019 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/>.
|
||||
--->
|
||||
37
examples/c/calc/calc.test
Normal file
37
examples/c/calc/calc.test
Normal file
@@ -0,0 +1,37 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2019 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 -4
|
||||
|
||||
cat >input <<EOF
|
||||
8 / 2 / 2
|
||||
EOF
|
||||
run 0 2
|
||||
|
||||
cat >input <<EOF
|
||||
(1+2) * 3
|
||||
EOF
|
||||
run 0 9
|
||||
run -noerr 0 9 -p
|
||||
93
examples/c/calc/calc.y
Normal file
93
examples/c/calc/calc.y
Normal file
@@ -0,0 +1,93 @@
|
||||
%code top {
|
||||
#include <ctype.h> /* isdigit. */
|
||||
#include <stdio.h> /* For printf, etc. */
|
||||
#include <string.h> /* strcmp. */
|
||||
|
||||
int yylex (void);
|
||||
void yyerror (char const *);
|
||||
}
|
||||
|
||||
%define api.value.type union /* Generate YYSTYPE from these types: */
|
||||
%token <double> NUM "number"
|
||||
%type <double> expr term fact
|
||||
|
||||
/* Generate the parser description file. */
|
||||
%verbose
|
||||
/* Enable run-time traces (yydebug). */
|
||||
%define parse.trace
|
||||
|
||||
/* Formatting semantic values. */
|
||||
%printer { fprintf (yyo, "%g", $$); } <double>;
|
||||
|
||||
%% /* The grammar follows. */
|
||||
input:
|
||||
%empty
|
||||
| input line
|
||||
;
|
||||
|
||||
line:
|
||||
'\n'
|
||||
| expr '\n' { printf ("%.10g\n", $1); }
|
||||
| error '\n' { yyerrok; }
|
||||
;
|
||||
|
||||
expr:
|
||||
expr '+' term { $$ = $1 + $3; }
|
||||
| expr '-' term { $$ = $1 - $3; }
|
||||
| term
|
||||
;
|
||||
|
||||
term:
|
||||
term '*' fact { $$ = $1 * $3; }
|
||||
| term '/' fact { $$ = $1 / $3; }
|
||||
| fact
|
||||
;
|
||||
|
||||
fact:
|
||||
"number"
|
||||
| '(' expr ')' { $$ = $2; }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
int
|
||||
yylex (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Ignore white space, get first nonwhite character. */
|
||||
while ((c = getchar ()) == ' ' || c == '\t')
|
||||
continue;
|
||||
|
||||
if (c == EOF)
|
||||
return 0;
|
||||
|
||||
/* Char starts a number => parse the number. */
|
||||
if (c == '.' || isdigit (c))
|
||||
{
|
||||
ungetc (c, stdin);
|
||||
scanf ("%lf", &yylval.NUM);
|
||||
return NUM;
|
||||
}
|
||||
|
||||
/* Any other character is a token by itself. */
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Called by yyparse on error. */
|
||||
void
|
||||
yyerror (char const *s)
|
||||
{
|
||||
fprintf (stderr, "%s\n", s);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char const* argv[])
|
||||
{
|
||||
int i;
|
||||
/* Enable parse traces on option -p. */
|
||||
for (i = 1; i < argc; ++i)
|
||||
if (!strcmp(argv[i], "-p"))
|
||||
yydebug = 1;
|
||||
return yyparse ();
|
||||
}
|
||||
32
examples/c/calc/local.mk
Normal file
32
examples/c/calc/local.mk
Normal file
@@ -0,0 +1,32 @@
|
||||
## Copyright (C) 2019 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/>.
|
||||
|
||||
calcdir = $(docdir)/%D%
|
||||
|
||||
## ------ ##
|
||||
## Calc. ##
|
||||
## ------ ##
|
||||
|
||||
check_PROGRAMS += %D%/calc
|
||||
TESTS += %D%/calc.test
|
||||
EXTRA_DIST += %D%/calc.test
|
||||
%C%_calc_SOURCES = %D%/calc.y
|
||||
|
||||
# Don't use gnulib's system headers.
|
||||
%C%_calc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
|
||||
|
||||
dist_calc_DATA = %D%/calc.y %D%/Makefile %D%/README.md
|
||||
CLEANFILES += %D%/calc %D%/*.o %D%/parse.c %D%/scan.c
|
||||
CLEANDIRS += %D%/*.dSYM
|
||||
@@ -15,7 +15,7 @@ all: $(BASE)
|
||||
$(FLEX) $(FLEXFLAGS) -o$@ $<
|
||||
|
||||
scan.o: parse.h
|
||||
lexcalc: parse.o scan.o
|
||||
$(BASE): parse.o scan.o
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
run: $(BASE)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
cdir = $(docdir)/%D%
|
||||
dist_c_DATA = %D%/README.md
|
||||
|
||||
include %D%/calc/local.mk
|
||||
include %D%/lexcalc/local.mk
|
||||
include %D%/mfcalc/local.mk
|
||||
include %D%/rpcalc/local.mk
|
||||
|
||||
Reference in New Issue
Block a user