// The ParRule and ParNode classes allow the representation of BNF
// rules.  A rule is denoted by a rule head and associated body
// sequences consisting of a sequence of nodes.

class ParRule;
class ParNode;

// The following classes are specialisations of ParNode and provide
// details of each body constituent.

class ParNonTermNode;
class ParSelectNode;
class ParActionNode;
class ParEndNode;

// The LConfList class is forward-declared.  The processing of the
// internal rule representation produces a cognate list from which
// configuration sets with appropriate transitions are ultimately
// constructed.

class LConfList;

// The ParRuleList class represents a list of ParRule items.  The find()
// member functions allow for searches given rule name.

class ParRuleList : public list<ParRule *> {
public:
	ParRule *find(char *);
};

class ParRule {
public:
	static int RuleId;
	static ParRuleList ruleSet;
	static ParRule *systemRoot;
	static void makeParser();
private:
	int _id;
	char *_name;
	ParNode *_rhs;

	bool _hasDefinition;	// ensures that forward definitions
	bool _isNonTerm;	// are you are terminal or nonterminal
public:
	char *name() { return(_name); }
	int id() { return _id; }
	ParNode *rhs() { return(_rhs); }
	bool hasDefinition() { return _hasDefinition; }
	bool isNonTerm() { return _isNonTerm; }
	void defTerm() {
		_hasDefinition = TRUE; _isNonTerm = FALSE;
	}
	void defn(ParNode *b) {
		_rhs = b; _hasDefinition = TRUE;
	}
	list<ParRule *> starters;
	int maybeEmpty;
	int precedence;
	int associativity;
	char *attributes;
	ParRule(char *n) {
		_name = strdup(n);
		_id = RuleId++;
		_isNonTerm = TRUE;
		_hasDefinition = FALSE;
		maybeEmpty = FALSE;
		_rhs = 0; attributes = 0;
		precedence = associativity = 0;
		ruleSet.append(this);
	}
	void show(FILE *);
};

class ParNode {
	ParNode *_next;
	char *_alias;
public:
	ParNode() { _next = 0; _alias = 0; }
	void nextIs(ParNode *n) { _next = n; }
	void aliasIs(char *n) {
        	_alias = allocate(strlen(n)+1);
        	strcpy(_alias, n);
	}
	char *alias() { return(_alias ? _alias : nontermRule()->name()); }
	ParNode *next() { return(_next); }
	virtual ParNode *inhNode() { return(next()->inhNode()); }
	virtual ParNode *parseItem() { return this; }
	virtual void show(ParNode *, FILE *) {
		error(INTERNAL, "ParNode: show\n");
	}
	virtual ParNode* leadsTo(ParNode *);
	virtual int parseItems() { return(1+next()->parseItems()); }
	virtual int inhItems() { return(next()->inhItems()); }
	virtual void order(int &n) { next()->order(n); }
	virtual int reduceOrder() { return next()->reduceOrder(); }
	virtual ParNode *condNode() { return(next()->condNode()); }
	virtual ParNode *actionNode() { return(next()->actionNode()); }
	virtual ParRule *nontermRule() {
		error(INTERNAL, "ParNode: nontermRule\n");
		return(0);
	}
	virtual int maybeEmpty() { return(next()->maybeEmpty()); }
	virtual void starters(list<ParRule *> *sym) { next()->starters(sym); }
	virtual int precedence() { return(next()->precedence()); }
	virtual int associativity() { return(next()->associativity()); }
	int closure(ParRule *, LConfList *);
	virtual void findClosure(ParRule *, LConfList *) {
		error(INTERNAL, "ParNode: findClosure\n");
	}
};

class ParNonTermNode : public ParNode {
	ParRule *_nonterm;
public:
	ParNonTermNode(ParRule *n) : ParNode() { _nonterm = n; }
	ParRule *nonterm() { return(_nonterm); }
	virtual ParRule* nontermRule() { return nonterm(); }
	virtual int maybeEmpty();
	virtual void starters(list<ParRule *> *sym);
	virtual int precedence();
	virtual int associativity();
	virtual void show(ParNode *, FILE *);
	virtual void findClosure(ParRule *head, LConfList *);
};

class ParSelectNode : public ParNode {
	ParNode *_alt1;
	ParNode *_alt2;
public:
	virtual ParNode *sigItem() {
		error(INTERNAL, "ParSelectNode: sigItem\n");
		return(0);
	}
	virtual ParNode *sigConfig() {
		error(INTERNAL, "ParSelectNode: sigConfig\n");
		return(0);
	}
	ParSelectNode(ParNode* a1, ParNode* a2) : ParNode() {
		_alt1 = a1; _alt2 = a2;
	}
	ParNode *alt1() { return(_alt1); }
	ParNode *alt2() { return(_alt2); }
	virtual void show(ParNode *, FILE *);
	virtual ParNode* leadsTo(ParNode *);
	virtual void order(int &n) { alt1()->order(n); alt2()->order(n); }
	virtual int maybeEmpty() {
		return(alt1()->maybeEmpty() || alt2()->maybeEmpty());
	}
	virtual void starters(list<ParRule *> *sym) {
		alt1()->starters(sym); alt2()->starters(sym);
	}
	virtual void findClosure(ParRule *head, LConfList *);
};

class ParEndNode : public ParNode {
	int declOrder;
	char *_code, *_cond;
public:
	ParEndNode() : ParNode() { _cond = _code = 0; declOrder = 0; }
	ParEndNode(char *p) : ParNode()
	{ _cond = 0; _code = p; declOrder = 0; }
	ParEndNode(char *p, char *p2) : ParNode()
	{ _code = p; _cond = p2; declOrder = 0; }
	char *code() { return _code; }
	char *condCode() { return _cond; }
	virtual ParNode *parseItem() { return 0; }
	virtual void show(ParNode *, FILE *);
	virtual int parseItems() { return 0; }
	virtual int inhItems() { return(0); }
	virtual void order(int &n) { declOrder = n++; }
	virtual int reduceOrder() { return declOrder; }
	virtual ParNode *actionNode() { return(_code ? this : 0); }
	virtual ParNode *condNode() { return(_cond ? this : 0); }
	virtual ParNode *leadsTo(ParNode *);
	virtual int maybeEmpty() { return TRUE; }
	virtual void starters(list<ParRule *> *sym) { }
	virtual int precedence() { return(0); }
	virtual int associativity() { return(0); }
	virtual void findClosure(ParRule *head, LConfList *);
};

class ParActionNode : public ParNode {
	char *_code;
	ParRule *genName;
public:
	ParActionNode(char *p) : ParNode() { _code = p; genName = 0; }
	virtual ParNode *inhNode() { return this; }
	char *code() { return _code; }
	virtual ParRule* nontermRule();
	virtual ParNode *parseItem() { return(next()->parseItem()); }
	virtual int inhItems() { return(1+next()->inhItems()); }
	virtual void show(ParNode *, FILE *);
	virtual void findClosure(ParRule *head, LConfList *l);
};

class InhMarker : public ParRule {
public:
	ParNode *context;
	InhMarker(char *n, ParNode *c) : ParRule(n) { context = c; }
};

#define	SYSROOT "%SYSTEM_ROOT%"
#define	SYSEOF "%EOF_MARK%"

#define ASSOC_LEFT	1
#define ASSOC_RIGHT	2
#define ASSOC_NONE	3


syntax highlighted by Code2HTML, v. 0.9.1