1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/*======================================================================
* Bison Options
*/
%pure_parser
%{
/*======================================================================
* Bison C Header
*/
#include <stdio.h>
#include <stdarg.h>
#include "calctest.tab.h"
#include "calctest.lex.h"
typedef struct _yyparse_param {
char *name;
char *filename;
yyscan_t scanner;
float val;
} yyparseParam;
#define YYLEX_PARAM ((yyparseParam*)pparam)->scanner
#define YYPARSE_PARAM pparam
extern void calctest_yyerror(const char *msg);
extern void calctest_yycarp(yyparseParam *pparams, const char *fmt, ...);
%}
/*======================================================================
* Bison Definitions
*/
%union {
double dbl;
}
%token <dbl> NUMBER PLUS MINUS TIMES DIV LPAREN RPAREN NEWLINE OTHER
%type <dbl> expr exprs
%left PLUS MINUS
%left TIMES DIV
%nonassoc UMINUS
/*======================================================================
* Bison Rules
*/
%%
exprs: /* empty */
{ $$=0; }
| exprs expr NEWLINE
{ printf("%g\n", $2); ((yyparseParam*)pparam)->val=$$=$2; }
;
expr: LPAREN expr RPAREN { $$=$2; }
| MINUS expr { $$=-$2; }
| expr TIMES expr { $$=$1*$3; }
| expr DIV expr { $$=$1/$3; }
| expr PLUS expr { $$=$1+$3; }
| expr MINUS expr %prec UMINUS { $$=$1-$3; }
| NUMBER { $$=$1; }
| OTHER
{
calctest_yycarp((yyparseParam*)pparam, "Failed to parse expression");
YYABORT;
}
;
%%
/*======================================================================
* User C Code
*/
void calctest_yyerror(const char *msg)
{
fprintf(stderr, "yyerror: %s\n", msg);
}
void calctest_yycarp(yyparseParam *pparams, const char *fmt, ...)
{
va_list ap;
fprintf(stderr, "%s: ", (pparams->name ? pparams->name : "calctest_parser"));
va_start(ap,fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, " in %s%s%s at line %u, column %u.\n",
(pparams->filename ? "file \"" : ""),
(pparams->filename ? pparams->filename : "input"),
(pparams->filename ? "\"" : ""),
calctest_yyget_lineno(pparams->scanner),
calctest_yyget_column(pparams->scanner));
}
int main (void) {
yyscan_t scanner;
yyparseParam pparams;
calctest_yylex_init(&scanner); //-- initialize reentrant flex scanner
pparams.name = NULL;
pparams.filename = NULL;
//--
//pparams.name = "myParser";
//pparams.filename = "(stdin)";
pparams.scanner = scanner;
calctest_yyparse(&pparams);
calctest_yylex_destroy(pparams.scanner); //-- cleanup reentrant flex scanner
printf("Final calctest value=%g\n", pparams.val);
return 0;
}
|