/* yacc file for AEC, the AE Compiler.
   Copyright (C) 1989, 1990 by James R. Larus (larus@cs.wisc.edu)

   AE and AEC are free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 1, or (at your option) any
   later version.

   AE and AEC are distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU CC; see the file COPYING.  If not, write to James R.
   Larus, Computer Sciences Department, University of Wisconsin--Madison,
   1210 West Dayton Street, Madison, WI 53706, USA or to the Free
   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */


/* $Header: /var/home/larus/AE/AEC/RCS/parser.y,v 2.0 90/02/09 17:23:46 larus Exp Locker: larus $ */


%start SCHEMA

%token Y_EOF 0

%token Y_FUNCTION_START
%token Y_FUNCTION_END
%token Y_BLOCK_START
%token Y_BLOCK_START_TARGET
%token Y_BLOCK_END
%token Y_BLOCK_END_NEXT_TARGET
%token Y_BLOCK_END_JUMP
%token Y_BLOCK_END_JUMP_NEXT_TARGET
%token Y_BLOCK_END_CJUMP
%token Y_UNEVENTFUL_INST
%token Y_STORE_INST
%token Y_STORE_D_INST
%token Y_STORE_UNKNOWN_INST
%token Y_LOAD_INST
%token Y_LOAD_D_INST
%token Y_LOAD_UNKNOWN_INST
%token Y_COMPUTE_DEFN_0
%token Y_COMPUTE_DEFN_1
%token Y_COMPUTE_DEFN_2
%token Y_UNKNOWN_DEFN
%token Y_CALL_INST
%token Y_CALL_INDIRECT_INST
%token Y_ID
%token Y_LIT
%token Y_INT
%token Y_LPAREN
%token Y_RPAREN
%token Y_REG
%token Y_NL
%token Y_OP
%token Y_LOOP_ENTRY
%token Y_LOOP_BACK
%token Y_LOOP_EXIT

%{
#include <stdio.h>
#include "aec.h"

extern int line_no;
void print_erroneous_line ();
void scanner_nl ();
%}

%%

SCHEMA	:	LINE
			{return(1);};

LINE	:	Y_FUNCTION_START Y_ID Y_INT Y_NL
			{function_start ($2, $3); scanner_nl ();}
	|	Y_FUNCTION_END Y_ID Y_NL
			{function_end ($2); scanner_nl ();}

	|	Y_BLOCK_START Y_INT Y_NL
			{block_start ($2); scanner_nl ();}
	|	Y_BLOCK_START_TARGET Y_INT Y_NL
			{block_start_target ($2); scanner_nl ();}

	|	Y_BLOCK_END Y_INT LOOP_ANNO Y_NL
			{block_end ($2, 0, $3); scanner_nl ();}
	|	Y_BLOCK_END_NEXT_TARGET Y_INT LOOP_ANNO Y_NL
			{block_end ($2, 1, $3); scanner_nl ();}

	|	Y_BLOCK_END_JUMP Y_INT Y_INT LOOP_ANNO Y_NL
			{block_end_jump ($2, $3, 0, $4); scanner_nl ();}
	|	Y_BLOCK_END_JUMP_NEXT_TARGET Y_INT Y_INT LOOP_ANNO Y_NL
			{block_end_jump ($2, $3, 1, $4); scanner_nl ();}

	|	Y_BLOCK_END_CJUMP Y_INT INT_LIST LOOP_ANNO Y_NL
			{block_end_cjump ($2, $3, $4); scanner_nl ();}

	|	Y_UNEVENTFUL_INST Y_INT Y_INT Y_NL
			{uneventful_inst ($2, $3); scanner_nl ();}

	|	Y_STORE_INST Y_LIT Y_OP Y_LIT Y_NL
			{if (*(char *) $3 != '+') yyerror ("syntax");
			 store_inst ($2, $4); scanner_nl ();}
	|	Y_STORE_D_INST Y_LIT Y_OP Y_LIT Y_NL
			{if (*(char *) $3 != '+') yyerror ("syntax");
			 store_d_inst ($2, $4); scanner_nl ();}
	|	Y_STORE_UNKNOWN_INST Y_NL
			{store_unknown_inst (); scanner_nl ();}

	|	Y_LOAD_INST Y_LIT Y_OP Y_LIT Y_NL
			{if (*(char *) $3 != '+') yyerror ("syntax");
			 load_inst ($2, $4); scanner_nl ();}
	|	Y_LOAD_D_INST Y_LIT Y_OP Y_LIT Y_NL
			{if (*(char *) $3 != '+') yyerror ("syntax");
			 load_d_inst ($2, $4); scanner_nl ();}
	|	Y_LOAD_UNKNOWN_INST Y_NL
			{load_unknown_inst (); scanner_nl ();}

	|	Y_COMPUTE_DEFN_0 Y_REG Y_LIT Y_NL
			{compute_defn (0, $2, NULL, $3, NULL); scanner_nl ();}
	|	Y_COMPUTE_DEFN_1 Y_REG Y_OP Y_LIT Y_NL
			{compute_defn (1, $2, $3, $4, NULL); scanner_nl ();}
	|	Y_COMPUTE_DEFN_2 Y_REG Y_LIT Y_OP Y_LIT Y_NL
			{compute_defn (2, $2, $4, $3, $5); scanner_nl ();}
	|	Y_UNKNOWN_DEFN Y_REG Y_NL
			{unknown_defn ($2); scanner_nl ();}

	|	Y_CALL_INST Y_ID Y_NL
			{call_inst ($2); scanner_nl ();}
	|	Y_CALL_INDIRECT_INST Y_REG Y_NL
			{call_indirect_inst ($2); scanner_nl ();}

	|	Y_NL
			{scanner_nl ();}

	|	Y_EOF
			{return (0);}

	|	error ;


INT_LIST:	INT_LIST Y_INT
			{$$ = (int) cons ($2, $1);}
	|	 Y_INT
			{$$ = (int) cons ($1, NULL);};


LOOP_ANNO:	LOOP_ANNO Y_LOOP_ENTRY Y_LPAREN Y_INT Y_INT Y_RPAREN
			{$$ = (int) cons (cons (START_LOOP, cons ($4, $5)),
					  $1);}
	|	LOOP_ANNO Y_LOOP_BACK Y_LPAREN Y_INT Y_INT Y_RPAREN
			{$$ = (int) cons (cons (CONT_LOOP, cons ($4, $5)),
					  $1);}
	|	LOOP_ANNO Y_LOOP_EXIT Y_LPAREN Y_INT Y_INT Y_RPAREN
			{$$ = (int) cons (cons (END_LOOP, cons ($4, $5)),
					  $1);}
	|
			{$$ = (int) NULL;};


%%

yyerror (s)
     char *s;
{
  extern char *input_file_name;

  fprintf (stderr, "aec: (parser) %s on line %d of file %s\n", s, line_no,
	   input_file_name);
  print_erroneous_line (stderr);
}
