1 /* expression.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 EXPRESSION  **********************************************/
46 /**********************************************************************/
47 /**********************************************************************/
48 
Expression(NodePtr & node)49 void IntParser::Expression(NodePtr& node)
50 {
51 	ListExpression(node, false, false);
52 }
53 
54 
ListExpression(NodePtr & node,bool rest,bool empty)55 void IntParser::ListExpression(NodePtr& node, bool rest, bool empty)
56 {
57 	if(empty && f_data.f_type == ',') {
58 		node.CreateNode(NODE_EMPTY);
59 		node.SetInputInfo(f_lexer.GetInput());
60 	}
61 	else {
62 		AssignmentExpression(node);
63 		// accept named parameters
64 		if(f_data.f_type == ':' && rest) {
65 			GetToken();
66 			NodePtr name;
67 			name.CreateNode(NODE_NAME);
68 			name.SetInputInfo(f_lexer.GetInput());
69 			name.AddChild(node);
70 			AssignmentExpression(node);
71 			node.AddChild(name);
72 		}
73 	}
74 
75 	if(f_data.f_type == ',') {
76 		NodePtr item = node;
77 
78 		node.CreateNode(NODE_LIST);
79 		node.SetInputInfo(f_lexer.GetInput());
80 
81 		node.AddChild(item);
82 
83 		int has_rest = 0;
84 		while(f_data.f_type == ',') {
85 			GetToken();
86 			if(has_rest == 1) {
87 				f_lexer.ErrMsg(AS_ERR_INVALID_REST, "'...' was expected to be the last expression only");
88 				has_rest = 2;
89 			}
90 			if(empty && f_data.f_type == ',') {
91 				NodePtr empty;
92 				empty.CreateNode(NODE_EMPTY);
93 				empty.SetInputInfo(f_lexer.GetInput());
94 				node.AddChild(empty);
95 			}
96 			else if(rest && f_data.f_type == NODE_REST) {
97 				NodePtr rest;
98 				rest.CreateNode(NODE_REST);
99 				rest.SetInputInfo(f_lexer.GetInput());
100 				node.AddChild(rest);
101 				GetToken();
102 				if(has_rest == 0) {
103 					has_rest = 1;
104 				}
105 				// note: we expect ')' here but we
106 				// let the user put ',' <expr> still
107 			}
108 			else {
109 				AssignmentExpression(item);
110 				// accept named parameters
111 				if(f_data.f_type == ':' && rest) {
112 					GetToken();
113 					NodePtr name;
114 					name.CreateNode(NODE_NAME);
115 					name.SetInputInfo(f_lexer.GetInput());
116 					name.AddChild(item);
117 					if(f_data.f_type == NODE_REST) {
118 						item.CreateNode(NODE_REST);
119 						item.SetInputInfo(f_lexer.GetInput());
120 						GetToken();
121 						if(has_rest == 0) {
122 							has_rest = 1;
123 						}
124 						// note: we expect ')' here but we
125 						// let the user put ',' <expr> still
126 					}
127 					else {
128 						AssignmentExpression(item);
129 					}
130 					item.AddChild(name);
131 				}
132 				node.AddChild(item);
133 			}
134 		}
135 
136 		// TODO: check that the list ends with a NODE_REST
137 	}
138 }
139 
140 
AssignmentExpression(NodePtr & node)141 void IntParser::AssignmentExpression(NodePtr& node)
142 {
143 	ConditionalExpression(node, true);
144 
145 	// TODO: check that the result is a postfix expression
146 	switch(f_data.f_type) {
147 	case '=':	// NODE_ASSIGNMENT
148 	case NODE_ASSIGNMENT_ADD:
149 	case NODE_ASSIGNMENT_BITWISE_AND:
150 	case NODE_ASSIGNMENT_BITWISE_OR:
151 	case NODE_ASSIGNMENT_BITWISE_XOR:
152 	case NODE_ASSIGNMENT_DIVIDE:
153 	case NODE_ASSIGNMENT_LOGICAL_AND:
154 	case NODE_ASSIGNMENT_LOGICAL_OR:
155 	case NODE_ASSIGNMENT_LOGICAL_XOR:
156 	case NODE_ASSIGNMENT_MAXIMUM:
157 	case NODE_ASSIGNMENT_MINIMUM:
158 	case NODE_ASSIGNMENT_MODULO:
159 	case NODE_ASSIGNMENT_MULTIPLY:
160 	case NODE_ASSIGNMENT_POWER:
161 	case NODE_ASSIGNMENT_ROTATE_LEFT:
162 	case NODE_ASSIGNMENT_ROTATE_RIGHT:
163 	case NODE_ASSIGNMENT_SHIFT_LEFT:
164 	case NODE_ASSIGNMENT_SHIFT_RIGHT:
165 	case NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
166 	case NODE_ASSIGNMENT_SUBTRACT:
167 		break;
168 
169 	default:
170 		return;
171 
172 	}
173 
174 	NodePtr left = node;
175 
176 	node.CreateNode(f_data.f_type);
177 	node.SetInputInfo(f_lexer.GetInput());
178 
179 	GetToken();
180 	NodePtr right;
181 	AssignmentExpression(right);
182 
183 	node.AddChild(left);
184 	node.AddChild(right);
185 }
186 
187 
ConditionalExpression(NodePtr & node,bool assignment)188 void IntParser::ConditionalExpression(NodePtr& node, bool assignment)
189 {
190 	MinMaxExpression(node);
191 
192 	if(f_data.f_type == '?') {
193 		NodePtr condition = node;
194 
195 		node.CreateNode(NODE_CONDITIONAL);
196 		node.SetInputInfo(f_lexer.GetInput());
197 		node.AddChild(condition);
198 
199 		GetToken();
200 		NodePtr left;
201 		// not like C/C++, not a list expression here
202 		if(assignment) {
203 			AssignmentExpression(left);
204 		}
205 		else {
206 			ConditionalExpression(left, false);
207 		}
208 		node.AddChild(left);
209 
210 		if(f_data.f_type == ':') {
211 			GetToken();
212 			NodePtr right;
213 			if(assignment) {
214 				AssignmentExpression(right);
215 			}
216 			else {
217 				ConditionalExpression(right, false);
218 			}
219 			node.AddChild(right);
220 		}
221 		else {
222 			f_lexer.ErrMsg(AS_ERR_INVALID_CONDITIONAL, "invalid use of the conditional operator, ':' was expected");
223 		}
224 	}
225 }
226 
227 
228 
MinMaxExpression(NodePtr & node)229 void IntParser::MinMaxExpression(NodePtr& node)
230 {
231 	LogicalOrExpression(node);
232 
233 	while(f_data.f_type == NODE_MINIMUM
234 	|| f_data.f_type == NODE_MAXIMUM) {
235 		NodePtr left = node;
236 
237 		node.CreateNode(f_data.f_type);
238 		node.SetInputInfo(f_lexer.GetInput());
239 
240 		GetToken();
241 		NodePtr right;
242 		LogicalOrExpression(right);
243 
244 		node.AddChild(left);
245 		node.AddChild(right);
246 	}
247 }
248 
249 
LogicalOrExpression(NodePtr & node)250 void IntParser::LogicalOrExpression(NodePtr& node)
251 {
252 	LogicalXOrExpression(node);
253 
254 	while(f_data.f_type == NODE_LOGICAL_OR) {
255 		NodePtr left = node;
256 
257 		node.CreateNode(NODE_LOGICAL_OR);
258 		node.SetInputInfo(f_lexer.GetInput());
259 
260 		GetToken();
261 		NodePtr right;
262 		LogicalXOrExpression(right);
263 
264 		node.AddChild(left);
265 		node.AddChild(right);
266 	}
267 }
268 
269 
LogicalXOrExpression(NodePtr & node)270 void IntParser::LogicalXOrExpression(NodePtr& node)
271 {
272 	LogicalAndExpression(node);
273 
274 	while(f_data.f_type == NODE_LOGICAL_XOR) {
275 		NodePtr left = node;
276 
277 		node.CreateNode(NODE_LOGICAL_XOR);
278 		node.SetInputInfo(f_lexer.GetInput());
279 
280 		GetToken();
281 		NodePtr right;
282 		LogicalAndExpression(right);
283 
284 		node.AddChild(left);
285 		node.AddChild(right);
286 	}
287 }
288 
289 
LogicalAndExpression(NodePtr & node)290 void IntParser::LogicalAndExpression(NodePtr& node)
291 {
292 	BitwiseOrExpression(node);
293 
294 	while(f_data.f_type == NODE_LOGICAL_AND) {
295 		NodePtr left = node;
296 
297 		node.CreateNode(NODE_LOGICAL_AND);
298 		node.SetInputInfo(f_lexer.GetInput());
299 
300 		GetToken();
301 		NodePtr right;
302 		BitwiseOrExpression(right);
303 
304 		node.AddChild(left);
305 		node.AddChild(right);
306 	}
307 }
308 
309 
310 
BitwiseOrExpression(NodePtr & node)311 void IntParser::BitwiseOrExpression(NodePtr& node)
312 {
313 	BitwiseXOrExpression(node);
314 
315 	while(f_data.f_type == '|') {
316 		NodePtr left = node;
317 
318 		node.CreateNode(NODE_BITWISE_OR);
319 		node.SetInputInfo(f_lexer.GetInput());
320 
321 		GetToken();
322 		NodePtr right;
323 		BitwiseXOrExpression(right);
324 
325 		node.AddChild(left);
326 		node.AddChild(right);
327 	}
328 }
329 
330 
BitwiseXOrExpression(NodePtr & node)331 void IntParser::BitwiseXOrExpression(NodePtr& node)
332 {
333 	BitwiseAndExpression(node);
334 
335 	while(f_data.f_type == '^') {
336 		NodePtr left = node;
337 
338 		node.CreateNode(NODE_BITWISE_XOR);
339 		node.SetInputInfo(f_lexer.GetInput());
340 
341 		GetToken();
342 		NodePtr right;
343 		BitwiseAndExpression(right);
344 
345 		node.AddChild(left);
346 		node.AddChild(right);
347 	}
348 }
349 
350 
BitwiseAndExpression(NodePtr & node)351 void IntParser::BitwiseAndExpression(NodePtr& node)
352 {
353 	EqualityExpression(node);
354 
355 	while(f_data.f_type == '&') {
356 		NodePtr left = node;
357 
358 		node.CreateNode(NODE_BITWISE_AND);
359 		node.SetInputInfo(f_lexer.GetInput());
360 
361 		GetToken();
362 		NodePtr right;
363 		EqualityExpression(right);
364 
365 		node.AddChild(left);
366 		node.AddChild(right);
367 	}
368 }
369 
370 
EqualityExpression(NodePtr & node)371 void IntParser::EqualityExpression(NodePtr& node)
372 {
373 	RelationalExpression(node);
374 
375 	while(f_data.f_type == NODE_EQUAL
376 	|| f_data.f_type == NODE_NOT_EQUAL
377 	|| f_data.f_type == NODE_STRICTLY_EQUAL
378 	|| f_data.f_type == NODE_STRICTLY_NOT_EQUAL) {
379 		NodePtr left = node;
380 
381 		node.CreateNode(f_data.f_type);
382 		node.SetInputInfo(f_lexer.GetInput());
383 
384 		GetToken();
385 		NodePtr right;
386 		RelationalExpression(right);
387 
388 		node.AddChild(left);
389 		node.AddChild(right);
390 	}
391 }
392 
393 
RelationalExpression(NodePtr & node)394 void IntParser::RelationalExpression(NodePtr& node)
395 {
396 	ShiftExpression(node);
397 
398 	while(f_data.f_type == NODE_LESS
399 	|| f_data.f_type == NODE_GREATER
400 	|| f_data.f_type == NODE_LESS_EQUAL
401 	|| f_data.f_type == NODE_GREATER_EQUAL
402 	|| f_data.f_type == NODE_IS
403 	|| f_data.f_type == NODE_AS
404 	|| f_data.f_type == NODE_MATCH
405 	|| f_data.f_type == NODE_IN
406 	|| f_data.f_type == NODE_INSTANCEOF) {
407 		NodePtr left = node;
408 
409 		node_t type = f_data.f_type;
410 		node.CreateNode(type);
411 		node.SetInputInfo(f_lexer.GetInput());
412 
413 		GetToken();
414 		NodePtr right;
415 		ShiftExpression(right);
416 
417 		node.AddChild(left);
418 		node.AddChild(right);
419 
420 		if(type == NODE_IN
421 		&& (f_data.f_type == NODE_RANGE || f_data.f_type == NODE_REST)) {
422 			GetToken();
423 			ShiftExpression(right);
424 			node.AddChild(right);
425 		}
426 	}
427 }
428 
429 
ShiftExpression(NodePtr & node)430 void IntParser::ShiftExpression(NodePtr& node)
431 {
432 	AdditiveExpression(node);
433 
434 	while(f_data.f_type == NODE_SHIFT_LEFT
435 	|| f_data.f_type == NODE_SHIFT_RIGHT
436 	|| f_data.f_type == NODE_SHIFT_RIGHT_UNSIGNED
437 	|| f_data.f_type == NODE_ROTATE_LEFT
438 	|| f_data.f_type == NODE_ROTATE_RIGHT) {
439 		NodePtr left = node;
440 
441 		node.CreateNode(f_data.f_type);
442 		node.SetInputInfo(f_lexer.GetInput());
443 
444 		GetToken();
445 		NodePtr right;
446 		AdditiveExpression(right);
447 
448 		node.AddChild(left);
449 		node.AddChild(right);
450 	}
451 }
452 
453 
AdditiveExpression(NodePtr & node)454 void IntParser::AdditiveExpression(NodePtr& node)
455 {
456 	MultiplicativeExpression(node);
457 
458 	while(f_data.f_type == '+'
459 	|| f_data.f_type == '-') {
460 		NodePtr left = node;
461 
462 		node.CreateNode(f_data.f_type);
463 		node.SetInputInfo(f_lexer.GetInput());
464 
465 		GetToken();
466 		NodePtr right;
467 		MultiplicativeExpression(right);
468 
469 		node.AddChild(left);
470 		node.AddChild(right);
471 	}
472 }
473 
474 
MultiplicativeExpression(NodePtr & node)475 void IntParser::MultiplicativeExpression(NodePtr& node)
476 {
477 	PowerExpression(node);
478 
479 	while(f_data.f_type == '*'
480 	|| f_data.f_type == '/'
481 	|| f_data.f_type == '%') {
482 		NodePtr left = node;
483 
484 		node.CreateNode(f_data.f_type);
485 		node.SetInputInfo(f_lexer.GetInput());
486 
487 		GetToken();
488 		NodePtr right;
489 		PowerExpression(right);
490 
491 		node.AddChild(left);
492 		node.AddChild(right);
493 	}
494 }
495 
496 
PowerExpression(NodePtr & node)497 void IntParser::PowerExpression(NodePtr& node)
498 {
499 	UnaryExpression(node);
500 
501 	if(f_data.f_type == NODE_POWER) {
502 		NodePtr left = node;
503 
504 		node.CreateNode(f_data.f_type);
505 		node.SetInputInfo(f_lexer.GetInput());
506 
507 		GetToken();
508 		NodePtr right;
509 		PowerExpression(right);
510 
511 		node.AddChild(left);
512 		node.AddChild(right);
513 	}
514 }
515 
516 
517 
UnaryExpression(NodePtr & node)518 void IntParser::UnaryExpression(NodePtr& node)
519 {
520 	switch(f_data.f_type) {
521 	case NODE_DELETE:
522 	case NODE_INCREMENT:
523 	case NODE_DECREMENT:
524 	{
525 		node.CreateNode(f_data.f_type);
526 		node.SetInputInfo(f_lexer.GetInput());
527 		GetToken();
528 		NodePtr postfix;
529 		PostfixExpression(postfix);
530 		node.AddChild(postfix);
531 	}
532 		break;
533 
534 	case NODE_VOID:
535 	case NODE_TYPEOF:
536 	case '+':
537 	case '-':
538 	case '~':
539 	case '!':
540 	{
541 		node.CreateNode(f_data.f_type);
542 		node.SetInputInfo(f_lexer.GetInput());
543 
544 		GetToken();
545 
546 		NodePtr unary;
547 		UnaryExpression(unary);
548 
549 		node.AddChild(unary);
550 	}
551 		break;
552 
553 	default:
554 		PostfixExpression(node);
555 		break;
556 
557 	}
558 }
559 
560 
PostfixExpression(NodePtr & node)561 void IntParser::PostfixExpression(NodePtr& node)
562 {
563 	PrimaryExpression(node);
564 
565 	for(;;) {
566 		switch(f_data.f_type) {
567 		case '.':
568 		{
569 			NodePtr left = node;
570 
571 			node.CreateNode(NODE_MEMBER);
572 			node.SetInputInfo(f_lexer.GetInput());
573 
574 			GetToken();
575 			NodePtr right;
576 			PrimaryExpression(right);
577 
578 			node.AddChild(left);
579 			node.AddChild(right);
580 		}
581 			break;
582 
583 		case NODE_SCOPE:
584 		{
585 			GetToken();
586 			if(f_data.f_type == NODE_IDENTIFIER) {
587 				NodePtr left = node;
588 
589 				node.CreateNode(NODE_SCOPE);
590 				node.SetInputInfo(f_lexer.GetInput());
591 
592 				NodePtr right;
593 				right.CreateNode();
594 				right.SetInputInfo(f_lexer.GetInput());
595 				right.SetData(f_data);
596 
597 				node.AddChild(left);
598 				node.AddChild(right);
599 
600 				GetToken();
601 			}
602 			else {
603 				f_lexer.ErrMsg(AS_ERR_INVALID_SCOPE, "'::' is expected to be followed by an identifier");
604 			}
605 			// don't repeat scope (it seems)
606 			return;
607 		}
608 			break;
609 
610 		case NODE_INCREMENT:
611 		{
612 			NodePtr left = node;
613 
614 			node.CreateNode(NODE_POST_INCREMENT);
615 			node.SetInputInfo(f_lexer.GetInput());
616 
617 			GetToken();
618 
619 			node.AddChild(left);
620 		}
621 			break;
622 
623 		case NODE_DECREMENT:
624 		{
625 			NodePtr left = node;
626 
627 			node.CreateNode(NODE_POST_DECREMENT);
628 			node.SetInputInfo(f_lexer.GetInput());
629 
630 			GetToken();
631 
632 			node.AddChild(left);
633 		}
634 			break;
635 
636 		case '(':		// arguments
637 		{
638 			NodePtr left = node;
639 
640 			node.CreateNode(NODE_CALL);
641 			node.SetInputInfo(f_lexer.GetInput());
642 
643 			GetToken();
644 
645 			node.AddChild(left);
646 
647 			// any arguments?
648 			NodePtr right;
649 			if(f_data.f_type != ')') {
650 				NodePtr list;
651 				ListExpression(list, true, false);
652 				Data& data = list.GetData();
653 				if(data.f_type == NODE_LIST) {
654 					right = list;
655 				}
656 				else {
657 					right.CreateNode(NODE_LIST);
658 					right.SetInputInfo(f_lexer.GetInput());
659 					right.AddChild(list);
660 				}
661 			}
662 			else {
663 				// an empty list!
664 				right.CreateNode(NODE_LIST);
665 				right.SetInputInfo(f_lexer.GetInput());
666 			}
667 			node.AddChild(right);
668 
669 			if(f_data.f_type == ')') {
670 				GetToken();
671 			}
672 			else {
673 				f_lexer.ErrMsg(AS_ERR_PARENTHESIS_EXPECTED, "')' expected to end the list of arguments");
674 			}
675 		}
676 			break;
677 
678 		case '[':		// array/property access
679 		{
680 			NodePtr left = node;
681 
682 			// NOTE: this could be NODE_MEMBER in most
683 			//	 cases however the NODE_ARRAY supports
684 			//	 lists (including the empty list)
685 			//	 which NODE_MEMBER doesn't
686 			node.CreateNode(NODE_ARRAY);
687 			node.SetInputInfo(f_lexer.GetInput());
688 
689 			GetToken();
690 
691 			node.AddChild(left);
692 
693 			// any arguments?
694 			if(f_data.f_type != ']') {
695 				NodePtr right;
696 				ListExpression(right, false, false);
697 				node.AddChild(right);
698 			}
699 
700 			if(f_data.f_type == ']') {
701 				GetToken();
702 			}
703 			else {
704 				f_lexer.ErrMsg(AS_ERR_SQUARE_BRAKETS_EXPECTED, "']' expected to end the list of element references");
705 			}
706 		}
707 			break;
708 
709 		default:
710 			return;
711 
712 		}
713 	}
714 }
715 
716 
PrimaryExpression(NodePtr & node)717 void IntParser::PrimaryExpression(NodePtr& node)
718 {
719 	switch(f_data.f_type) {
720 	case NODE_NULL:
721 	case NODE_UNDEFINED:
722 	case NODE_TRUE:
723 	case NODE_FALSE:
724 	case NODE_IDENTIFIER:
725 	case NODE_INT64:
726 	case NODE_FLOAT64:
727 	case NODE_STRING:
728 	case NODE_THIS:
729 	case NODE_REGULAR_EXPRESSION:
730 	case NODE_PUBLIC:
731 	case NODE_PRIVATE:
732 	{
733 		node.CreateNode();
734 		node.SetInputInfo(f_lexer.GetInput());
735 		node.SetData(f_data);
736 		GetToken();
737 	}
738 		break;
739 
740 	case NODE_NEW:
741 	{
742 		node.CreateNode(NODE_NEW);
743 		node.SetInputInfo(f_lexer.GetInput());
744 		GetToken();
745 		NodePtr object;
746 		PostfixExpression(object);
747 		node.AddChild(object);
748 	}
749 		break;
750 
751 	case NODE_SUPER:
752 	{
753 		node.CreateNode(NODE_SUPER);
754 		node.SetInputInfo(f_lexer.GetInput());
755 		GetToken();
756 	}
757 		break;
758 
759 	case '(':
760 	{
761 		GetToken();
762 		ListExpression(node, false, false);
763 		Data& d = node.GetData();
764 		// NOTE: the following is important in different cases
765 		// such as (a).field which is dynamic (i.e. we get the
766 		// content of variable a as the name of the object to
767 		// access and thus it is not equivalent to a.field)
768 		if(d.f_type == NODE_IDENTIFIER) {
769 			d.f_type = NODE_VIDENTIFIER;
770 		}
771 		if(f_data.f_type == ')') {
772 			GetToken();
773 		}
774 		else {
775 			f_lexer.ErrMsg(AS_ERR_PARENTHESIS_EXPECTED, "')' expected to match the '('");
776 		}
777 	}
778 		break;
779 
780 	case '[':
781 	{
782 		node.CreateNode(NODE_ARRAY_LITERAL);
783 		node.SetInputInfo(f_lexer.GetInput());
784 		GetToken();
785 
786 		NodePtr elements;
787 		ListExpression(elements, false, true);
788 		node.AddChild(elements);
789 		if(f_data.f_type == ']') {
790 			GetToken();
791 		}
792 		else {
793 			f_lexer.ErrMsg(AS_ERR_SQUARE_BRAKETS_EXPECTED, "']' expected to match the '[' of this array");
794 		}
795 	}
796 		break;
797 
798 	case '{':
799 	{
800 		GetToken();
801 		ObjectLiteralExpression(node);
802 		if(f_data.f_type == '}') {
803 			GetToken();
804 		}
805 		else {
806 			f_lexer.ErrMsg(AS_ERR_CURVLY_BRAKETS_EXPECTED, "'}' expected to match the '{' of this object literal");
807 		}
808 	}
809 		break;
810 
811 	case NODE_FUNCTION:
812 	{
813 		GetToken();
814 		Function(node, true);
815 	}
816 		break;
817 
818 	default:
819 		f_lexer.ErrMsg(AS_ERR_INVALID_EXPRESSION, "unexpected token found in an expression");
820 		break;
821 
822 	}
823 }
824 
825 
826 
ObjectLiteralExpression(NodePtr & node)827 void IntParser::ObjectLiteralExpression(NodePtr& node)
828 {
829 	NodePtr		name;
830 	node_t		type;
831 
832 	node.CreateNode(NODE_OBJECT_LITERAL);
833 	node.SetInputInfo(f_lexer.GetInput());
834 	for(;;) {
835 		name.CreateNode(NODE_TYPE);
836 		name.SetInputInfo(f_lexer.GetInput());
837 		switch(type = f_data.f_type) {
838 		case '(':
839 		{
840 			// We keep the '(' so an identifier becomes
841 			// a VIDENTIFIER and thus remains dynamic.
842 			//GetToken();
843 			NodePtr type;
844 			Expression(type);
845 			name.AddChild(type);
846 		}
847 			goto and_scope;
848 
849 		case NODE_IDENTIFIER:	// <name> or <namespace>::<name>
850 		case NODE_PRIVATE:	// private::<name> only
851 		case NODE_PUBLIC:	// public::<name> only
852 			// NOTE: an IDENTIFIER here remains NODE_IDENTIFIER
853 			// so it doesn't look like the previous expression
854 			// (i.e. an expression literal can be just an
855 			// identifier but it will be marked as
856 			// NODE_VIDENTIFIER instead)
857 			name.SetData(f_data);
858 			GetToken();
859 and_scope:
860 			if(f_data.f_type == NODE_SCOPE) {
861 				GetToken();
862 				if(f_data.f_type == NODE_IDENTIFIER) {
863 					NodePtr scope;
864 					scope.CreateNode();
865 					scope.SetInputInfo(f_lexer.GetInput());
866 					scope.SetData(f_data);
867 					name.AddChild(scope);
868 				}
869 				else {
870 					f_lexer.ErrMsg(AS_ERR_INVALID_SCOPE, "'::' is expected to be followed by an identifier");
871 				}
872 			}
873 			else if(type != NODE_IDENTIFIER) {
874 				f_lexer.ErrMsg(AS_ERR_INVALID_FIELD_NAME, "'public' or 'private' cannot be used as a field name, '::' was expected");
875 			}
876 			break;
877 
878 		case NODE_INT64:
879 		case NODE_FLOAT64:
880 		case NODE_STRING:
881 			name.SetData(f_data);
882 			GetToken();
883 			break;
884 
885 		default:
886 			f_lexer.ErrMsg(AS_ERR_INVALID_FIELD, "the name of a field was expected");
887 			break;
888 
889 		}
890 
891 		if(f_data.f_type == ':') {
892 			GetToken();
893 		}
894 		else {
895 			// if we have a closing brace here, the programmer
896 			// tried to end his list with a comma; we just
897 			// accept that one silently! (like in C/C++)
898 			if(f_data.f_type == '}') {
899 				break;
900 			}
901 
902 			f_lexer.ErrMsg(AS_ERR_COLON_EXPECTED, "':' expected after the name of a field");
903 			if(f_data.f_type == ';') {
904 				// this is probably the end...
905 				return;
906 			}
907 
908 			// if we have a comma here, the programmer
909 			// just forgot a few things...
910 			if(f_data.f_type == ',') {
911 				GetToken();
912 				// we accept a comma at the end here too!
913 				if(f_data.f_type == '}'
914 				|| f_data.f_type == ';') {
915 					break;
916 				}
917 				continue;
918 			}
919 		}
920 
921 		// add the name only now so we have a mostly
922 		// valid tree from here on
923 		node.AddChild(name);
924 
925 		NodePtr value;
926 		AssignmentExpression(value);
927 		node.AddChild(value);
928 
929 		if(f_data.f_type != ',') {
930 			break;
931 		}
932 		GetToken();
933 	}
934 }
935 
936 
937 
938 
939 
940 };	// namespace as
941 };	// namespace sswf
942