www.pudn.com > cppcc.rar > ebnf_la_node.hh
/* * File: ebnf_la_node.hh * $Id: ebnf_la_node.hh,v 1.11 2002/06/26 20:46:29 alec Exp $ * * Author: Alec Panovici (alecu@email.com) * * Comments: * * Revision history: * * $Log: ebnf_la_node.hh,v $ * Revision 1.11 2002/06/26 20:46:29 alec * g++ 3.x happy * * Revision 1.10 2002/06/23 23:31:59 alec * la-time usercode (force) * * Revision 1.9 2002/06/13 11:36:52 alec * added #line stuff * * Revision 1.8 2002/06/05 21:32:43 alec * g++ happy * * Revision 1.7 2002/05/31 12:11:08 alec * *** empty log message *** * * Revision 1.6 2002/05/27 03:00:00 alec * doc update * * Revision 1.5 2002/05/22 01:36:19 alec * LOOKAHEAD fixes * * Revision 1.4 2002/05/16 21:34:35 alec * parser generation done * * Revision 1.3 2002/05/10 18:07:58 alec * *** empty log message *** * * Revision 1.2 2002/05/10 07:15:10 alec * parser parse tree ok * * Revision 1.1 2002/05/08 18:17:22 alec * *** empty log message *** * */ /* Copyright (C) 2002 Alexandru Panoviciu (alecu@email.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __EBNF_LA_NODE_HH__ #define __EBNF_LA_NODE_HH__ #include#include using namespace std; #include "ebnf_node.hh" #include "vbitset.hh" #include "numbered_la_spec.hh" #include "catch_clause.hh" class TokenDesc; class ITokenSpec; /** * This class adds to the EbnfNode the stuff needed for generating a LA * parser. */ class EbnfLaNode : public EbnfNode { public: /** * Creates a new EbnfLaNode associated with the given position in the input * file and having the associated (possibly NULL) lookahead specification. */ EbnfLaNode (const Position &pos_, NumberedLaSpec *laSpec_ = NULL) : EbnfNode(pos_), laSpec(laSpec_) {} /** * Copy constructor. It has an in-depth semantics (the lookahead spec, if * any is cloned). */ EbnfLaNode (const EbnfLaNode &o) : EbnfNode(o.getPos()), laSpec(o.laSpec != NULL ? dynamic_cast (o.laSpec->clone()) : NULL), first(o.first), follow(o.follow), nullable(o.nullable), startCode(o.startCode), endCode(o.endCode), forceStartCode(o.forceStartCode), forceEndCode(o.forceEndCode), catchList(o.catchList), colour(o.colour) {} ~EbnfLaNode () { if (laSpec != NULL) delete laSpec; } #ifdef DEBUG protected: static int indent_level; static void indent() { indent_level++; } static void unindent () { indent_level--; } static ostream& format (ostream &os) { for (int i = 0; i < indent_level; i++) os << " "; return os; } void dumpAttributes (ostream &os) const; public: static ITokenSpec *tokens; #endif public: /** * The lookahead associated with this node, if any (can be NULL). */ NumberedLaSpec *laSpec; /** * Contains the user code found before the expansion represented by this * node in the input file. */ CodeChunk startCode; /** * Contains the user code found after the expansion represented by this node in the input file. */ CodeChunk endCode; bool forceStartCode, forceEndCode; /** * Contains any CatchClause objects resulted from the catch constructions * found in the input file after the production represented by this node. */ vector catchList; /** * Contains the FIRST set of terminals for this node. * * \sa EbnfFirstCompAlgo */ vBitset first; /** * Contains the FOLLOW set of terminals for this node. * * \sa EbnfFollowCompAlgo */ vBitset follow; /** * Indicates whether the expansion represented by this node can match an * empty string of tokens. * * \sa EbnfNullableCompAlgo */ bool nullable; /** * During the recursive traversal we use colours to mark visited nodes. */ typedef enum { white, grey, black } Colours; /** * This field is used during recursive traversal of EBNF nodes, which may * reffer to each other. Their meanings are the classical: white : not * visited yet, grey : being visited now, black: already visited. This field * can be (and is) used by the EbnfNodeAlgo implementations in order to * avoid infinite recursion if some productions mutually refer each other. */ Colours colour; }; /** * Represents an expansion obtained by applying the "|" operator to two * other expansions. */ class EbnfOrNode : public EbnfLaNode { public: EbnfOrNode (EbnfLaNode *pre_, EbnfLaNode *post_, const Position &pos_) : EbnfLaNode(pos_), pre(pre_), post(post_) {} EbnfOrNode (const EbnfOrNode &o) : EbnfLaNode(o), pre(dynamic_cast (o.pre->clone())), post(dynamic_cast (o.post->clone())) {} virtual EbnfNode& operator [] (int index) { ASSERT((0 <= index) && (index <= 1), "Bad index in EbnfOrNode::operator []"); return index ? *post : *pre; } virtual EbnfNode* clone () { return new EbnfOrNode(*this); } virtual int getChildCount () { return 2; } virtual ~EbnfOrNode () { delete pre; delete post; } #ifdef DEBUG virtual void dump (ostream &os) const; #endif public: /** * The left operand of the "|" operator in textual order. */ EbnfLaNode *pre; /** * The right operand of the "|" operator in textual order. */ EbnfLaNode *post; }; /** * Represents an expansion obtained from the concatenation of two other * expansions. */ class EbnfCatNode : public EbnfLaNode { public: EbnfCatNode (EbnfLaNode *pre_, EbnfLaNode *post_, const Position &pos_) : EbnfLaNode(pos_), pre(pre_), post(post_) {} EbnfCatNode (const EbnfCatNode &o) : EbnfLaNode(o), pre(dynamic_cast (o.pre->clone())), post(dynamic_cast (o.post->clone())) {} virtual EbnfNode& operator [] (int index) { ASSERT((0 <= index) && (index <= 1), "Bad index in EbnfCatNode::operator []"); return index ? *post : *pre; } virtual int getChildCount () { return 2; } virtual EbnfNode* clone () { return new EbnfCatNode(*this); } virtual ~EbnfCatNode () { delete pre; delete post; } #ifdef DEBUG virtual void dump (ostream &os) const; #endif public: /** * The first part of the concatenation, in textual order. */ EbnfLaNode *pre; /** * the second part of the concatenation, in textual order. */ EbnfLaNode *post; }; /** * Represents an expansion obtained by applying the "*"operator to a nother * expansion. */ class EbnfStarNode : public EbnfLaNode { public: EbnfStarNode (EbnfLaNode *in_, const Position &pos_) : EbnfLaNode(pos_), in(in_) {} EbnfStarNode (const EbnfStarNode &o) : EbnfLaNode(o), in(dynamic_cast (o.in->clone())) {} virtual EbnfNode& operator [] (int index) { ASSERT((0 == index), "Bad index in EbnfStarNode::operator []"); return *in; } virtual int getChildCount () { return 1; } virtual EbnfNode* clone () { return new EbnfStarNode(*this); } virtual ~EbnfStarNode () { delete in; } #ifdef DEBUG virtual void dump (ostream &os) const; #endif public: /** * The operand expansion to which we apply the "*" operator. */ EbnfLaNode *in; }; /** * Represents an expansion that matches whatever another production does. */ class EbnfNonterminalNode : public EbnfLaNode { public: EbnfNonterminalNode (const string &targetVar_, const Position &targetVarPos_, const string &nontermName_, const string &actualArgs_, const Position &argsPos_, const Position &pos_) : EbnfLaNode(pos_), targetVar(targetVarPos_, targetVar_), nontermName(nontermName_), actualArgs(argsPos_, actualArgs_) {} EbnfNonterminalNode (const EbnfNonterminalNode &o) : EbnfLaNode(o), targetVar(o.targetVar), nontermName(o.nontermName), actualArgs(o.actualArgs) {} virtual EbnfNode& operator [] (int index) { ASSERT(0, "EbnfNonterminalNode::operator [] called !"); return * (EbnfNode*) NULL; } virtual int getChildCount () { return 0; } virtual EbnfNode* clone () { return new EbnfNonterminalNode(*this); } #ifdef DEBUG virtual void dump (ostream &os) const; #endif public: /** * If the result of calling the production's method should be stored in a * variable, this field contains the name of that variable, otherwise it * contains an empty string. */ CodeChunk targetVar; /** * The name of the production to call. */ string nontermName; /** * A string containing the C++ list of actual arguments to be passed to the * called production. */ CodeChunk actualArgs; /** * Whis will point to the reffered production's expansion after fixup. BE * careful with this as it is possible to be NULL, if the production that is * refferred has no expansion (eg. pure code productions). */ EbnfLaNode *nonterm; }; /** * Represents an expansion that matches exactly one terminal. */ class EbnfTerminalNode : public EbnfLaNode { public: EbnfTerminalNode (TokenDesc &terminal_, const Position &pos_) : EbnfLaNode(pos_), terminal(terminal_) {} EbnfTerminalNode (const EbnfTerminalNode &o) : EbnfLaNode(o), terminal(o.terminal) {} virtual EbnfNode& operator [] (int index) { ASSERT(0, "EbnfTerminalNode::operator [] called !"); return * (EbnfNode*) NULL; } virtual int getChildCount () { return 0; } virtual EbnfNode* clone () { return new EbnfTerminalNode(*this); } #ifdef DEBUG virtual void dump (ostream &os) const; #endif public: /** * Points to the TokenDesc object that describes the token matched by this * expansion. */ TokenDesc &terminal; }; /** * Represents an expansion that matches nothing. */ class EbnfLambdaNode : public EbnfLaNode { public: EbnfLambdaNode (const Position &pos_) : EbnfLaNode(pos_) {} EbnfLambdaNode (const EbnfLambdaNode &o) : EbnfLaNode(o) {} virtual EbnfNode& operator [] (int index) { ASSERT(0, "EbnfLambdaNode::operator [] called !"); return *(EbnfNode*) NULL; } virtual int getChildCount () { return 0; } virtual EbnfNode* clone () { return new EbnfLambdaNode(*this); } #ifdef DEBUG virtual void dump (ostream &os) const; #endif }; #endif /* #ifndef __EBNF_LA_NODE_HH__ */