/* $Id$ */

#define MAX_ARITY	2

typedef int ItemSetNum;
typedef int OperatorNum;
typedef int NonTerminalNum;
typedef int RuleNum;
typedef int ArityNum;
typedef int ERuleNum;

extern NonTerminalNum	last_user_nonterminal;
extern NonTerminalNum	max_nonterminal;
extern RuleNum		max_rule;
extern ERuleNum		max_erule_num;
extern int		max_arity;

#ifdef __STDC__
#define ARGS(x) x
#else
#define ARGS(x) ()
#endif

#ifndef NOLEX
#define DELTAWIDTH	4
typedef short DeltaCost[DELTAWIDTH];
typedef short *DeltaPtr;
extern void ASSIGNCOST ARGS((DeltaPtr, DeltaPtr));
extern void ADDCOST ARGS((DeltaPtr, DeltaPtr));
extern void MINUSCOST ARGS((DeltaPtr, DeltaPtr));
extern void ZEROCOST ARGS((DeltaPtr));
extern int LESSCOST ARGS((DeltaPtr, DeltaPtr));
extern int EQUALCOST ARGS((DeltaPtr, DeltaPtr));
#define PRINCIPLECOST(x)	(x[0])
#else
#define DELTAWIDTH	1
typedef int DeltaCost;
typedef int DeltaPtr;
#define ASSIGNCOST(l, r)	((l) = (r))
#define ADDCOST(l, r)		((l) += (r))
#define MINUSCOST(l, r)		((l) -= (r))
#define ZEROCOST(x)		((x) = 0)
#define LESSCOST(l, r)		((l) < (r))
#define EQUALCOST(l, r)		((l) == (r))
#define PRINCIPLECOST(x)	(x)
#endif /* NOLEX */
#define NODIVERGE(c,state,nt,base)		if (prevent_divergence > 0) CHECKDIVERGE(c,state,nt,base);

struct list {
	void		*x;
	struct list	*next;
};
typedef struct list	*List;

struct intlist {
	int		x;
	struct intlist	*next;
};
typedef struct intlist	*IntList;

struct operator {
	char		*name;
	unsigned int	ref:1;
	OperatorNum	num;
	ItemSetNum	baseNum;
	ItemSetNum	stateCount;
	ArityNum	arity;
	struct table	*table;
};
typedef struct operator	*Operator;

struct nonterminal {
	char		*name;
	NonTerminalNum	num;
	ItemSetNum	baseNum;
	ItemSetNum	ruleCount;
	struct plankMap *pmap;

	struct rule	*sampleRule; /* diagnostic---gives "a" rule that with this lhs */
};
typedef struct nonterminal	*NonTerminal;

struct pattern {
	NonTerminal	normalizer;
	Operator	op;		/* NULL if NonTerm -> NonTerm */
	NonTerminal	children[MAX_ARITY];
};
typedef struct pattern	*Pattern;

struct rule {
	DeltaCost	delta;
	ERuleNum	erulenum;
	RuleNum		num;
	RuleNum		newNum;
	NonTerminal	lhs;
	Pattern		pat;
	unsigned int	used:1;
};
typedef struct rule	*Rule;

struct item {
	DeltaCost	delta;
	Rule		rule;
};
typedef struct item	Item;

typedef short 	*Relevant;	/* relevant non-terminals */

typedef Item	*ItemArray;

struct item_set {	/* indexed by NonTerminal */
	ItemSetNum	num;
	ItemSetNum	newNum;
	Operator	op;
	struct item_set *kids[2];
	struct item_set *representative;
	Relevant	relevant;
	ItemArray	virgin;
	ItemArray	closed;
};
typedef struct item_set	*Item_Set;

#define DIM_MAP_SIZE	(1 << 8)
#define GLOBAL_MAP_SIZE	(1 << 15)

struct mapping {	/* should be a hash table for TS -> int */
	List		*hash;
	int		hash_size;
	int		max_size;
	ItemSetNum	count;
	Item_Set	*set;	/* map: int <-> Item_Set */
};
typedef struct mapping	*Mapping;

struct index_map {
	ItemSetNum	max_size;
	Item_Set	*class;
};
typedef struct index_map	Index_Map;

struct dimension {
	Relevant	relevant;
	Index_Map	index_map;
	Mapping		map;
	ItemSetNum	max_size;
	struct plankMap *pmap;
};
typedef struct dimension	*Dimension;


struct table {
	Operator	op;
	List		rules;
	Relevant	relevant;
	Dimension	dimen[MAX_ARITY];	/* 1 for each dimension */
	Item_Set	*transition;	/* maps local indices to global
						itemsets */
};
typedef struct table	*Table;

struct relation {
	Rule	rule;
	DeltaCost	chain;
	NonTerminalNum	nextchain;
	DeltaCost	sibling;
	int		sibFlag;
	int		sibComputed;
};
typedef struct relation	*Relation;

struct queue {
	List head;
	List tail;
};
typedef struct queue	*Queue;

struct plank {
	char *name;
	List fields;
	int width;
};
typedef struct plank	*Plank;

struct except {
	short index;
	short value;
};
typedef struct except	*Exception;

struct plankMap {
	List exceptions;
	int offset;
	struct stateMap *values;
};
typedef struct plankMap	*PlankMap;

struct stateMap {
	char *fieldname;
	Plank plank;
	int width;
	short *value;
};
typedef struct stateMap	*StateMap;

struct stateMapTable {
	List maps;
};

extern void CHECKDIVERGE ARGS((DeltaPtr, Item_Set, int, int));
extern void zero ARGS((Item_Set));
extern ItemArray newItemArray ARGS((void));
extern ItemArray itemArrayCopy ARGS((ItemArray));
extern Item_Set newItem_Set ARGS((Relevant));
extern void freeItem_Set ARGS((Item_Set));
extern Mapping newMapping ARGS((int));
extern NonTerminal newNonTerminal ARGS((char *));
extern int nonTerminalName ARGS((char *, int));
extern Operator newOperator ARGS((char *, OperatorNum, ArityNum));
extern Pattern newPattern ARGS((Operator));
extern Rule newRule ARGS((DeltaPtr, ERuleNum, NonTerminal, Pattern));
extern List newList ARGS((void *, List));
extern IntList newIntList ARGS((int, IntList));
extern int length ARGS((List));
extern List appendList ARGS((void *, List));
extern Table newTable ARGS((Operator));
extern Queue newQ ARGS((void));
extern void addQ ARGS((Queue, Item_Set));
extern Item_Set popQ ARGS((Queue));
extern int equivSet ARGS((Item_Set, Item_Set));
extern Item_Set decode ARGS((Mapping, ItemSetNum));
extern Item_Set encode ARGS((Mapping, Item_Set, int *));
extern void build ARGS((void));
extern Item_Set *transLval ARGS((Table, int, int));

typedef void *	(*ListFn) ARGS((void *));
extern void foreachList ARGS((ListFn, List));
extern void reveachList ARGS((ListFn, List));

extern void addToTable ARGS((Table, Item_Set));

extern void closure ARGS((Item_Set));
extern void trim ARGS((Item_Set));
extern void findChainRules ARGS((void));
extern void findAllPairs ARGS((void));
extern void addRelevant ARGS((Relevant, NonTerminalNum));

extern void *zalloc ARGS((unsigned int));
extern void zfree ARGS((void *));

extern NonTerminal	start;
extern List		rules;
extern List		chainrules;
extern List		operators;
extern List		leaves;
extern List		nonterminals;
extern List		grammarNts;
extern Queue		globalQ;
extern Mapping		globalMap;
extern int		exceptionTolerance;
extern int		prevent_divergence;
extern int		principleCost;
extern int		lexical;
extern struct rule	stub_rule;
extern Relation 	*allpairs;
extern Item_Set		*sortedStates;
extern Item_Set		errorState;

extern void dumpRelevant ARGS((Relevant));
extern void dumpOperator ARGS((Operator, int));
extern void dumpOperator_s ARGS((Operator));
extern void dumpOperator_l ARGS((Operator));
extern void dumpNonTerminal ARGS((NonTerminal));
extern void dumpRule ARGS((Rule));
extern void dumpRuleList ARGS((List));
extern void dumpItem ARGS((Item *));
extern void dumpItem_Set ARGS((Item_Set));
extern void dumpMapping ARGS((Mapping));
extern void dumpQ ARGS((Queue));
extern void dumpIndex_Map ARGS((Index_Map *));
extern void dumpDimension ARGS((Dimension));
extern void dumpPattern ARGS((Pattern));
extern void dumpTable ARGS((Table, int));
extern void dumpTransition ARGS((Table));
extern void dumpCost ARGS((DeltaCost));
extern void dumpAllPairs ARGS((void));
extern void dumpRelation ARGS((Relation));
extern void dumpSortedStates ARGS((void));
extern void dumpSortedRules ARGS((void));
extern int debugTrim;

#ifdef DEBUG
#define debug(a,b)	if (a) b
#else
#define debug(a,b)
#endif
extern int debugTables;

#define TABLE_INCR	8
#define STATES_INCR	64

#ifdef NDEBUG
#define assert(c) ((void) 0)
#else
#define assert(c) ((void) ((c) || fatal(__FILE__,__LINE__)))
#endif

extern void doStart ARGS((char *));
extern void exit ARGS((int));
extern int fatal ARGS((const char *, int));
extern void yyerror ARGS((const char *));
extern void yyerror1 ARGS((const char *));