/* 
 * Laddie to Clay Compiler
 * Author: Lea Wittie and Derrin Pierret
 * Copyright (c) 2007 Bucknell University
 *
 * Permission is hereby granted, free of charge, to any individual or
 * institution obtaining a copy of this software and associated
 * documentation files (the "Software"), to use, copy, modify, and
 * distribute without restriction, provided that this copyright and
 * permission notice is maintained, intact, in all copies and supporting
 * documentation.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
driver			: states_opt ports ;

/* general things */
num			:	INT | HEX ;
num_or_set		:	num | '[' constraint_set ']' ;
num_or_range		:	num | num ':' num | num '-' num ;
type			:	BOOLEAN | INTEGER ;
constraint_set		:	num_or_range
			|	num_or_range ',' constraint_set ;
num_or_bool             :       num | BOOL ;
id_or_value		:       ID | VALUE ;

/* global state declarations with constraints  
   Translate into Clay linear 0-word types and 
   Add to a Clay struct of capabilities 
*/
states_opt	:	| states ;
states		: state | state states ;
state		: type ID ';' 
			| type ID colon_opt num_or_set ';' ;

/* ports: IO rules. uses states */
ports			: port ports | port ;
port			: PORT num '{' port_info '}' ;
port_info		: name_info size_info_opt 
                          type_info_opt access_info_opt 
			  field_list_opt before_opt after_opt test_opt ;
name_info		: NAME '=' ID ';' ;
size_info_opt		: | SIZE '=' num ';' ; // default is 2 byte
type_info_opt           : | TYPE '=' REPEATED ';' ; // default is not repeated
access_info_opt		: | ACCESS '=' read_write ';' ; // default is RW
read_write		: R | W | RW ;

/* fields */
field_list_opt	: | field_list ;
field_list		: field_info | field_info field_list ;
field_info		: '[' num_or_range ']' colon_opt ID ';' field_attribs;
colon_opt               : | ':' ;
field_attribs           : read_attrib_opt write_attrib_opt enum_opt ;
write_attrib_opt        : | WRITE_VALUE '=' write_attrib ';' ;
write_attrib            : FIXED '(' num ')' | PRESERVED ; /* default is none */
read_attrib_opt         : | READ_VALUE '=' read_attrib ';' ;
// read: dont_matter | volatile_se | fixed(num)
// write:dont_change | no_default | explicit
read_attrib             : STATIC | VOLATILE ; /* default is none */
// HAIL allows an enum: "enum { foo=0x2, bar=0x3 }"
enum_opt                : | ENUM '{' enum_list '}' ';' ;
enum_list               : enum_val | enum_val ',' enum_list ;
enum_val                : ID | ID '=' num ;

/* constraints on input or output */
before_opt       : | before before_opt ;
before           : REQUIRES constraints | REQUIRES read_write constraints
         | REQUIRES '{' constraints '}' | REQUIRES read_write '{' constraints '}' ;
after_opt        : | after after_opt ;
after            : ENSURES constraints | ENSURES read_write constraints 
         | ENSURES '{' constraints '}' | ENSURES read_write '{' constraints '}' ;
constraints      : transitions 
		 | SWITCH ID '{' switch_cases default_case_opt '}' ;
switch_cases : switch_case | switch_case switch_cases ;
switch_case	 : num ':' transitions | ID ':' transitions ;
default_case_opt : | DEFAULT ':' transitions ;

/* a set of transitions */
transitions    :  logic_OR ';' | '{' logic_list '}' ;
logic_list     : logic_OR ';' | logic_OR ';' logic_list ;

logic_OR       : logic_AND | logic_OR OROR logic_AND ;
logic_AND      : logic_NOT | logic_AND ANDAND logic_NOT ;
logic_NOT      : '!' logic_end | logic_end ;
logic_end      : '(' logic_OR ')' | rel_exp ;

rel_exp        : add_exp relop add_exp ;
relop          :   '>' | GEQ | '<' | LEQ | EQEQ | NEQ;

add_exp        : mul_exp | add_exp addop mul_exp ;
addop          : '+' | '-' ;
mul_exp        : exp_end | mul_exp '*' exp_end ;
exp_end        : '(' add_exp ')' | ID | num | BOOL | OLD '(' ID ')' | VALUE 
	       | COUNT ;

test_opt       : | TEST_INPUT test_list ';' ;
test_list      : test | test_list ',' test ;
test           : id_or_value '=' num_or_bool ;

SPECIAL_TERMINALS ID, INT, HEX, BOOL;
