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.
This commit is contained in:
Akim Demaille
2018-12-09 14:19:00 +01:00
parent 4cbdcaa572
commit d657da9fb4
10 changed files with 270 additions and 6 deletions

View File

@@ -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;
}