summaryrefslogtreecommitdiffstats
path: root/poxml/antlr/src/ASTFactory.cpp
blob: 66902522be74b702f18b68e0a2d6203bec69f07e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/**
 * <b>SOFTWARE RIGHTS</b>
 * <p>
 * ANTLR 2.6.0 MageLang Insitute, 1998
 * <p>
 * We reserve no legal rights to the ANTLR--it is fully in the
 * public domain. An individual or company may do whatever
 * they wish with source code distributed with ANTLR or the
 * code generated by ANTLR, including the incorporation of
 * ANTLR, or its output, into commerical software.
 * <p>
 * We encourage users to develop software with ANTLR. However,
 * we do ask that credit is given to us for developing
 * ANTLR. By "credit", we mean that if you use ANTLR or
 * incorporate any source code into one of your programs
 * (commercial product, research project, or otherwise) that
 * you acknowledge this fact somewhere in the documentation,
 * research report, etc... If you like ANTLR and have
 * developed a nice tool with the output, please mention that
 * you developed it using ANTLR. In addition, we ask that the
 * headers remain intact in our source code. As long as these
 * guidelines are kept, we expect to continue enhancing this
 * system and expect to make other tools available as they are
 * completed.
 * <p>
 * The ANTLR gang:
 * @version ANTLR 2.6.0 MageLang Insitute, 1998
 * @author Terence Parr, <a href=http://www.MageLang.com>MageLang Institute</a>
 * @author <br>John Lilley, <a href=http://www.Empathy.com>Empathy Software</a>
 * @author <br><a href="mailto:pete@yamuna.demon.co.uk">Pete Wells</a>
 */

#include "antlr/ASTFactory.hpp"
#include "antlr/CommonAST.hpp"

ANTLR_BEGIN_NAMESPACE(antlr)

/** AST Support code shared by TreeParser and Parser.
 *  We use delegation to share code (and have only one
 *  bit of code to maintain) rather than subclassing
 *  or superclassing (forces AST support code to be
 *  loaded even when you don't want to do AST stuff).
 *
 *  Typically, setASTNodeType is used to specify the
 *  type of node to create, but you can override
 *  create to make heterogeneous nodes etc...
 */

ASTFactory::ASTFactory() : nodeFactory(&CommonAST::factory)
{
}

/** Add a child to the current AST */
void ASTFactory::addASTChild(ASTPair& currentAST, RefAST child)
{
	if (child) {
		if (!currentAST.root) {
			// Make new child the current root
			currentAST.root = child;
		}
		else {
			if (!currentAST.child) {
				// Add new child to current root
				currentAST.root->setFirstChild(child);
			}
			else {
				currentAST.child->setNextSibling(child);
			}
		}
		// Make new child the current child
		currentAST.child = child;
		currentAST.advanceChildToEnd();
	}
}
/** Create a new empty AST node; if the user did not specify
 *  an AST node type, then create a default one: CommonAST.
 */
RefAST ASTFactory::create()
{
	RefAST node = nodeFactory();
	node->setType(Token::INVALID_TYPE);
	return node;
}

RefAST ASTFactory::create(int type)
{
	RefAST t = nodeFactory();
	t->initialize(type,"");
	return t;
}

RefAST ASTFactory::create(int type, const ANTLR_USE_NAMESPACE(std)string& txt)
{
	RefAST t = nodeFactory();
	t->initialize(type,txt);
	return t;
}

/** Create a new empty AST node; if the user did not specify
 *  an AST node type, then create a default one: CommonAST.
 */
RefAST ASTFactory::create(RefAST tr)
{
	if (!tr)
		return nullAST;

	RefAST t = nodeFactory();
	t->initialize(tr);
	return t;
}

RefAST ASTFactory::create(RefToken tok)
{
	RefAST t = nodeFactory();
	t->initialize(tok);
	return t;
}
/** Copy a single node.  clone() is not used because
 *  we want to return an AST not a plain object...a type
 *  safety issue.  Further, we want to have all AST node
 *  creation go through the factory so creation can be
 *  tracked.  Returns null if t is null.
 */
RefAST ASTFactory::dup(RefAST t)
{
	return create(t);		// if t==null, create returns null
}

/** Duplicate tree including siblings of root. */
RefAST ASTFactory::dupList(RefAST t)
{
	RefAST result = dupTree(t);         // if t == null, then result==null
	RefAST nt = result;
	while (t) {									// for each sibling of the root
		t = t->getNextSibling();
		nt->setNextSibling(dupTree(t));	// dup each subtree, building new tree
		nt = nt->getNextSibling();
	}
	return result;
}
/**Duplicate a tree, assuming this is a root node of a tree--
 * duplicate that node and what's below; ignore siblings of root node.
 */
RefAST ASTFactory::dupTree(RefAST t)
{
	RefAST result = dup(t);		// make copy of root
	// copy all tqchildren of root.
	if (t) {
		result->setFirstChild( dupList(t->getFirstChild()) );
	}
	return result;
}
/** Make a tree from a list of nodes.  The first element in the
 *  array is the root.  If the root is null, then the tree is
 *  a simple list not a tree.  Handles null tqchildren nodes correctly.
 *  For example, build(a, b, null, c) yields tree (a b c).  build(null,a,b)
 *  yields tree (nil a b).
 */
RefAST ASTFactory::make(ANTLR_USE_NAMESPACE(std)vector<RefAST> nodes)
{
	if ( nodes.size()==0 )
		return RefAST(nullASTptr);
	RefAST root = nodes[0];
	RefAST tail = RefAST(nullASTptr);
	if (root) {
		root->setFirstChild(RefAST(nullASTptr));	// don't leave any old pointers set
	}
	// link in tqchildren;
	for (unsigned int i=1; i<nodes.size(); i++) {
		if ( !nodes[i] ) continue;	// ignore null nodes
		if ( !root ) {
			// Set the root and set it up for a flat list
			root = tail = nodes[i];
		}
		else if ( !tail ) {
			root->setFirstChild(nodes[i]);
			tail = root->getFirstChild();
		}
		else {
			tail->setNextSibling(nodes[i]);
			tail = tail->getNextSibling();
		}
		// Chase tail to last sibling
		while (tail->getNextSibling()) {
			tail = tail->getNextSibling();
		}
	}
	return root;
}
/** Make a tree from a list of nodes, where the nodes are contained
  * in an ASTArray object
  */
RefAST ASTFactory::make(ASTArray* nodes)
{
	RefAST ret = make(nodes->array);
	delete nodes;
	return ret;
}
/** Make an AST the root of current AST */
void ASTFactory::makeASTRoot(ASTPair& currentAST, RefAST root)
{
	if (root) {
		// Add the current root as a child of new root
		root->addChild(currentAST.root);
		// The new current child is the last sibling of the old root
		currentAST.child = currentAST.root;
		currentAST.advanceChildToEnd();
		// Set the new root
		currentAST.root = root;
	}
}
void ASTFactory::setASTNodeFactory(factory_type factory)
{
	nodeFactory = factory;
}

ANTLR_END_NAMESPACE