Annotation of gforth/vmgen-ex/mini.y, revision 1.6

1.1       anton       1: /* front-end compiler for vmgen example
                      2: 
1.5       anton       3:   Copyright (C) 2001,2002,2003 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>