1: /* front-end compiler for vmgen example
2:
3: Copyright (C) 2001,2002,2003 Free Software Foundation, Inc.
4:
5: This file is part of Gforth.
6:
7: Gforth is free software; you can redistribute it and/or
8: modify it under the terms of the GNU General Public License
9: as published by the Free Software Foundation; either version 2
10: of the License, or (at your option) any later version.
11:
12: This program is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with this program; if not, write to the Free Software
19: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20: */
21:
22: /* I use yacc/bison here not because I think it's the best tool for
23: the job, but because it's widely available and popular; it's also
24: (barely) adequate for this job. */
25:
26: %{
27: #include <stdlib.h>
28: #include <stdio.h>
29: #include <string.h>
30: #include "mini.h"
31:
32: /* BB_BOUNDARY is needed on basic blocks without a preceding VM branch */
33: #define BB_BOUNDARY (last_compiled = NULL, /* suppress peephole opt */ \
34: block_insert(vmcodep)) /* for accurate profiling */
35:
36: Label *vm_prim;
37: Inst *vmcodep;
38: FILE *vm_out;
39: int vm_debug;
40:
41: void yyerror(char *s)
42: {
43: #if 1
44: /* for pure flex call */
45: fprintf(stderr, "%s: %s\n", program_name, s);
46: #else
47: /* lex or flex -l supports yylineno */
48: fprintf (stderr, "%s: %d: %s\n", program_name, yylineno, s);
49: #endif
50: }
51:
52: #include "mini-gen.i"
53:
54: void gen_main_end(void)
55: {
56: gen_call(&vmcodep, func_addr("main"), func_calladjust("main"));
57: gen_end(&vmcodep);
58: BB_BOUNDARY; /* for profiling; see comment in mini.vmg:end */
59: }
60:
61: int locals=0;
62: int nonparams=0;
63:
64: int yylex();
65: %}
66:
67:
68: %token FUNC RETURN END VAR IF THEN ELSE WHILE DO BECOMES PRINT NUM IDENT
69:
70: %union {
71: long num;
72: char *string;
73: Inst *instp;
74: }
75:
76: %type <string> IDENT;
77: %type <num> NUM;
78: %type <instp> elsepart;
79:
80:
81: %%
82: program: program function
83: | ;
84:
85: function: FUNC IDENT { locals=0; nonparams=0; } '(' params ')'
86: vars { insert_func($2,vmcodep,locals,nonparams); }
87: stats RETURN expr ';'
88: END FUNC ';' { gen_return(&vmcodep, -adjust(locals)); }
89: ;
90:
91: params: IDENT ',' { insert_local($1); } params
92: | IDENT { insert_local($1); }
93: | ;
94:
95: vars: vars VAR IDENT ';' { insert_local($3); nonparams++; }
96: | ;
97:
98: stats: stats stat ';'
99: | ;
100:
101: stat: IF expr THEN { gen_zbranch(&vmcodep, 0); $<instp>$ = vmcodep; }
102: stats { $<instp>$ = $<instp>4; }
103: elsepart END IF { BB_BOUNDARY; vm_target2Cell(vmcodep, $<instp>7[-1]); }
104: | WHILE { BB_BOUNDARY; $<instp>$ = vmcodep; }
105: expr DO { gen_zbranch(&vmcodep, 0); $<instp>$ = vmcodep; }
106: stats END WHILE { gen_branch(&vmcodep, $<instp>2); vm_target2Cell(vmcodep, $<instp>5[-1]); }
107: | IDENT BECOMES expr { gen_storelocal(&vmcodep, var_offset($1)); }
108: | PRINT expr { gen_print(&vmcodep); }
109: | expr { gen_drop(&vmcodep); }
110: ;
111:
112: elsepart: ELSE { gen_branch(&vmcodep, 0); $<instp>$ = vmcodep; vm_target2Cell(vmcodep, $<instp>0[-1]); }
113: stats { $$ = $<instp>2; }
114: | { $$ = $<instp>0; }
115: ;
116:
117: expr: term '+' term { gen_add(&vmcodep); }
118: | term '-' term { gen_sub(&vmcodep); }
119: | term '*' term { gen_mul(&vmcodep); }
120: | term '&' term { gen_and(&vmcodep); }
121: | term '|' term { gen_or(&vmcodep); }
122: | term '<' term { gen_lessthan(&vmcodep); }
123: | term '=' term { gen_equals(&vmcodep); }
124: | '!' term { gen_not(&vmcodep); }
125: | '-' term { gen_negate(&vmcodep); }
126: | term
127: ;
128:
129: term: '(' expr ')'
130: | IDENT '(' args ')' { gen_call(&vmcodep, func_addr($1), func_calladjust($1)); }
131: | IDENT { gen_loadlocal(&vmcodep, var_offset($1)); }
132: | NUM { gen_lit(&vmcodep, $1); }
133: ;
134:
135: /* missing: argument counting and checking against called function */
136: args: expr ',' args
137: | expr
138: | ;
139: %%
140: int yywrap(void)
141: {
142: return 1;
143: }
144:
145: #include "lex.yy.c"
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>