comparison dmdscript_tango/parse.d @ 0:55c2951c07be

initial, files origin, premoved tree
author saaadel
date Sun, 24 Jan 2010 12:34:47 +0200
parents
children 8363a4bf6a8f
comparison
equal deleted inserted replaced
-1:000000000000 0:55c2951c07be
1
2 /* Digital Mars DMDScript source code.
3 * Copyright (c) 2000-2002 by Chromium Communications
4 * D version Copyright (c) 2004-2005 by Digital Mars
5 * All Rights Reserved
6 * written by Walter Bright
7 * www.digitalmars.com
8 * Use at your own risk. There is no warranty, express or implied.
9 * License for redistribution is by the GNU General Public License in gpl.txt.
10 *
11 * A binary, non-exclusive license for commercial use can be
12 * purchased from www.digitalmars.com/dscript/buy.html.
13 *
14 * DMDScript is implemented in the D Programming Language,
15 * www.digitalmars.com/d/
16 *
17 * For a C++ implementation of DMDScript, including COM support,
18 * see www.digitalmars.com/dscript/cppscript.html.
19 */
20
21
22 module dmdscript.parse;
23
24 import dmdscript.script;
25 import dmdscript.lexer;
26 import dmdscript.functiondefinition;
27 import dmdscript.expression;
28 import dmdscript.statement;
29 import dmdscript.identifier;
30 import dmdscript.ir;
31 import dmdscript.errmsgs;
32
33 class Parser : Lexer
34 {
35 uint flags;
36
37 enum
38 {
39 normal = 0,
40 initial = 1,
41
42 allowIn = 0,
43 noIn = 2,
44
45 // Flag if we're in the for statement header, as
46 // automatic semicolon insertion is suppressed inside it.
47 inForHeader = 4,
48 }
49
50 FunctionDefinition lastnamedfunc;
51
52
53 this(char[] sourcename, tchar[] base, int useStringtable)
54 {
55 //writefln("Parser.this(base = '%s')", base);
56 super(sourcename, base, useStringtable);
57 nextToken(); // start up the scanner
58 }
59
60 ~this()
61 {
62 lastnamedfunc = null;
63 }
64
65
66 /**********************************************
67 * Return !=0 on error, and fill in *perrinfo.
68 */
69
70 static int parseFunctionDefinition(out FunctionDefinition pfd,
71 d_string params, d_string bdy, out ErrInfo perrinfo)
72 {
73 Parser p;
74 Identifier*[] parameters;
75 TopStatement[] topstatements;
76 FunctionDefinition fd = null;
77 int result;
78
79 p = new Parser("anonymous", params, 0);
80
81 // Parse FormalParameterList
82 while (p.token.value != TOKeof)
83 {
84 if (p.token.value != TOKidentifier)
85 {
86 p.error(errmsgtbl[ERR_FPL_EXPECTED_IDENTIFIER], p.token.toString());
87 goto Lreturn;
88 }
89 parameters ~= p.token.ident;
90 p.nextToken();
91 if (p.token.value == TOKcomma)
92 p.nextToken();
93 else if (p.token.value == TOKeof)
94 break;
95 else
96 {
97 p.error(errmsgtbl[ERR_FPL_EXPECTED_COMMA], p.token.toString());
98 goto Lreturn;
99 }
100 }
101 if (p.errinfo.message)
102 goto Lreturn;
103
104 delete p;
105
106 // Parse StatementList
107 p = new Parser("anonymous", bdy, 0);
108 for (;;)
109 { TopStatement ts;
110
111 if (p.token.value == TOKeof)
112 break;
113 ts = p.parseStatement();
114 topstatements ~= ts;
115 }
116
117 fd = new FunctionDefinition(0, 0, null, parameters, topstatements);
118 fd.isanonymous = 1;
119
120 Lreturn:
121 pfd = fd;
122 perrinfo = p.errinfo;
123 result = (p.errinfo.message != null);
124 delete p;
125 p = null;
126 return result;
127 }
128
129 /**********************************************
130 * Return !=0 on error, and fill in *perrinfo.
131 */
132
133 int parseProgram(out TopStatement[] topstatements, ErrInfo *perrinfo)
134 {
135 topstatements = parseTopStatements();
136 check(TOKeof);
137 //writef("parseProgram done\n");
138 *perrinfo = errinfo;
139 //clearstack();
140 return errinfo.message != null;
141 }
142
143 TopStatement[] parseTopStatements()
144 {
145 TopStatement[] topstatements;
146 TopStatement ts;
147
148 //writefln("parseTopStatements()");
149 for (;;)
150 {
151 switch (token.value)
152 {
153 case TOKfunction:
154 ts = parseFunction(0);
155 topstatements ~= ts;
156 break;
157
158 case TOKeof:
159 return topstatements;
160
161 case TOKrbrace:
162 return topstatements;
163
164 default:
165 ts = parseStatement();
166 topstatements ~= ts;
167 break;
168 }
169 }
170 assert(0);
171 }
172
173 /***************************
174 * flag:
175 * 0 Function statement
176 * 1 Function literal
177 */
178
179 TopStatement parseFunction(int flag)
180 { Identifier* name;
181 Identifier*[] parameters;
182 TopStatement[] topstatements;
183 FunctionDefinition f;
184 Expression e = null;
185 Loc loc;
186
187 //writef("parseFunction()\n");
188 loc = currentline;
189 nextToken();
190 name = null;
191 if (token.value == TOKidentifier)
192 {
193 name = token.ident;
194 nextToken();
195
196 if (!flag && token.value == TOKdot)
197 {
198 // Regard:
199 // function A.B() { }
200 // as:
201 // A.B = function() { }
202 // This is not ECMA, but a jscript feature
203
204 e = new IdentifierExpression(loc, name);
205 name = null;
206
207 while (token.value == TOKdot)
208 {
209 nextToken();
210 if (token.value == TOKidentifier)
211 { e = new DotExp(loc, e, token.ident);
212 nextToken();
213 }
214 else
215 {
216 error(errmsgtbl[ERR_EXPECTED_IDENTIFIER_2PARAM], ".", token.toString());
217 break;
218 }
219 }
220 }
221 }
222
223 check(TOKlparen);
224 if (token.value == TOKrparen)
225 nextToken();
226 else
227 {
228 for (;;)
229 {
230 if (token.value == TOKidentifier)
231 {
232 parameters ~= token.ident;
233 nextToken();
234 if (token.value == TOKcomma)
235 { nextToken();
236 continue;
237 }
238 if (!check(TOKrparen))
239 break;
240 }
241 else
242 error(ERR_EXPECTED_IDENTIFIER);
243 break;
244 }
245 }
246
247 check(TOKlbrace);
248 topstatements = parseTopStatements();
249 check(TOKrbrace);
250
251 f = new FunctionDefinition(loc, 0, name, parameters, topstatements);
252
253 lastnamedfunc = f;
254
255 //writef("parseFunction() done\n");
256 if (!e)
257 return f;
258
259 // Construct:
260 // A.B = function() { }
261
262 Expression e2 = new FunctionLiteral(loc, f);
263
264 e = new AssignExp(loc, e, e2);
265
266 Statement s = new ExpStatement(loc, e);
267
268 return s;
269 }
270
271 /*****************************************
272 */
273
274 Statement parseStatement()
275 { Statement s;
276 Token *t;
277 Loc loc;
278
279 //writefln("parseStatement()");
280 loc = currentline;
281 switch (token.value)
282 {
283 case TOKidentifier:
284 case TOKthis:
285 // Need to look ahead to see if it is a declaration, label, or expression
286 t = peek(&token);
287 if (t.value == TOKcolon && token.value == TOKidentifier)
288 { // It's a label
289 Identifier *ident;
290
291 ident = token.ident;
292 nextToken();
293 nextToken();
294 s = parseStatement();
295 s = new LabelStatement(loc, ident, s);
296 }
297 else if (t.value == TOKassign ||
298 t.value == TOKdot ||
299 t.value == TOKlbracket)
300 { Expression exp;
301
302 exp = parseExpression();
303 parseOptionalSemi();
304 s = new ExpStatement(loc, exp);
305 }
306 else
307 { Expression exp;
308
309 exp = parseExpression(initial);
310 parseOptionalSemi();
311 s = new ExpStatement(loc, exp);
312 }
313 break;
314
315 case TOKreal:
316 case TOKstring:
317 case TOKdelete:
318 case TOKlparen:
319 case TOKplusplus:
320 case TOKminusminus:
321 case TOKplus:
322 case TOKminus:
323 case TOKnot:
324 case TOKtilde:
325 case TOKtypeof:
326 case TOKnull:
327 case TOKnew:
328 case TOKtrue:
329 case TOKfalse:
330 case TOKvoid:
331 { Expression exp;
332
333 exp = parseExpression(initial);
334 parseOptionalSemi();
335 s = new ExpStatement(loc, exp);
336 break;
337 }
338
339 case TOKvar:
340 {
341 Identifier *ident;
342 Expression init;
343 VarDeclaration v;
344 VarStatement vs;
345
346 vs = new VarStatement(loc);
347 s = vs;
348
349 nextToken();
350 for (;;)
351 { loc = currentline;
352
353 if (token.value != TOKidentifier)
354 {
355 error(errmsgtbl[ERR_EXPECTED_IDENTIFIER_PARAM], token.toString());
356 break;
357 }
358 ident = token.ident;
359 init = null;
360 nextToken();
361 if (token.value == TOKassign)
362 { uint flags_save;
363
364 nextToken();
365 flags_save = flags;
366 flags &= ~initial;
367 init = parseAssignExp();
368 flags = flags_save;
369 }
370 v = new VarDeclaration(loc, ident, init);
371 vs.vardecls ~= v;
372 if (token.value != TOKcomma)
373 break;
374 nextToken();
375 }
376 if (!(flags & inForHeader))
377 parseOptionalSemi();
378 break;
379 }
380
381 case TOKlbrace:
382 { BlockStatement bs;
383
384 nextToken();
385 bs = new BlockStatement(loc);
386 while (token.value != TOKrbrace)
387 {
388 if (token.value == TOKeof)
389 { /* { */
390 error(ERR_UNTERMINATED_BLOCK);
391 break;
392 }
393 bs.statements ~= parseStatement();
394 }
395 s = bs;
396 nextToken();
397
398 // The following is to accommodate the jscript bug:
399 // if (i) {return(0);}; else ...
400 if (token.value == TOKsemicolon)
401 nextToken();
402
403 break;
404 }
405
406 case TOKif:
407 { Expression condition;
408 Statement ifbody;
409 Statement elsebody;
410
411 nextToken();
412 condition = parseParenExp();
413 ifbody = parseStatement();
414 if (token.value == TOKelse)
415 {
416 nextToken();
417 elsebody = parseStatement();
418 }
419 else
420 elsebody = null;
421 s = new IfStatement(loc, condition, ifbody, elsebody);
422 break;
423 }
424
425 case TOKswitch:
426 { Expression condition;
427 Statement bdy;
428
429 nextToken();
430 condition = parseParenExp();
431 bdy = parseStatement();
432 s = new SwitchStatement(loc, condition, bdy);
433 break;
434 }
435
436 case TOKcase:
437 { Expression exp;
438
439 nextToken();
440 exp = parseExpression();
441 check(TOKcolon);
442 s = new CaseStatement(loc, exp);
443 break;
444 }
445
446 case TOKdefault:
447 nextToken();
448 check(TOKcolon);
449 s = new DefaultStatement(loc);
450 break;
451
452 case TOKwhile:
453 { Expression condition;
454 Statement bdy;
455
456 nextToken();
457 condition = parseParenExp();
458 bdy = parseStatement();
459 s = new WhileStatement(loc, condition, bdy);
460 break;
461 }
462
463 case TOKsemicolon:
464 nextToken();
465 s = new EmptyStatement(loc);
466 break;
467
468 case TOKdo:
469 { Statement bdy;
470 Expression condition;
471
472 nextToken();
473 bdy = parseStatement();
474 check(TOKwhile);
475 condition = parseParenExp();
476 parseOptionalSemi();
477 s = new DoStatement(loc, bdy, condition);
478 break;
479 }
480
481 case TOKfor:
482 {
483 Statement init;
484 Statement bdy;
485
486 nextToken();
487 flags |= inForHeader;
488 check(TOKlparen);
489 if (token.value == TOKvar)
490 {
491 init = parseStatement();
492 }
493 else
494 { Expression e;
495
496 e = parseOptionalExpression(noIn);
497 init = e ? new ExpStatement(loc, e) : null;
498 }
499
500 if (token.value == TOKsemicolon)
501 { Expression condition;
502 Expression increment;
503
504 nextToken();
505 condition = parseOptionalExpression();
506 check(TOKsemicolon);
507 increment = parseOptionalExpression();
508 check(TOKrparen);
509 flags &= ~inForHeader;
510
511 bdy = parseStatement();
512 s = new ForStatement(loc, init, condition, increment, bdy);
513 }
514 else if (token.value == TOKin)
515 { Expression inexp;
516 VarStatement vs;
517
518 // Check that there's only one VarDeclaration
519 // in init.
520 if (init.st == VARSTATEMENT)
521 {
522 vs = cast(VarStatement)init;
523 if (vs.vardecls.length != 1)
524 error(errmsgtbl[ERR_TOO_MANY_IN_VARS], vs.vardecls.length);
525 }
526
527 nextToken();
528 inexp = parseExpression();
529 check(TOKrparen);
530 flags &= ~inForHeader;
531 bdy = parseStatement();
532 s = new ForInStatement(loc, init, inexp, bdy);
533 }
534 else
535 {
536 error(errmsgtbl[ERR_IN_EXPECTED], token.toString());
537 s = null;
538 }
539 break;
540 }
541
542 case TOKwith:
543 { Expression exp;
544 Statement bdy;
545
546 nextToken();
547 exp = parseParenExp();
548 bdy = parseStatement();
549 s = new WithStatement(loc, exp, bdy);
550 break;
551 }
552
553 case TOKbreak:
554 { Identifier *ident;
555
556 nextToken();
557 if (token.sawLineTerminator && token.value != TOKsemicolon)
558 { // Assume we saw a semicolon
559 ident = null;
560 }
561 else
562 {
563 if (token.value == TOKidentifier)
564 { ident = token.ident;
565 nextToken();
566 }
567 else
568 ident = null;
569 parseOptionalSemi();
570 }
571 s = new BreakStatement(loc, ident);
572 break;
573 }
574
575 case TOKcontinue:
576 { Identifier *ident;
577
578 nextToken();
579 if (token.sawLineTerminator && token.value != TOKsemicolon)
580 { // Assume we saw a semicolon
581 ident = null;
582 }
583 else
584 {
585 if (token.value == TOKidentifier)
586 { ident = token.ident;
587 nextToken();
588 }
589 else
590 ident = null;
591 parseOptionalSemi();
592 }
593 s = new ContinueStatement(loc, ident);
594 break;
595 }
596
597 case TOKgoto:
598 { Identifier *ident;
599
600 nextToken();
601 if (token.value != TOKidentifier)
602 { error(errmsgtbl[ERR_GOTO_LABEL_EXPECTED], token.toString());
603 s = null;
604 break;
605 }
606 ident = token.ident;
607 nextToken();
608 parseOptionalSemi();
609 s = new GotoStatement(loc, ident);
610 break;
611 }
612
613 case TOKreturn:
614 { Expression exp;
615
616 nextToken();
617 if (token.sawLineTerminator && token.value != TOKsemicolon)
618 { // Assume we saw a semicolon
619 s = new ReturnStatement(loc, null);
620 }
621 else
622 { exp = parseOptionalExpression();
623 parseOptionalSemi();
624 s = new ReturnStatement(loc, exp);
625 }
626 break;
627 }
628
629 case TOKthrow:
630 { Expression exp;
631
632 nextToken();
633 exp = parseExpression();
634 parseOptionalSemi();
635 s = new ThrowStatement(loc, exp);
636 break;
637 }
638
639 case TOKtry:
640 { Statement bdy;
641 Identifier *catchident;
642 Statement catchbody;
643 Statement finalbody;
644
645 nextToken();
646 bdy = parseStatement();
647 if (token.value == TOKcatch)
648 {
649 nextToken();
650 check(TOKlparen);
651 catchident = null;
652 if (token.value == TOKidentifier)
653 catchident = token.ident;
654 check(TOKidentifier);
655 check(TOKrparen);
656 catchbody = parseStatement();
657 }
658 else
659 { catchident = null;
660 catchbody = null;
661 }
662
663 if (token.value == TOKfinally)
664 { nextToken();
665 finalbody = parseStatement();
666 }
667 else
668 finalbody = null;
669
670 if (!catchbody && !finalbody)
671 { error(ERR_TRY_CATCH_EXPECTED);
672 s = null;
673 }
674 else
675 {
676 s = new TryStatement(loc, bdy, catchident, catchbody, finalbody);
677 }
678 break;
679 }
680
681 default:
682 error(errmsgtbl[ERR_STATEMENT_EXPECTED], token.toString());
683 nextToken();
684 s = null;
685 break;
686 }
687
688 //writefln("parseStatement() done");
689 return s;
690 }
691
692
693
694 Expression parseOptionalExpression(uint flags = 0)
695 {
696 Expression e;
697
698 if (token.value == TOKsemicolon || token.value == TOKrparen)
699 e = null;
700 else
701 e = parseExpression(flags);
702 return e;
703 }
704
705 // Follow ECMA 7.8.1 rules for inserting semicolons
706 void parseOptionalSemi()
707 {
708 if (token.value != TOKeof &&
709 token.value != TOKrbrace &&
710 !(token.sawLineTerminator && (flags & inForHeader) == 0)
711 )
712 check(TOKsemicolon);
713 }
714
715 int check(TOK value)
716 {
717 if (token.value != value)
718 {
719 error(errmsgtbl[ERR_EXPECTED_GENERIC], token.toString(), Token.toString(value));
720 return 0;
721 }
722 nextToken();
723 return 1;
724 }
725
726 /********************************* Expression Parser ***************************/
727
728
729 Expression parseParenExp()
730 { Expression e;
731
732 check(TOKlparen);
733 e = parseExpression();
734 check(TOKrparen);
735 return e;
736 }
737
738 Expression parsePrimaryExp(int innew)
739 { Expression e;
740 Loc loc;
741
742 loc = currentline;
743 switch (token.value)
744 {
745 case TOKthis:
746 e = new ThisExpression(loc);
747 nextToken();
748 break;
749
750 case TOKnull:
751 e = new NullExpression(loc);
752 nextToken();
753 break;
754
755 case TOKtrue:
756 e = new BooleanExpression(loc, 1);
757 nextToken();
758 break;
759
760 case TOKfalse:
761 e = new BooleanExpression(loc, 0);
762 nextToken();
763 break;
764
765 case TOKreal:
766 e = new RealExpression(loc, token.realvalue);
767 nextToken();
768 break;
769
770 case TOKstring:
771 e = new StringExpression(loc, token.string);
772 token.string = null; // release to gc
773 nextToken();
774 break;
775
776 case TOKregexp:
777 e = new RegExpLiteral(loc, token.string);
778 token.string = null; // release to gc
779 nextToken();
780 break;
781
782 case TOKidentifier:
783 e = new IdentifierExpression(loc, token.ident);
784 token.ident = null; // release to gc
785 nextToken();
786 break;
787
788 case TOKlparen:
789 e = parseParenExp();
790 break;
791
792 case TOKlbracket:
793 e = parseArrayLiteral();
794 break;
795
796 case TOKlbrace:
797 if (flags & initial)
798 {
799 error(ERR_OBJ_LITERAL_IN_INITIALIZER);
800 nextToken();
801 return null;
802 }
803 e = parseObjectLiteral();
804 break;
805
806 case TOKfunction:
807 // if (flags & initial)
808 // goto Lerror;
809 e = parseFunctionLiteral();
810 break;
811
812 case TOKnew:
813 { Expression newarg;
814 Expression[] arguments;
815
816 nextToken();
817 newarg = parsePrimaryExp(1);
818 arguments = parseArguments();
819 e = new NewExp(loc, newarg, arguments);
820 break;
821 }
822
823 default:
824 // Lerror:
825 error(errmsgtbl[ERR_EXPECTED_EXPRESSION], token.toString());
826 nextToken();
827 return null;
828 }
829 return parsePostExp(e, innew);
830 }
831
832 Expression[] parseArguments()
833 {
834 Expression[] arguments = null;
835
836 if (token.value == TOKlparen)
837 {
838 nextToken();
839 if (token.value != TOKrparen)
840 {
841 for (;;)
842 { Expression arg;
843
844 arg = parseAssignExp();
845 arguments ~= arg;
846 if (token.value == TOKrparen)
847 break;
848 if (!check(TOKcomma))
849 break;
850 }
851 }
852 nextToken();
853 }
854 return arguments;
855 }
856
857 Expression parseArrayLiteral()
858 {
859 Expression e;
860 Expression[] elements;
861 Loc loc;
862
863 //writef("parseArrayLiteral()\n");
864 loc = currentline;
865 check(TOKlbracket);
866 if (token.value != TOKrbracket)
867 {
868 for (;;)
869 {
870 if (token.value == TOKcomma)
871 // Allow things like [1,2,,,3,]
872 // Like Explorer 4, and unlike Netscape, the
873 // trailing , indicates another null element.
874 elements ~= cast(Expression)null;
875 else if (token.value == TOKrbracket)
876 {
877 elements ~= cast(Expression)null;
878 break;
879 }
880 else
881 { e = parseAssignExp();
882 elements ~= e;
883 if (token.value != TOKcomma)
884 break;
885 }
886 nextToken();
887 }
888 }
889 check(TOKrbracket);
890 e = new ArrayLiteral(loc, elements);
891 return e;
892 }
893
894 Expression parseObjectLiteral()
895 {
896 Expression e;
897 Field[] fields;
898 Loc loc;
899
900 //writef("parseObjectLiteral()\n");
901 loc = currentline;
902 check(TOKlbrace);
903 if (token.value == TOKrbrace)
904 nextToken();
905 else
906 {
907 for (;;)
908 { Field f;
909 Identifier* ident;
910
911 if (token.value != TOKidentifier)
912 { error(ERR_EXPECTED_IDENTIFIER);
913 break;
914 }
915 ident = token.ident;
916 nextToken();
917 check(TOKcolon);
918 f = new Field(ident, parseAssignExp());
919 fields ~= f;
920 if (token.value != TOKcomma)
921 break;
922 nextToken();
923 }
924 check(TOKrbrace);
925 }
926 e = new ObjectLiteral(loc, fields);
927 return e;
928 }
929
930 Expression parseFunctionLiteral()
931 { FunctionDefinition f;
932 Loc loc;
933
934 loc = currentline;
935 f = cast(FunctionDefinition)parseFunction(1);
936 return new FunctionLiteral(loc, f);
937 }
938
939 Expression parsePostExp(Expression e, int innew)
940 { Loc loc;
941
942 for (;;)
943 {
944 loc = currentline;
945 //loc = (Loc)token.ptr;
946 switch (token.value)
947 {
948 case TOKdot:
949 nextToken();
950 if (token.value == TOKidentifier)
951 {
952 e = new DotExp(loc, e, token.ident);
953 }
954 else
955 {
956 error(errmsgtbl[ERR_EXPECTED_IDENTIFIER_2PARAM], ".", token.toString());
957 return e;
958 }
959 break;
960
961 case TOKplusplus:
962 if (token.sawLineTerminator && !(flags & inForHeader))
963 goto Linsert;
964 e = new PostIncExp(loc, e);
965 break;
966
967 case TOKminusminus:
968 if (token.sawLineTerminator && !(flags & inForHeader))
969 {
970 Linsert:
971 // insert automatic semicolon
972 insertSemicolon(token.sawLineTerminator);
973 return e;
974 }
975 e = new PostDecExp(loc, e);
976 break;
977
978 case TOKlparen:
979 { // function call
980 Expression[] arguments;
981
982 if (innew)
983 return e;
984 arguments = parseArguments();
985 e = new CallExp(loc, e, arguments);
986 continue;
987 }
988
989 case TOKlbracket:
990 { // array dereference
991 Expression index;
992
993 nextToken();
994 index = parseExpression();
995 check(TOKrbracket);
996 e = new ArrayExp(loc, e, index);
997 continue;
998 }
999
1000 default:
1001 return e;
1002 }
1003 nextToken();
1004 }
1005 assert(0);
1006 }
1007
1008 Expression parseUnaryExp()
1009 { Expression e;
1010 Loc loc;
1011
1012 loc = currentline;
1013 switch (token.value)
1014 {
1015 case TOKplusplus:
1016 nextToken();
1017 e = parseUnaryExp();
1018 e = new PreExp(loc, IRpreinc, e);
1019 break;
1020
1021 case TOKminusminus:
1022 nextToken();
1023 e = parseUnaryExp();
1024 e = new PreExp(loc, IRpredec, e);
1025 break;
1026
1027 case TOKminus:
1028 nextToken();
1029 e = parseUnaryExp();
1030 e = new XUnaExp(loc, TOKneg, IRneg, e);
1031 break;
1032
1033 case TOKplus:
1034 nextToken();
1035 e = parseUnaryExp();
1036 e = new XUnaExp(loc, TOKpos, IRpos, e);
1037 break;
1038
1039 case TOKnot:
1040 nextToken();
1041 e = parseUnaryExp();
1042 e = new NotExp(loc, e);
1043 break;
1044
1045 case TOKtilde:
1046 nextToken();
1047 e = parseUnaryExp();
1048 e = new XUnaExp(loc, TOKtilde, IRcom, e);
1049 break;
1050
1051 case TOKdelete:
1052 nextToken();
1053 e = parsePrimaryExp(0);
1054 e = new DeleteExp(loc, e);
1055 break;
1056
1057 case TOKtypeof:
1058 nextToken();
1059 e = parseUnaryExp();
1060 e = new XUnaExp(loc, TOKtypeof, IRtypeof, e);
1061 break;
1062
1063 case TOKvoid:
1064 nextToken();
1065 e = parseUnaryExp();
1066 e = new XUnaExp(loc, TOKvoid, IRundefined, e);
1067 break;
1068
1069 default:
1070 e = parsePrimaryExp(0);
1071 break;
1072 }
1073 return e;
1074 }
1075
1076 Expression parseMulExp()
1077 { Expression e;
1078 Expression e2;
1079 Loc loc;
1080
1081 loc = currentline;
1082 e = parseUnaryExp();
1083 for (;;)
1084 {
1085 switch (token.value)
1086 {
1087 case TOKmultiply:
1088 nextToken();
1089 e2 = parseUnaryExp();
1090 e = new XBinExp(loc, TOKmultiply, IRmul, e, e2);
1091 continue;
1092
1093 case TOKregexp:
1094 // Rescan as if it was a "/"
1095 rescan();
1096 case TOKdivide:
1097 nextToken();
1098 e2 = parseUnaryExp();
1099 e = new XBinExp(loc, TOKdivide, IRdiv, e, e2);
1100 continue;
1101
1102 case TOKpercent:
1103 nextToken();
1104 e2 = parseUnaryExp();
1105 e = new XBinExp(loc, TOKpercent, IRmod, e, e2);
1106 continue;
1107
1108 default:
1109 break;
1110 }
1111 break;
1112 }
1113 return e;
1114 }
1115
1116 Expression parseAddExp()
1117 { Expression e;
1118 Expression e2;
1119 Loc loc;
1120
1121 loc = currentline;
1122 e = parseMulExp();
1123 for (;;)
1124 {
1125 switch (token.value)
1126 {
1127 case TOKplus:
1128 nextToken();
1129 e2 = parseMulExp();
1130 e = new AddExp(loc, e, e2);
1131 continue;
1132
1133 case TOKminus:
1134 nextToken();
1135 e2 = parseMulExp();
1136 e = new XBinExp(loc, TOKminus, IRsub, e, e2);
1137 continue;
1138
1139 default:
1140 break;
1141 }
1142 break;
1143 }
1144 return e;
1145 }
1146
1147 Expression parseShiftExp()
1148 { Expression e;
1149 Expression e2;
1150 Loc loc;
1151
1152 loc = currentline;
1153 e = parseAddExp();
1154 for (;;)
1155 { uint ircode;
1156 TOK op = token.value;
1157
1158 switch (op)
1159 {
1160 case TOKshiftleft: ircode = IRshl; goto L1;
1161 case TOKshiftright: ircode = IRshr; goto L1;
1162 case TOKushiftright: ircode = IRushr; goto L1;
1163
1164 L1: nextToken();
1165 e2 = parseAddExp();
1166 e = new XBinExp(loc, op, ircode, e, e2);
1167 continue;
1168
1169 default:
1170 break;
1171 }
1172 break;
1173 }
1174 return e;
1175 }
1176
1177 Expression parseRelExp()
1178 { Expression e;
1179 Expression e2;
1180 Loc loc;
1181
1182 loc = currentline;
1183 e = parseShiftExp();
1184 for (;;)
1185 { uint ircode;
1186 TOK op = token.value;
1187
1188 switch (op)
1189 {
1190 case TOKless: ircode = IRclt; goto L1;
1191 case TOKlessequal: ircode = IRcle; goto L1;
1192 case TOKgreater: ircode = IRcgt; goto L1;
1193 case TOKgreaterequal: ircode = IRcge; goto L1;
1194
1195 L1:
1196 nextToken();
1197 e2 = parseShiftExp();
1198 e = new CmpExp(loc, op, ircode, e, e2);
1199 continue;
1200
1201 case TOKinstanceof:
1202 nextToken();
1203 e2 = parseShiftExp();
1204 e = new XBinExp(loc, TOKinstanceof, IRinstance, e, e2);
1205 continue;
1206
1207 case TOKin:
1208 if (flags & noIn)
1209 break; // disallow
1210 nextToken();
1211 e2 = parseShiftExp();
1212 e = new InExp(loc, e, e2);
1213 continue;
1214
1215 default:
1216 break;
1217 }
1218 break;
1219 }
1220 return e;
1221 }
1222
1223 Expression parseEqualExp()
1224 { Expression e;
1225 Expression e2;
1226 Loc loc;
1227
1228 loc = currentline;
1229 e = parseRelExp();
1230 for (;;)
1231 { uint ircode;
1232 TOK op = token.value;
1233
1234 switch (op)
1235 {
1236 case TOKequal: ircode = IRceq; goto L1;
1237 case TOKnotequal: ircode = IRcne; goto L1;
1238 case TOKidentity: ircode = IRcid; goto L1;
1239 case TOKnonidentity: ircode = IRcnid; goto L1;
1240
1241 L1:
1242 nextToken();
1243 e2 = parseRelExp();
1244 e = new CmpExp(loc, op, ircode, e, e2);
1245 continue;
1246
1247 default:
1248 break;
1249 }
1250 break;
1251 }
1252 return e;
1253 }
1254
1255 Expression parseAndExp()
1256 { Expression e;
1257 Expression e2;
1258 Loc loc;
1259
1260 loc = currentline;
1261 e = parseEqualExp();
1262 while (token.value == TOKand)
1263 {
1264 nextToken();
1265 e2 = parseEqualExp();
1266 e = new XBinExp(loc, TOKand, IRand, e, e2);
1267 }
1268 return e;
1269 }
1270
1271 Expression parseXorExp()
1272 { Expression e;
1273 Expression e2;
1274 Loc loc;
1275
1276 loc = currentline;
1277 e = parseAndExp();
1278 while (token.value == TOKxor)
1279 {
1280 nextToken();
1281 e2 = parseAndExp();
1282 e = new XBinExp(loc, TOKxor, IRxor, e, e2);
1283 }
1284 return e;
1285 }
1286
1287 Expression parseOrExp()
1288 { Expression e;
1289 Expression e2;
1290 Loc loc;
1291
1292 loc = currentline;
1293 e = parseXorExp();
1294 while (token.value == TOKor)
1295 {
1296 nextToken();
1297 e2 = parseXorExp();
1298 e = new XBinExp(loc, TOKor, IRor, e, e2);
1299 }
1300 return e;
1301 }
1302
1303 Expression parseAndAndExp()
1304 { Expression e;
1305 Expression e2;
1306 Loc loc;
1307
1308 loc = currentline;
1309 e = parseOrExp();
1310 while (token.value == TOKandand)
1311 {
1312 nextToken();
1313 e2 = parseOrExp();
1314 e = new AndAndExp(loc, e, e2);
1315 }
1316 return e;
1317 }
1318
1319 Expression parseOrOrExp()
1320 { Expression e;
1321 Expression e2;
1322 Loc loc;
1323
1324 loc = currentline;
1325 e = parseAndAndExp();
1326 while (token.value == TOKoror)
1327 {
1328 nextToken();
1329 e2 = parseAndAndExp();
1330 e = new OrOrExp(loc, e, e2);
1331 }
1332 return e;
1333 }
1334
1335 Expression parseCondExp()
1336 { Expression e;
1337 Expression e1;
1338 Expression e2;
1339 Loc loc;
1340
1341 loc = currentline;
1342 e = parseOrOrExp();
1343 if (token.value == TOKquestion)
1344 {
1345 nextToken();
1346 e1 = parseAssignExp();
1347 check(TOKcolon);
1348 e2 = parseAssignExp();
1349 e = new CondExp(loc, e, e1, e2);
1350 }
1351 return e;
1352 }
1353
1354 Expression parseAssignExp()
1355 { Expression e;
1356 Expression e2;
1357 Loc loc;
1358
1359 loc = currentline;
1360 e = parseCondExp();
1361 for (;;)
1362 { uint ircode;
1363 TOK op = token.value;
1364
1365 switch (op)
1366 {
1367 case TOKassign:
1368 nextToken();
1369 e2 = parseAssignExp();
1370 e = new AssignExp(loc, e, e2);
1371 continue;
1372
1373 case TOKplusass:
1374 nextToken();
1375 e2 = parseAssignExp();
1376 e = new AddAssignExp(loc, e, e2);
1377 continue;
1378
1379 case TOKminusass: ircode = IRsub; goto L1;
1380 case TOKmultiplyass: ircode = IRmul; goto L1;
1381 case TOKdivideass: ircode = IRdiv; goto L1;
1382 case TOKpercentass: ircode = IRmod; goto L1;
1383 case TOKandass: ircode = IRand; goto L1;
1384 case TOKorass: ircode = IRor; goto L1;
1385 case TOKxorass: ircode = IRxor; goto L1;
1386 case TOKshiftleftass: ircode = IRshl; goto L1;
1387 case TOKshiftrightass: ircode = IRshr; goto L1;
1388 case TOKushiftrightass: ircode = IRushr; goto L1;
1389
1390 L1: nextToken();
1391 e2 = parseAssignExp();
1392 e = new BinAssignExp(loc, op, ircode, e, e2);
1393 continue;
1394
1395 default:
1396 break;
1397 }
1398 break;
1399 }
1400 return e;
1401 }
1402
1403 Expression parseExpression(uint flags = 0)
1404 { Expression e;
1405 Expression e2;
1406 Loc loc;
1407 uint flags_save;
1408
1409 //writefln("Parser.parseExpression()");
1410 flags_save = this.flags;
1411 this.flags = flags;
1412 loc = currentline;
1413 e = parseAssignExp();
1414 while (token.value == TOKcomma)
1415 {
1416 nextToken();
1417 e2 = parseAssignExp();
1418 e = new CommaExp(loc, e, e2);
1419 }
1420 this.flags = flags_save;
1421 return e;
1422 }
1423
1424 }
1425
1426 /********************************* ***************************/
1427