mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
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:
95
examples/c/lexcalc/parse.y
Normal file
95
examples/c/lexcalc/parse.y
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user