File:  [gforth] / gforth / vmgen-ex / mini.y
Revision 1.5: download - view: text, annotated - select for diffs
Mon Aug 25 14:17:55 2003 UTC (17 years, 8 months ago) by anton
Branches: MAIN
CVS tags: v0-6-2, HEAD
documentation updates
fixed some portability bugs in vmgen-ex and vmgen-ex2
updated copyright years

    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: Inst *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; $<instp>7[-1] = (Inst)vmcodep; }
  104:     | WHILE   { BB_BOUNDARY; $<instp>$ = vmcodep; } 
  105:       expr DO { gen_zbranch(&vmcodep, 0); $<instp>$ = vmcodep; }
  106:       stats END WHILE { gen_branch(&vmcodep, $<instp>2); $<instp>5[-1] = (Inst)vmcodep; }
  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; $<instp>0[-1] = (Inst)vmcodep; }
  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>