// The following LexRule and LexNode classes allow for rule // representation in LexGen. class LexRule; class LexNode; // The processing of the internal representation generates an FSA with // nodes represented as fsaState instances. The fsaState class is // currently forward defined and will be elaborated subsequently. class fsaState; // LexRuleList is a list of LexRule pointers for organising rules into a // collection. class LexRuleList : public list { public: LexRule *find(char *); }; // The LexRule class allows for the representation of rules. Each rule // has a rule name and a definition which consist of a sequence of // LexNode instances. // The _hasDefinition flag indicates whether the rule has an appropriate // definition and is not just forward defined. The _isIgnored flag // indicates rules which are considered as whitespaces and comments. // These must be recognised in the generated lexer, but are not // significant in terms of tokens returned. On ther other hand, the // _isToken flag indicates that the rule should result in a final state // in the generated lexer. The _filter reference contains the code // block to be invoked when the rule is recognised. This allows for // extra flexiblity when additional processing is required. class LexRule { public: static LexRuleList ruleSet; private: char *_name; LexNode *_body; bool _hasDefinition; bool _isIgnored; bool _isToken; char *_filter; public: void defn(LexNode *b) { if (hasDefinition()) error(ERROR, "`%s' has been redefined\n", name()); _body = b; _hasDefinition = TRUE; } char *name() { return _name; } LexNode *body() { return _body; } bool hasDefinition() { return _hasDefinition; } bool isIgnored() { return _isIgnored; } bool isToken() { return _isToken; } void ignored() { _isIgnored = TRUE; } void token() { _isToken = TRUE; } char *filter() { return _filter; } void filterIs(char *f) { _filter = f; } LexRule(char *); fsaState *process(fsaState *); }; // The LexNode abstract class merely contains a reference to another // node for sequence representation, as well as a stub process() // specification for generating the equivalent FSA. LexNodeTermNode, // LexCharNode, LexSelectNode and LexRepeatNode class definitions are // derived from LexNode. class LexNode { public: LexNode *next; LexNode() { next = 0; } virtual fsaState *process(fsaState *); }; class LexNonTermNode : public LexNode { LexRule *_nonterm; public: LexRule *nonterm() { return _nonterm; } LexNonTermNode(LexRule *r) { _nonterm = r; } fsaState *process(fsaState *); }; class LexCharNode : public LexNode { char _ch1, _ch2; public: char ch1() { return _ch1; } char ch2() { return _ch2; } LexCharNode(char c) : LexNode() { _ch1 = _ch2 = c; } LexCharNode(char c1, char c2) : LexNode() { _ch1 = c1; _ch2 = c2; } fsaState *process(fsaState *); }; class LexSelectNode : public LexNode { LexNode *_alt1; LexNode *_alt2; public: LexNode *alt1() { return _alt1; } LexNode *alt2() { return _alt2; } LexSelectNode(LexNode *a1, LexNode *a2) : LexNode() { _alt1 = a1; _alt2 = a2; } fsaState *process(fsaState *); }; class LexRepeatNode : public LexNode { LexNode *_repetition; LexNode *_separator; bool _atLeastOne; public: LexNode *repetition() { return _repetition; } LexNode *separator() { return _separator; } bool atLeastOne() { return _atLeastOne; } LexRepeatNode(LexNode *rep, LexNode *sep, bool v) : LexNode() { _repetition = rep; _separator = sep; _atLeastOne = v; } fsaState *process(fsaState *); };