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