
%token PREDICATE

%token CHUNK

%token SEMI
%token OPEN
%token CLOSE
%token DOTDOT
%token DOT
%token BECOMES
%token BLOCK
%token COMMA
%token ARROW
%token COLON

%token SKIP
%token ABORT
%token ARRAY
%token OF
%token DO
%token OD
%token IF
%token FI

%token SWAP

%token OPENBLOCK
%token CLOSEBLOCK

%token UNARY_OP
%token MINUS
%token BINARY_OP

%token ACCESS
%token TYPE
%token ID
%token NUMBER

%%

stmt_list	: stmt
		| predicate stmt		{ $1 force $2 }
		| predicate stmt predicate	{ $1 force $2 force $3 }
		| stmt predicate		{ $1 force $2 }
		| stmt SEMI stmt_list		{ $1 $2 force $3 }
		| predicate stmt SEMI stmt_list	{ $1 force $2 $3 force $4 }
;

predicate	: PREDICATE
		| PREDICATE predicate		{ $1 force $2 }
;

stmt		: selection
		| repetition
		| block
		| SWAP simple_expr DOT simple_expr DOT simple_expr   { $1 " " $2 $3 $4 $5 $6 }
		| SKIP
		| ABORT
		| CHUNK
		| assign
;

assign		: expr_list BECOMES expr_list  { $1 " " $2 " " indent opt5 outdent $3 }
;

expr_list	: expr
		| expr COMMA expr_list         { $1 $2 " " opt9 $3 }
;

simple_expr     : ID
		| NUMBER
		| OPEN expr CLOSE
;

expr		: simple_expr
		| ID DOT simple_expr
		| UNARY_OP simple_expr
		| expr binary_op expr        { $1 " " $2 " " $3 }
;

binary_op       : BINARY_OP
		| MINUS
;

unary_op	: UNARY_OP
		| MINUS
;

repetition	: DO guarded_list OD  { $1 " " $2 force $3 }
;

selection	: IF guarded_list FI  { $1 " " $2 force $3 }
;

guarded_list	: guarded_stmt
		| guarded_stmt BLOCK guarded_list  { $1 force $2 " " $3 }
;

guarded_stmt	: expr ARROW stmt_list  { $1 " " $2 indent force $3 outdent }
;

block		: OPENBLOCK decls stmt_list CLOSEBLOCK { $1 indent force $2 force $3 outdent force $4 }
;

decls		: decl
		| decl decls
;

decl		: ACCESS type_decls SEMI { $1 " " $2 " " $3 force }
;

type_decls      : type_decl
                | type_decl COMMA type_decls   { $1 $2 " " $3 }
;

type_decl       : expr_list COLON type { $1 " " $2 " " $3 }
;

type		: TYPE
		| ARRAY bounds OF TYPE  { $1 " " $2 " " $3 " " $4 }
;

bounds		: OPEN expr DOTDOT expr CLOSE
;
