ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/antlr/BaseAST.cpp
Revision: 2469
Committed: Fri Dec 2 15:38:03 2005 UTC (18 years, 7 months ago) by tim
File size: 6754 byte(s)
Log Message:
End of the Link --> List
Return of the Oject-Oriented
replace yacc/lex parser with antlr parser

File Contents

# User Rev Content
1 tim 2469 /* ANTLR Translator Generator
2     * Project led by Terence Parr at http://www.jGuru.com
3     * Software rights: http://www.antlr.org/license.html
4     *
5     * $Id: BaseAST.cpp,v 1.1 2005-12-02 15:38:02 tim Exp $
6     */
7    
8     #include <iostream>
9    
10     #include "antlr/config.hpp"
11     #include "antlr/AST.hpp"
12     #include "antlr/BaseAST.hpp"
13    
14     ANTLR_USING_NAMESPACE(std)
15     #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
16     namespace antlr {
17     #endif
18    
19     const char* const BaseAST::TYPE_NAME = "BaseAST";
20    
21     size_t BaseAST::getNumberOfChildren() const
22     {
23     RefBaseAST t = this->down;
24     size_t n = 0;
25     if( t )
26     {
27     n = 1;
28     while( t->right )
29     {
30     t = t->right;
31     n++;
32     }
33     return n;
34     }
35     return n;
36     }
37    
38     void BaseAST::doWorkForFindAll(
39     ANTLR_USE_NAMESPACE(std)vector<RefAST>& v,
40     RefAST target,bool partialMatch)
41     {
42     // Start walking sibling lists, looking for matches.
43     for (RefAST sibling=this;
44     sibling;
45     sibling=sibling->getNextSibling())
46     {
47     if ( (partialMatch && sibling->equalsTreePartial(target)) ||
48     (!partialMatch && sibling->equalsTree(target)) ) {
49     v.push_back(sibling);
50     }
51     // regardless of match or not, check any children for matches
52     if ( sibling->getFirstChild() ) {
53     RefBaseAST(sibling->getFirstChild())->doWorkForFindAll(v, target, partialMatch);
54     }
55     }
56     }
57    
58     /** Is t an exact structural and equals() match of this tree. The
59     * 'this' reference is considered the start of a sibling list.
60     */
61     bool BaseAST::equalsList(RefAST t) const
62     {
63     // the empty tree is not a match of any non-null tree.
64     if (!t)
65     return false;
66    
67     // Otherwise, start walking sibling lists. First mismatch, return false.
68     RefAST sibling=this;
69     for (;sibling && t;
70     sibling=sibling->getNextSibling(), t=t->getNextSibling()) {
71     // as a quick optimization, check roots first.
72     if (!sibling->equals(t))
73     return false;
74     // if roots match, do full list match test on children.
75     if (sibling->getFirstChild()) {
76     if (!sibling->getFirstChild()->equalsList(t->getFirstChild()))
77     return false;
78     }
79     // sibling has no kids, make sure t doesn't either
80     else if (t->getFirstChild())
81     return false;
82     }
83    
84     if (!sibling && !t)
85     return true;
86    
87     // one sibling list has more than the other
88     return false;
89     }
90    
91     /** Is 'sub' a subtree of this list?
92     * The siblings of the root are NOT ignored.
93     */
94     bool BaseAST::equalsListPartial(RefAST sub) const
95     {
96     // the empty tree is always a subset of any tree.
97     if (!sub)
98     return true;
99    
100     // Otherwise, start walking sibling lists. First mismatch, return false.
101     RefAST sibling=this;
102     for (;sibling && sub;
103     sibling=sibling->getNextSibling(), sub=sub->getNextSibling()) {
104     // as a quick optimization, check roots first.
105     if (!sibling->equals(sub))
106     return false;
107     // if roots match, do partial list match test on children.
108     if (sibling->getFirstChild())
109     if (!sibling->getFirstChild()->equalsListPartial(sub->getFirstChild()))
110     return false;
111     }
112    
113     if (!sibling && sub)
114     // nothing left to match in this tree, but subtree has more
115     return false;
116    
117     // either both are null or sibling has more, but subtree doesn't
118     return true;
119     }
120    
121     /** Is tree rooted at 'this' equal to 't'? The siblings
122     * of 'this' are ignored.
123     */
124     bool BaseAST::equalsTree(RefAST t) const
125     {
126     // check roots first
127     if (!equals(t))
128     return false;
129     // if roots match, do full list match test on children.
130     if (getFirstChild()) {
131     if (!getFirstChild()->equalsList(t->getFirstChild()))
132     return false;
133     }
134     // sibling has no kids, make sure t doesn't either
135     else if (t->getFirstChild())
136     return false;
137    
138     return true;
139     }
140    
141     /** Is 'sub' a subtree of the tree rooted at 'this'? The siblings
142     * of 'this' are ignored.
143     */
144     bool BaseAST::equalsTreePartial(RefAST sub) const
145     {
146     // the empty tree is always a subset of any tree.
147     if (!sub)
148     return true;
149    
150     // check roots first
151     if (!equals(sub))
152     return false;
153     // if roots match, do full list partial match test on children.
154     if (getFirstChild())
155     if (!getFirstChild()->equalsListPartial(sub->getFirstChild()))
156     return false;
157    
158     return true;
159     }
160    
161     /** Walk the tree looking for all exact subtree matches. Return
162     * an ASTEnumerator that lets the caller walk the list
163     * of subtree roots found herein.
164     */
165     ANTLR_USE_NAMESPACE(std)vector<RefAST> BaseAST::findAll(RefAST target)
166     {
167     ANTLR_USE_NAMESPACE(std)vector<RefAST> roots;
168    
169     // the empty tree cannot result in an enumeration
170     if (target) {
171     doWorkForFindAll(roots,target,false); // find all matches recursively
172     }
173    
174     return roots;
175     }
176    
177     /** Walk the tree looking for all subtrees. Return
178     * an ASTEnumerator that lets the caller walk the list
179     * of subtree roots found herein.
180     */
181     ANTLR_USE_NAMESPACE(std)vector<RefAST> BaseAST::findAllPartial(RefAST target)
182     {
183     ANTLR_USE_NAMESPACE(std)vector<RefAST> roots;
184    
185     // the empty tree cannot result in an enumeration
186     if (target)
187     doWorkForFindAll(roots,target,true); // find all matches recursively
188    
189     return roots;
190     }
191    
192     ANTLR_USE_NAMESPACE(std)string BaseAST::toStringList() const
193     {
194     ANTLR_USE_NAMESPACE(std)string ts="";
195    
196     if (getFirstChild())
197     {
198     ts+=" ( ";
199     ts+=toString();
200     ts+=getFirstChild()->toStringList();
201     ts+=" )";
202     }
203     else
204     {
205     ts+=" ";
206     ts+=toString();
207     }
208    
209     if (getNextSibling())
210     ts+=getNextSibling()->toStringList();
211    
212     return ts;
213     }
214    
215     ANTLR_USE_NAMESPACE(std)string BaseAST::toStringTree() const
216     {
217     ANTLR_USE_NAMESPACE(std)string ts = "";
218    
219     if (getFirstChild())
220     {
221     ts+=" ( ";
222     ts+=toString();
223     ts+=getFirstChild()->toStringList();
224     ts+=" )";
225     }
226     else
227     {
228     ts+=" ";
229     ts+=toString();
230     }
231     return ts;
232     }
233    
234     #ifdef ANTLR_SUPPORT_XML
235     /* This whole XML output stuff needs a little bit more thought
236     * I'd like to store extra XML data in the node. e.g. for custom ast's
237     * with for instance symboltable references. This
238     * should be more pluggable..
239     * @returns boolean value indicating wether a closetag should be produced.
240     */
241     bool BaseAST::attributesToStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const
242     {
243     out << "text=\"" << this->getText()
244     << "\" type=\"" << this->getType() << "\"";
245    
246     return false;
247     }
248    
249     void BaseAST::toStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const
250     {
251     for( RefAST node = this; node != 0; node = node->getNextSibling() )
252     {
253     out << "<" << this->typeName() << " ";
254    
255     // Write out attributes and if there is extra data...
256     bool need_close_tag = node->attributesToStream( out );
257    
258     if( need_close_tag )
259     {
260     // got children so write them...
261     if( node->getFirstChild() != 0 )
262     node->getFirstChild()->toStream( out );
263    
264     // and a closing tag..
265     out << "</" << node->typeName() << ">" << endl;
266     }
267     }
268     }
269     #endif
270    
271     // this is nasty, but it makes the code generation easier
272     ANTLR_API RefAST nullAST;
273    
274     #if defined(_MSC_VER) && !defined(__ICL) // Microsoft Visual C++
275     extern ANTLR_API AST* const nullASTptr = 0;
276     #else
277     ANTLR_API AST* const nullASTptr = 0;
278     #endif
279    
280     #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
281     }
282     #endif