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