/*
 * javahu.fg -- experimental Pretzel grammar for Java
 */

/* original filename java.fg
 * (slight changes to java.fg by Lee Wittenberg)
 * by Holger Uhr <huhr@uni-paderborn.de>
 */

%token	BINOP
%token	BREAK_LIKE
%token	CASE_LIKE
%token	CATCH_LIKE
%token	CHUNK
%token	COLON
%token	COMMA
%token	COMMENT
%token	DEFAULT_LIKE
%token	DOT
%token	DOT_STAR
%token	DO_LIKE
%token	ELSE_LIKE
%token	EXTENDS_LIKE
%token	FINALLY_LIKE
%token	FOR_LIKE
%token	ID_LIKE
%token	IF_LIKE
%token	IGNORE
%token	IMPORT_LIKE
%token	INCROP
%token	LBRACE
%token	LBRACK
%token	LPAR
%token	NUM
%token	QUESTION
%token	RBRACE
%token	RBRACK
%token	RPAR
%token	SEMI
%token	STRING
%token	SYNC_LIKE
%token	TRY_LIKE
%token	UNOP
%token	UNORBINOP

%%

final	:	exp				{ "\\mathin" $1 "\\mathout" }
		|	decl_list	{ cancel $1 cancel }
		|	IGNORE
		|	COMMENT	{ $1 force }
		|	IGNORE final
		|	COMMENT final	{ $1 force $2 }
		;

decl_list	:	decl
			|	decl_list decl			{ $1 force $2 }
			;

decl		:	exp block				{ big_force "\\mathin" $1 "\\mathout\\ " $2 big_force }
			;

block		:	lbrace rbrace			{ $1 force $2 }
			|	lbrace decl_list rbrace
					{ $1 indent force $2 cancel outdent force $3 }
			;

exp			:	expr
			|	exp dot expr
			|	exp comma expr		{ $1 $2 opt3 "\\mathin" $3 }
			|	exp expr			{ $1 $2 }
			;

expr		:	term
			|	expr binop term				{ $1 opt9 $2 $3 }
			|	expr unorbinop term			{ $1 opt9 $2 $3 }
			|	expr extends_like idlist	{ $1 force "\\ldots" $2 "\\ " $3 }
			|	expr brack_exp
			;

binop		:	question exp colon		{ "\\mathbin{" $1 $2 $3 "}" }
			;

idlist		:	ident
			|	idlist comma ident		{ $1 $2 opt9 $3 }
			;

ident		:	id_like
			|	sync_like id_like		{ $1 "\\ " $2 }
			|	ident id_like			{ $1 "\\ " $2 }
			;

brack_exp	:	lbrack rbrack			{ $1 "\\thinspace" $2 }
			|	lbrack exp rbrack
			|	brack_exp ident			{ $1 "\\ " $2 }
			;

term		:	factor
			|	unop term				{ "\\mathin{" $1 $2 "}" }
			|	unorbinop term			{ "\\mathin{" $1 $2 "}" }
			|	incrop term				{ "\\mathin{" $1 $2 "}" }
			|	term incrop				{ "\\mathin{" $1 $2 "}" }
			;

factor		:	ident
			|	num
			|	string
			|	lpar rpar				{ $1 "\\thinspace" $2 }
			|	lpar exp rpar
			;

decl		:	block
			|	non_block_stmt
			;

non_block_stmt
			:	semi					{ cancel $1 }
			|	exp semi				{ "\\mathin" $1 "\\mathout" $2 }
			|	break_like semi
			|	break_like exp semi		{ $1 "\\ \\mathin" $2 "\\mathout" $3 }
			|	sync_like lpar exp rpar decl
					{ $1 "\\ \\mathin" $2 $3 $4 "\\mathout\\ " $5 }
			|	import_head semi
			|	label colon decl		{ force backup $1 $2 force $3 }
			|	try_stmt
			|	if_block
			|	if_simple
			|	else_head block			{ $1 "\\ " $2 }
			|	else_head non_block_stmt
					{ $1 indent force $2 outdent }
			|	for_stmt
			|	do_stmt
			|	CHUNK	{ $1 force } // Holger Uhr
			;

import_head	:	import_like id_like		{ $1 "\\ " $2 }
			|	import_head dot id_like
			|	import_head dot_star
			;

if_head		:	if_like lpar exp rpar
					{ $1 "\\ \\mathin" $2 $3 $4 "\\mathout" }
			;

if_block	:	if_head block			{ $1 "\\ " $2 }
			;

if_simple	:	if_head non_block_stmt	{ $1 indent force $2 outdent }
			;

else_head	:	else_like
			|	if_block else_like		{ $1 "\\ " $2 }
			|	if_simple else_like		{ $1 force $2 }
			;

try_stmt	:	try_like block			{ $1 "\\ " $2 }
			|	try_stmt finally_like block
					{ $1 "\\ " $2 "\\ " $3 }
			|	try_stmt catch_like lpar exp rpar block
					{ $1 "\\ \\mathin" $2 $3 $4 $5 "\\mathout\\ " $6 }
			;

label		:	default_like
			|	case_like exp			{ $1 "\\ \\mathin" $2 "\\mathout"}
			|	id_like
			;

do_stmt		:	do_like block if_head semi
					{ $1 "\\ " $2 "\\ " $3 $4 }
			|	do_like non_block_stmt if_head semi
					{ $1 indent force $2 outdent $3 $4 }
			;

for_head	:	for_like lpar for_control rpar
					{ $1 "\\ " $2 $3 $4 }
			;

for_control	:	opt_exp semi opt_exp semi opt_exp
			;

opt_exp		:	// empty
			|	exp			{ "\\mathin" $1 "\\mathout" }
			;

for_stmt	:	for_head block			{ $1 "\\ " $2 }
			|	for_head non_block_stmt	{ $1 indent force $2 outdent }
			;

// rules to pass comments and ignores through unnoticed
binop			:	BINOP
				|	binop IGNORE
				|	binop COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
break_like		:	BREAK_LIKE
				|	break_like IGNORE
				|	break_like COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
case_like		:	CASE_LIKE
				|	case_like IGNORE
				|	case_like COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
catch_like		:	CATCH_LIKE
				|	catch_like IGNORE
				|	catch_like COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
colon			:	COLON
				|	colon IGNORE
				|	colon COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
comma			:	COMMA
				|	comma IGNORE
				|	comma COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
default_like	:	DEFAULT_LIKE
				|	default_like IGNORE
				|	default_like COMMENT	{ $1 "\\qquad" break_space $2 force }
				;
dot				:	DOT
				|	dot IGNORE
				|	dot COMMENT				{ $1 "\\qquad" break_space $2 force }
				;
dot_star		:	DOT_STAR
				|	dot_star IGNORE
				|	dot_star COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
do_like			:	DO_LIKE
				|	do_like IGNORE
				|	do_like COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
else_like		:	ELSE_LIKE
				|	else_like IGNORE
				|	else_like COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
extends_like	:	EXTENDS_LIKE
				|	extends_like IGNORE
				|	extends_like COMMENT	{ $1 "\\qquad" break_space $2 force }
				;
finally_like	:	FINALLY_LIKE
				|	finally_like IGNORE
				|	finally_like COMMENT	{ $1 "\\qquad" break_space $2 force }
				;
for_like		:	FOR_LIKE
				|	for_like IGNORE
				|	for_like COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
id_like			:	ID_LIKE
				|	id_like IGNORE
				|	id_like COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
if_like			:	IF_LIKE
				|	if_like IGNORE
				|	if_like COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
import_like		:	IMPORT_LIKE
				|	import_like IGNORE
				|	import_like COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
incrop			:	INCROP
				|	incrop IGNORE
				|	incrop COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
lbrace			:	LBRACE
				|	lbrace IGNORE
				|	lbrace COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
lbrack			:	LBRACK
				|	lbrack IGNORE
				|	lbrack COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
lpar			:	LPAR
				|	lpar IGNORE
				|	lpar COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
num				:	NUM
				|	num IGNORE
				|	num COMMENT				{ $1 "\\qquad" break_space $2 force }
				;
question		:	QUESTION
				|	question IGNORE
				|	question COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
rbrace			:	RBRACE
				|	rbrace IGNORE
				|	rbrace COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
rbrack			:	RBRACK
				|	rbrack IGNORE
				|	rbrack COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
rpar			:	RPAR
				|	rpar IGNORE
				|	rpar COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
semi			:	SEMI
				|	semi IGNORE
				|	semi COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
string			:	STRING
				|	string IGNORE
				|	string COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
sync_like		:	SYNC_LIKE
				|	sync_like IGNORE
				|	sync_like COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
try_like		:	TRY_LIKE
				|	try_like IGNORE
				|	try_like COMMENT		{ $1 "\\qquad" break_space $2 force }
				;
unop			:	UNOP
				|	unop IGNORE
				|	unop COMMENT			{ $1 "\\qquad" break_space $2 force }
				;
unorbinop		:	UNORBINOP
				|	unorbinop IGNORE
				|	unorbinop COMMENT		{ $1 "\\qquad" break_space $2 force }
				;

%%

