%{ CODE HEADER
/*
 * The Termprocessor Kimwitu
 *
 * Copyright (c) 1991 University of Twente, Dept TIOS.
 * All rights reserved.
 *
 */
%}
/*
 * abs.k
 */
%{
#if ! (defined(lint) || defined(SABER) || defined(CODECENTER))
  static char abs_kAccesSid[] = "@(#)$Id: abs.k,v 1.18 1997/05/26 16:10:31 belinfan Rel $";
#endif
%}

/***************************************************************************/
/*
 * Name conventions: atom phyla are in CAPITALS (like ID, INT)
 * other phyla are in lowercase
 * operators are capitalized
 *
 */
/***************************************************************************/
/*
 * ABSTRACT SYNTAX
 *
 * Phyla used only as attribute value follow below in a separate section
 */

uniqID { uniq }
:	Str( casestring )
{	IDtype type = ITUnknown();
	int line = 0;
	casestring file = mkcasestring("");
	scopetypefilelinestack scopeinfo = Nilscopetypefilelinestack();
	/*
	 * in the scopeinfo we store the last (previous) typeinfo,
	 * together with the _current_ scope, ie the same scope as
	 * in the current typeinfo.
	 * this scope is used to check whether we need to pop the
	 * scopeinfo, or have to wait. This should handle things like:
	 *   void foo( v ) phylum v; {
	 *      with( v ) {
	 *	  Operator( s1, x, y ): {
	 *	    with( s1 ) {
	 *	      Operator( s2, *, y ): {
	 *		with( s2 ) {
	 * 		  Operator( *, y, x ): {
	 * etc.
	 * ie. where we have 'holes' in the scopestack, for certain
	 * variables, like `x' in the example above
	 */
};

ID
:	Id( uniqID )
{	IDtype type = ITUnknown();
	int line = 0;
	casestring file = mkcasestring("");
};

INT
:	Int( int )
{	int line = 0;
	casestring file = mkcasestring("");
};

STRING
:	String( casestring )
{	int line = 0;
	casestring file = mkcasestring("");
};

phylumdeclarationsroot
:	PhylumDeclarations( phylumdeclarations )
;

phylumdeclarations
:	list phylumdeclaration
;

phylumnames
:	list ID
;

phylumdeclaration

:	PhylumDeclaration( ID storageoption  productionblock Ccode_option )
{	int marked = 0;
};

storageoption
:	NoStorageOption()
|	NegativeStorageOption( ID )
|	PositiveStorageOption( ID )
;

storageclasses
:	list ID
{	phylumnames phyla = Nilphylumnames();
}
;

productionblock
:	Emptyproductionblock()
|	ListAlternatives( alternatives ID )
|	NonlistAlternatives( alternatives )
|	PredefinedAlternatives( alternatives )
;

alternatives
:	list alternative
;

alternative
:	Alternative( ID  arguments )
{	rewriterulesinfo rewriteinfo = Nilrewriterulesinfo();
	unparsedeclsinfo unparseinfo = Nilunparsedeclsinfo();
	boolean bigatoms = False;
}
;

arguments
:	list ID
{	int seqnr;
};

argument
:	Argument( ID /*seqnr*/int )
;

Ccode_option
:	CcodeOption( attributes Ctexts )
;

attributes
:	list attribute
;

attribute
:	Attribute( ID ID attribute_initialisation_option )
;

attribute_initialisation_option
:	Noattribute_initialisation()
|	Yesattribute_initialisation( Cexpression )
;

Cexpression
:	list Cexpression_elem
{	int line = 0;
	casestring file = mkcasestring("");
};

Cexpression_elem
:	CExpressionPart( casestring )
|	CExpressionDollarvar( INT )
|	CExpressionNl( int )
|	CExpressionDQ( CexpressionDQ )
|	CExpressionSQ( CexpressionSQ )
|	CExpressionPack( Cexpression )
|	CExpressionArray( Cexpression )
;


CexpressionDQ
:	list CexpressionDQ_elem
;

CexpressionDQ_elem
:	CExpressionDQPart( casestring )
|	CExpressionDQNl( int )
;

CexpressionSQ
:	list CexpressionSQ_elem
;

CexpressionSQ_elem
:	CExpressionSQPart( casestring )
|	CExpressionSQNl( int )
;

idCexpressions
:	list idCexpression
;

idCexpression
:	IdCexpression( ID Cexpression )
{	ID id = f_emptyId();
}
;

Ctexts
:	list Ctext
;

%{ KC_TYPES_HEADER
typedef enum {include_header =0, include_file =1, include_unknown, include_both} include_type;
#define INC2 inc[2]
%}
includefiles
:	list includefile
;

includefile {uniq}
:	IncludeFile( casestring )
{
	include_type inc_type = include_unknown; /* indexes in includes */
	includedeclarations INC2;
	includefile newinclude = 0; /*points to new includes for old ones */
	{ $0->inc[0] = Nilincludedeclarations();
	  $0->inc[1] = Nilincludedeclarations();
	 if (Theincludefiles == (includefiles)0) {
	     Theincludefiles = Consincludefiles( $0, Nilincludefiles());
	  } else {
	     Theincludefiles = Consincludefiles( $0, Theincludefiles);
	  }
	}
};

includedeclarations
:	list includedeclaration
;

includedeclaration
:	IncludeDeclaration( includes )
{	int line = 0;
	casestring file = mkcasestring("");
};

includes
:	list include
;

include
:	Include( casestring )
|	IncludeNl( int )
;

rwdeclarations	
:	list rwdeclaration
;

rwdeclaration	
:	RwDeclaration( outmostpatterns rewriteclauses )
;

rewriteclauses
:	list rewriteclause
;

rewriteclause
:	RewriteClause( viewnames term )
;

/* concrete syntax: patternchains = patternchain, patternchain,.... */
patternchains
:	list patternchain
{	int line = 0;
	casestring file = mkcasestring("");
}
;

/* concrete syntax: patternchain = patternchainitem & patternchainitem & .... */
patternchain
:	list patternchainitem
{	int line = 0;
	casestring file = mkcasestring("");
}
;

outmostpatterns
:	list outmostpattern
;

patternchainitem
:	PatternchainitemOutmost( outmostpattern )
|	PatternchainitemGroup( patternchains )
|	PatternchainitemDollarid( ID )
{	int line = 0;
	casestring file = mkcasestring("");
	ID type = f_emptyId();
}
;

outmostpattern
:	OPOperatorWildcard( ID )
|	OPOperator( ID patterns )
|	OPNonLeafVariable( ID outmostpattern )
|	OPWildcard()
|	OPDefault() /* HACK!! */
{	ID type = f_emptyId();
}
;

pattern
:	PVariable( ID )
|	POperator( ID patterns )
|	PNonLeafVariable( ID pattern )
|	PWildcard()
|	PStringLiteral( CexpressionDQ )
|	PIntLiteral( INT )
;

patterns
:	list pattern
;

term	
:	TVariable( ID )
|	TOperator( ID terms )
|	TStringLiteral( CexpressionDQ )
|	TIntLiteral( INT )
;

terms	
:	list term
;


fnfiles
:	list fnfile
;

fnfile {uniq}
:	FnFile( casestring )
{
	fndeclarations fns;
	{ $0->fns = Nilfndeclarations();
	 if (Thefnfiles == (fnfiles)0) {
	     Thefnfiles = Consfnfiles( $0, Nilfnfiles());
	  } else {
	     Thefnfiles = Consfnfiles( $0, Thefnfiles);
	  }
	}
};

fndeclarations	
:	list fndeclaration
;

/* needed for sort_extend_Cvariabledeclarations */
%{ KC_TYPES
#include "gutil.h"
%}
fndeclaration	
:	FnDeclaration( ID/*type*/ int/*pointer*/ ID/*name*/ fnarguments Cvariabledeclarations Ctext fnclass )
|	FnAcDeclaration( ac_declaration_specifiers ac_declarator ac_declaration_list Ctext ID/*name*/ fnclass )
{ Cvariabledeclarations sorted;
  ac_parameter_type_list newsorted;
	int last_line = 0; /* line nr of _last_ line of body (contains close-brace) */
	casestring file = mkcasestring("");
	{ with($0) {
	    FnDeclaration(*, *, *, fn_args, C_vardecls, *, *): {
	      $0->sorted = sort_extend_Cvariabledeclarations( C_vardecls, fn_args );
		}
	    FnAcDeclaration(*, fn_args, C_vardecls, *, *, *): {
	      $0->newsorted = sort_extend_parameter_type_list( C_vardecls, fn_args );
	} } }
}
;

fnclass	
:	GlobalFn()
|	LocalFn( casestring/*filename*/ )
;

fnarguments	
:	list ID
;

Cvariabledeclarations
:	list Cvariabledeclaration
;

Cvariabledeclaration
:	CVariabledeclaration( ID/*type*/ Cvariables )
|	Fnargfpdecl( ID/*type*/ Cvariables )
;

Cvariables
:	list Cvariable
;

Cvariable
:	CVPointer( /*pointer*/int /*name*/ID )
|	CVFunction( /*pointer*/int /*pointer*/int /*name*/ID )
;

Ctext
:	list Ctext_elem
{	int line = 0;
	casestring file = mkcasestring("");
}
;

Ctext_elem
:	CTextLine( casestring )
|	CTextDollarVar( INT )
|	CTextNl( int )
|	CTextCexpressionDQ( CexpressionDQ )
|	CTextCexpressionSQ( CexpressionSQ )
|	CTextCbody( Ctext )
|	CTextForeachexpression( patternchain idCexpressions withexpressions Ctext foreach_after )
|	CTextWithexpression( withexpressions withcases contextinfo )
{	int line = 0;
	casestring file = mkcasestring("");
}
;

foreach_after
:	NoForeachAfter()
|	ForeachAfter( patternchain idCexpressions withexpressions Ctext )
{	int line = 0;
	casestring file = mkcasestring("");
}
;

contextinfo
:	InForeachContext( patternchain )
|	NotInForeachContext()
;

withexpressions
:	list withexpression
{	phylumnames type = 0;
	int line = 0;
	casestring file = mkcasestring("");
 {	with($0) {
 		Nilwithexpressions(): {
 			$0->type = Nilphylumnames();
 		}
 		Conswithexpressions( h, t ): {
 			$0->type = Consphylumnames( h->type, t->type );
 			$0->line = h->line;
 			$0->file = h->file;
 	}	}
 }
}
;

withexpression
:	WEVariable( ID )
|	WECexpression( Cexpression )
{	ID type = f_emptyId();
	int line = 0;
	casestring file = mkcasestring("");
 {
 	with($0) {
 		WEVariable( id ): {
 			$0->line = id->line;
 			$0->file = id->file;
 		}
 		WECexpression( e ): {
 			$0->line = e->line;
 			$0->file = e->file;
 		}
 	}
 }
	
}
;

withcases
:	list withcase
{	withcasesinfo wcinfo;
}
;

withcase
:	Withcase( patternchains Ctext )
{	withcasesinfo wcinfo;
}
;

unparsedeclarations
:	list unparsedeclaration
;

unparsedeclaration
:	UnparseDeclaration( outmostpatterns unparseclauses )
{	patternrepresentations patternreps;
}
;

unparseclauses
:	list unparseclause
;

unparseclause
:	UnparseClause( viewnames unparseitems )
;

viewnames
:	list ID
;

unparseitems
:	list unparseitem
;

unparseitem
:	UnpStr( CexpressionDQ viewnameoption )
|	UnpSubexpr( unpsubterm viewnameoption )
|	UnpCtext( Ctext )
|	UnpBody( unparseitems )
;

unpsubterm
:	UnpSubTerm( ID )
|	UnpDollarvarTerm( INT )
|	UnpSubAttr( ID unpattributes )
|	UnpDollarvarAttr( INT unpattributes )
|	UnpCastedVariable( ID ID )
;

unpattributes
:	list ID
;

viewnameoption
:	NoViewname()
|	YesViewname( ID )
;

/***************************************************************************/
/*
 * ATTRIBUTE TYPES
 *
 */

filelinestack
:	list fileline
;

fileline
:	FileLine( casestring int )
|	NoFileLine()
|	PosNoFileLine()
;

nooperatorsstack
:	list int
;

scopetypefilelinestack
:	list scopetypefileline
;

scopetypefileline
:	ScopeTypeFileLine( int IDtype casestring int )
;

IDtype
:	ITUnknown()
|	ITPredefinedPhylum( phylumdeclaration )
|	ITPredefinedBigatomPhylum( phylumdeclaration )
|	ITUserPhylum( phylumdeclaration )
|	ITPredefinedOperator( alternative /*phylum*/ID )
|	ITUserOperator( alternative /*phylum*/ID )
|	ITPredefinedStorageClass()
|	ITStorageClass()
|	ITPredefinedUView()
|	ITUserUView()
|	ITPredefinedRView()
|	ITUserRView()
|	ITUserFunction( fnclass )
|	ITPatternVariable( /*phylum*/ID /*scope*/ int )
{
{	with($0) {
	    ITPredefinedBigatomPhylum( PhylumDeclaration( id, *, *, * ) ): {
	 	if (cg_bigatomphyla) {
		    cg_bigatomphyla = Consphyla( id, cg_bigatomphyla );
		} else {
		    cg_bigatomphyla = Consphyla( id, Nilphyla() );
	    }   }
	    default: {/*EMPTY*/}
}	}
}
;

operatorsstack
:	list operators
;

operators
:	list ID
;

phyla
:	list ID
;

variables
:	list ID
;

argumentsstack
:	list arguments
;

phylumstack
:	list ID
;

phylumnamesstack
:	list phylumnames
;

withexpressionsstack
:	list withexpressions
;

operatorstack
:	list ID
;

variablesstack
:	list variables
;

selvarstack
:	list ID
;

dollarvarstatus
:	DVAllowed()
|	DVDisallowed()
;

dollarvarsallowedstack
:	list dollarvarstatus
;

intstack
:	list int
;

idCexpressionsstack
:	list idCexpressions
;

/***************************************************************************/
/*
 * TWO-* STUFF FOR PATTERN MATCHING
 *
 */

two_phyla
:	TwoStorageoption( storageoption storageoption )
|	TwoProductionblock( productionblock productionblock )
|	TwoCcode_option( Ccode_option Ccode_option )
|	TwoRewriteruleinfo( rewriteruleinfo rewriteruleinfo )
|	TwoWithcaseinfo( withcaseinfo withcaseinfo )
|	TwoUnparsedeclinfo( unparsedeclinfo unparsedeclinfo )
|	TwoPatternrepresentation( patternrepresentation patternrepresentation )
|	TwoElem_patternrepresentation( elem_patternrepresentation elem_patternrepresentation )
|	TwoPaths( paths paths )
|	TwoPath( path path )
;

tribool
:	Equal()
|	Smaller()
|	Bigger()
;

/***************************************************************************/
/*
 * Stuff for patterns etc.
 */

patternrepresentations
:	list patternrepresentation
;

patternrepresentation
:	list elem_patternrepresentation
;

elem_patternrepresentation
:	PRBinding( path ID )
|	PRVarPredicate( paths ID patternrepresentation )
|	PROperPredicate( path ID )
|	PRNonLeafBinding( path ID patternrepresentation )
|	PRWildcard( path )
|	PRDefault()
|	PRStringLiteral( path CexpressionDQ )
|	PRIntLiteral( path INT )
{	ID type = f_emptyId();
};

path
:	list int
{	ID op = f_emptyId();
	ID id = f_emptyId(); /* we use this only to store info for OPNonLeafVariable */
}
;

paths
:	list path
;

/***************************************************************************/

argsnumbers
:	list int
;

/***************************************************************************/


rewriterulesinfo
:	list rewriteruleinfo
;

rewriteruleinfo
:	Rewriteruleinfo( patternrepresentation/*predicates*/ patternrepresentation/*bindings*/ rewriteclause )
;

withcasesinfo
:	list withcaseinfo
;

withcaseinfo
:	Withcaseinfo( patternrepresentation/*predicates*/ patternrepresentation/*bindings*/ Ctext )
;

rewriteviewsinfo
:	list rewriteviewinfo
;

rewriteviewinfo
:	Rewriteviewinfo( ID rewriterulesinfo )
;

unparseviewsinfo
:	list unparseviewinfo
;

unparseviewinfo
:	Unparseviewinfo( ID unparsedeclsinfo )
;

unparsedeclsinfo
:	list unparsedeclinfo
;

unparsedeclinfo
:	Unparsedeclinfo( patternrepresentation/*predicates*/ patternrepresentation/*bindings*/ unparseclause )
;

ac_declaration
:	AcDeclaration( ac_declaration_specifiers ac_init_declarator_list )
;

ac_declaration_list
:	list ac_declaration
;

ac_declaration_specifiers
:	list ac_declaration_specifier
;

ac_declaration_specifier
:	AcDeclSpecStorageSpec( ac_storage_class_specifier )
|	AcDeclSpecTypeSpec( ac_type_specifier )
|	AcDeclSpecTypeQual( ac_type_qualifier )
;

ac_storage_class_specifier
:	AcAuto()
|	AcRegister()
|	AcStatic()
|	AcExtern()
|	AcTypedef()
;

ac_type_specifier
:	AcTypeSpec( ID )		/* to simplify */
;

ac_type_qualifier
:	AcConst()
|	AcVolatile()
;

ac_init_declarator_list
:	list ac_init_declarator
;

ac_init_declarator
:	AcInitDecl( ac_declarator )
/* this one commented out for simplification
|	ac_declarator '=' ac_initializer
*/
;

ac_declarator
:	AcDeclarator( ac_pointer_option ac_direct_declarator )
;

ac_direct_declarator
:	AcDirectDeclId( ID )
|	AcDirectDeclPack( ac_declarator )
|	AcDirectDeclArray( ac_direct_declarator ac_constant_expression_option )
|	AcDirectDeclProto( ac_direct_declarator ac_parameter_type_list )
|	AcDirectDeclKandR( ac_direct_declarator ac_identifier_list )
;

ac_pointer_option
:	Nopointer()
|	Yespointer( ac_pointer )
;
ac_pointer
:	AcPointerNil( ac_type_qualifier_list )
|	AcPointerCons( ac_type_qualifier_list ac_pointer )
;

ac_type_qualifier_list
:	list ac_type_qualifier
;

ac_parameter_type_list
:	AcParList( ac_parameter_list )
|	AcParList3Dot( ac_parameter_list )
;

ac_parameter_list
:	list ac_parameter_declaration
;

ac_parameter_declaration
:	AcParDeclDecl( ac_declaration_specifiers ac_declarator )
|	AcParDeclAbsdecl( ac_declaration_specifiers ac_abstract_declarator )
;

ac_identifier_list
:	list ID
;

ac_abstract_declarator
:	AcAbsdeclPointer( ac_pointer )
|	AcAbsdeclDirdecl( ac_pointer_option ac_direct_abstract_declarator )
;

ac_direct_abstract_declarator_option
:	Noac_direct_abstract_declarator()
|	Yesac_direct_abstract_declarator( ac_direct_abstract_declarator )
;
ac_direct_abstract_declarator
:	AcDirAbsdeclPack( ac_abstract_declarator )
|	AcDirAbsdeclArray( ac_direct_abstract_declarator_option ac_constant_expression_option )
|	AcDirAbsdeclFn( ac_direct_abstract_declarator_option ac_parameter_type_list )
;

/* we don't need a Noac_constant_expression here, because Cexpression
 * can be the empty string
 */
ac_constant_expression_option
:	Yesac_constant_expression( ac_constant_expression )
;
ac_constant_expression
:	AcConstExpr( Cexpression ) /* to make things easier, I hope... */
;
