Annotation of gforth/vmgen-ex/mini.y, revision 1.7
1.1 anton 1: /* front-end compiler for vmgen example
2:
1.7 ! anton 3: Copyright (C) 2001,2002,2003,2007 Free Software Foundation, Inc.
1.1 anton 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
1.6 anton 9: as published by the Free Software Foundation, either version 3
1.1 anton 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
1.6 anton 18: along with this program; if not, see http://www.gnu.org/licenses/.
1.1 anton 19: */
20:
21: /* I use yacc/bison here not because I think it's the best tool for
22: the job, but because it's widely available and popular; it's also
23: (barely) adequate for this job. */
24:
25: %{
26: #include <stdlib.h>
27: #include <stdio.h>
28: #include <string.h>
29: #include "mini.h"
30:
31: /* BB_BOUNDARY is needed on basic blocks without a preceding VM branch */
32: #define BB_BOUNDARY (last_compiled = NULL, /* suppress peephole opt */ \
33: block_insert(vmcodep)) /* for accurate profiling */
34:
35: Inst *vm_prim;
36: Inst *vmcodep;
37: FILE *vm_out;
38: int vm_debug;
39:
40: void yyerror(char *s)
41: {
1.5 anton 42: #if 1
43: /* for pure flex call */
44: fprintf(stderr, "%s: %s\n", program_name, s);
45: #else
46: /* lex or flex -l supports yylineno */
47: fprintf (stderr, "%s: %d: %s\n", program_name, yylineno, s);
48: #endif
1.1 anton 49: }
50:
51: #include "mini-gen.i"
52:
53: void gen_main_end(void)
54: {
55: gen_call(&vmcodep, func_addr("main"), func_calladjust("main"));
56: gen_end(&vmcodep);
57: BB_BOUNDARY; /* for profiling; see comment in mini.vmg:end */
58: }
59:
60: int locals=0;
61: int nonparams=0;
62:
63: int yylex();
64: %}
65:
66:
67: %token FUNC RETURN END VAR IF THEN ELSE WHILE DO BECOMES PRINT NUM IDENT
68:
69: %union {
70: long num;
71: char *string;
72: Inst *instp;
73: }
74:
75: %type <string> IDENT;
76: %type <num> NUM;
77: %type <instp> elsepart;
78:
79:
80: %%
81: program: program function
82: | ;
83:
84: function: FUNC IDENT { locals=0; nonparams=0; } '(' params ')'
85: vars { insert_func($2,vmcodep,locals,nonparams); }
86: stats RETURN expr ';'
87: END FUNC ';' { gen_return(&vmcodep, -adjust(locals)); }
88: ;
89:
90: params: IDENT ',' { insert_local($1); } params
91: | IDENT { insert_local($1); }
92: | ;
93:
94: vars: vars VAR IDENT ';' { insert_local($3); nonparams++; }
95: | ;
96:
97: stats: stats stat ';'
98: | ;
99:
100: stat: IF expr THEN { gen_zbranch(&vmcodep, 0); $<instp>$ = vmcodep; }
101: stats { $<instp>$ = $<instp>4; }
1.3 anton 102: elsepart END IF { BB_BOUNDARY; $<instp>7[-1] = (Inst)vmcodep; }
1.1 anton 103: | WHILE { BB_BOUNDARY; $<instp>$ = vmcodep; }
104: expr DO { gen_zbranch(&vmcodep, 0); $<instp>$ = vmcodep; }
1.3 anton 105: stats END WHILE { gen_branch(&vmcodep, $<instp>2); $<instp>5[-1] = (Inst)vmcodep; }
1.1 anton 106: | IDENT BECOMES expr { gen_storelocal(&vmcodep, var_offset($1)); }
107: | PRINT expr { gen_print(&vmcodep); }
108: | expr { gen_drop(&vmcodep); }
109: ;
110:
1.3 anton 111: elsepart: ELSE { gen_branch(&vmcodep, 0); $<instp>$ = vmcodep; $<instp>0[-1] = (Inst)vmcodep; }
1.1 anton 112: stats { $$ = $<instp>2; }
113: | { $$ = $<instp>0; }
114: ;
115:
116: expr: term '+' term { gen_add(&vmcodep); }
117: | term '-' term { gen_sub(&vmcodep); }
118: | term '*' term { gen_mul(&vmcodep); }
119: | term '&' term { gen_and(&vmcodep); }
120: | term '|' term { gen_or(&vmcodep); }
121: | term '<' term { gen_lessthan(&vmcodep); }
122: | term '=' term { gen_equals(&vmcodep); }
123: | '!' term { gen_not(&vmcodep); }
124: | '-' term { gen_negate(&vmcodep); }
125: | term
126: ;
127:
128: term: '(' expr ')'
129: | IDENT '(' args ')' { gen_call(&vmcodep, func_addr($1), func_calladjust($1)); }
130: | IDENT { gen_loadlocal(&vmcodep, var_offset($1)); }
131: | NUM { gen_lit(&vmcodep, $1); }
132: ;
133:
1.2 anton 134: /* missing: argument counting and checking against called function */
1.1 anton 135: args: expr ',' args
136: | expr
137: | ;
138: %%
139: int yywrap(void)
140: {
141: return 1;
142: }
143:
144: #include "lex.yy.c"
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>