// 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 { 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 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 *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 *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 *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 *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