1 /* class.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2009 */
2 
3 /*
4 
5 Copyright (c) 2005-2009 Made to Order Software Corp.
6 
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16 
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31 
32 */
33 
34 #include	"parser.h"
35 
36 
37 namespace sswf
38 {
39 namespace as
40 {
41 
42 
43 /**********************************************************************/
44 /**********************************************************************/
45 /***  PARSER CLASS  ***************************************************/
46 /**********************************************************************/
47 /**********************************************************************/
48 
Class(NodePtr & node,node_t type)49 void IntParser::Class(NodePtr& node, node_t type)
50 {
51 	if(f_data.f_type != NODE_IDENTIFIER) {
52 		f_lexer.ErrMsg(AS_ERR_INVALID_CLASS, "the name of the class is expected after the keyword 'class'");
53 		return;
54 	}
55 
56 	node.CreateNode(type);
57 	node.SetInputInfo(f_lexer.GetInput());
58 
59 	// *** NAME ***
60 	Data& data = node.GetData();
61 	data.f_str = f_data.f_str;
62 	GetToken();
63 
64 	// *** INHERITANCE ***
65 	while(f_data.f_type == NODE_EXTENDS
66 			|| f_data.f_type == NODE_IMPLEMENTS) {
67 		NodePtr inherits;
68 		inherits.CreateNode(f_data.f_type);
69 		inherits.SetInputInfo(f_lexer.GetInput());
70 		node.AddChild(inherits);
71 
72 		GetToken();
73 
74 		NodePtr expr;
75 		Expression(expr);
76 		inherits.AddChild(expr);
77 		// TODO: EXTENDS and IMPLEMENTS don't accept assignments.
78 		// TODO: EXTENDS doesn't accept lists.
79 		//	 We need to test for that here.
80 	}
81 	// TODO: note that we only can accept one EXTENDS and
82 	//	 one IMPLEMENTS in that order. We need to check
83 	//	 that here. [that's according to the spec. is
84 	//	 that really important?]
85 
86 	if(f_data.f_type == '{') {
87 		GetToken();
88 
89 		// *** DECLARATION ***
90 		if(f_data.f_type != '}') {
91 			NodePtr directive_list;
92 			DirectiveList(directive_list);
93 			node.AddChild(directive_list);
94 		}
95 
96 		if(f_data.f_type == '}') {
97 			GetToken();
98 		}
99 		else {
100 			f_lexer.ErrMsg(AS_ERR_CURVLY_BRAKETS_EXPECTED, "'}' expected to close the 'class' definition");
101 		}
102 	}
103 	else if(f_data.f_type != ';') {	// accept empty class definitions (for typedef's and forward declaration)
104 		f_lexer.ErrMsg(AS_ERR_CURVLY_BRAKETS_EXPECTED, "'{' expected to start the 'class' definition");
105 	}
106 }
107 
108 
109 
110 
111 /**********************************************************************/
112 /**********************************************************************/
113 /***  PARSER ENUM  ****************************************************/
114 /**********************************************************************/
115 /**********************************************************************/
116 
Enum(NodePtr & node)117 void IntParser::Enum(NodePtr& node)
118 {
119 	node.CreateNode(NODE_ENUM);
120 	node.SetInputInfo(f_lexer.GetInput());
121 
122 	// enumerations can be unamed
123 	if(f_data.f_type == NODE_IDENTIFIER) {
124 		Data& data = node.GetData();
125 		data.f_str = f_data.f_str;
126 		GetToken();
127 	}
128 
129 	// in case the name was not specified, we can still have a type (?)
130 	if(f_data.f_type == ':') {
131 		NodePtr type;
132 		Expression(type);
133 		node.AddChild(type);
134 	}
135 
136 	if(f_data.f_type != '{') {
137 		if(f_data.f_type == ';') {
138 			// empty enumeration
139 			return;
140 		}
141 		f_lexer.ErrMsg(AS_ERR_CURVLY_BRAKETS_EXPECTED, "'{' expected to start the 'enum' definition");
142 		return;
143 	}
144 
145 	GetToken();
146 
147 	Data previous;
148 	previous.f_type = NODE_NULL;
149 	while(f_data.f_type != '}' && f_data.f_type != NODE_EOF) {
150 		if(f_data.f_type == ',') {
151 			// TODO: should we warn here?
152 			GetToken();
153 			continue;
154 		}
155 		String current_name = "null";
156 		NodePtr entry;
157 		entry.CreateNode(NODE_VARIABLE);
158 		entry.SetInputInfo(f_lexer.GetInput());
159 		node.AddChild(entry);
160 		if(f_data.f_type == NODE_IDENTIFIER) {
161 			f_data.f_type = NODE_VARIABLE;
162 			f_data.f_int.Set(NODE_VAR_FLAG_CONST | NODE_VAR_FLAG_ENUM);
163 			entry.SetData(f_data);
164 			current_name = f_data.f_str;
165 			GetToken();
166 		}
167 		else {
168 			f_lexer.ErrMsg(AS_ERR_INVALID_ENUM, "each 'enum' entry needs to include an identifier");
169 		}
170 		NodePtr expr;
171 		if(f_data.f_type == '=') {
172 			GetToken();
173 			ConditionalExpression(expr, false);
174 		}
175 		else if(previous.f_type == NODE_NULL) {
176 			// very first time
177 			expr.CreateNode();
178 			expr.SetInputInfo(f_lexer.GetInput());
179 			Data set_zero;
180 			set_zero.f_type = NODE_INT64;
181 			set_zero.f_int.Set(0);
182 			expr.SetData(set_zero);
183 		}
184 		else {
185 			expr.CreateNode(NODE_ADD);
186 			expr.SetInputInfo(f_lexer.GetInput());
187 			NodePtr left;
188 			left.CreateNode();
189 			left.SetInputInfo(f_lexer.GetInput());
190 			left.SetData(previous);
191 			expr.AddChild(left);
192 			NodePtr one;
193 			one.CreateNode();
194 			one.SetInputInfo(f_lexer.GetInput());
195 			Data set_one;
196 			set_one.f_type = NODE_INT64;
197 			set_one.f_int.Set(1);
198 			one.SetData(set_one);
199 			expr.AddChild(one);
200 		}
201 
202 		NodePtr set;
203 		set.CreateNode(NODE_SET);
204 		set.SetInputInfo(f_lexer.GetInput());
205 		set.AddChild(expr);
206 		entry.AddChild(set);
207 
208 		previous.f_type = NODE_IDENTIFIER;
209 		previous.f_str = current_name;
210 
211 		if(f_data.f_type == ',') {
212 			GetToken();
213 		}
214 		else if(f_data.f_type != '}') {
215 			f_lexer.ErrMsg(AS_ERR_CURVLY_BRAKETS_EXPECTED, "',' expected between enumeration elements");
216 		}
217 	}
218 
219 	if(f_data.f_type == '}') {
220 		GetToken();
221 	}
222 	else {
223 		f_lexer.ErrMsg(AS_ERR_CURVLY_BRAKETS_EXPECTED, "'}' expected to close the 'enum' definition");
224 	}
225 }
226 
227 
228 
229 
230 };	// namespace as
231 };	// namespace sswf
232