**** Merged from MCS ****
[mono-project.git] / mcs / class / Microsoft.JScript / Microsoft.JScript / jscript-lexer-parser.g
blob3af1c8ce14827926578e557c0623dd6f0cc2678d
1 //
2 // jscript-lexer-parser.g: EcmaScript Grammar written on antlr.
3 //
4 // Author:
5 //       Cesar Lopez Nataren (cesar@ciencias.unam.mx)
6 //
7 // (C) 2003, 2004, Cesar Lopez Nataren
8 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 header {
32         using System.Collections;
35 options {
36         language = "CSharp";
37         namespace = "Microsoft.JScript";
41 // Parser
44 class JScriptParser extends Parser;
45 options {
46         defaultErrorHandler = false;
49 program returns [ScriptBlock prog]
50 { prog = new ScriptBlock (); }
51         : source_elements [prog.src_elems]
52         ;
54 source_elements [Block elems]
55         : (source_element [elems, elems.parent])*
56         ;
58 source_element [Block elems, AST parent]
59 { AST stm = null; }
60         : stm = statement [parent]
61           { 
62                   if (stm != null)
63                           elems.Add (stm); 
64           }
65         | stm = function_decl_or_expr [parent]
66           {
67                   if (stm != null)
68                           elems.Add (stm);
69           }
70         ;
72 function_decl_or_expr [AST parent] returns [AST func]
74         func = null;
75         bool is_func_exp = false;
76         FormalParameterList p = new FormalParameterList ();
77         Block body = null;
79         : "function" (id:IDENTIFIER | { is_func_exp = true; } ) 
80           OPEN_PARENS (p = formal_param_list [parent] | ) CLOSE_PARENS 
81           (COLON type_annot:IDENTIFIER | )
82           {
83                 if (is_func_exp)
84                         if (type_annot == null)
85                                 func = new FunctionExpression (parent, String.Empty, p,
86                                                                null, null);
87                         else 
88                                 func = new FunctionExpression (parent, String.Empty, p,
89                                                                type_annot.getText (), null);
90                 else if (type_annot == null)
91                         func = new FunctionDeclaration (parent, id.getText (), p, null, null);
92                      else 
93                         func = new FunctionDeclaration (parent, id.getText (), p, 
94                                                         type_annot.getText (), null);
95           }
96           OPEN_BRACE 
97                   body = function_body [func] 
98                   { ((FunctionDeclaration) func).Function.body = body; } 
99           CLOSE_BRACE
100         ;
102 function_body [AST parent] returns [Block elems]
104         elems = new Block (parent);
106         : source_elements [elems]
107         ;
109 formal_param_list [AST parent] returns [FormalParameterList p]
111         p = new FormalParameterList ();
112     p.parent = parent;
114         : i:IDENTIFIER (COLON t1:IDENTIFIER { p.Add (i.getText (), t1.getText ()); } 
115                        | { p.Add (i.getText (), "Object"); } 
116                        )
117           (COMMA g:IDENTIFIER (COLON t2:IDENTIFIER { p.Add (g.getText (), t2.getText ()); } 
118                               | { p.Add (g.getText (), "Object"); }
119                               )
120           )*
121         ;
124 // Statements
127 statement [AST parent] returns [AST stm]
128 { stm = null; }
129         : stm = expr_stm [parent] SEMI_COLON
130         | stm = var_stm [parent]
131         | empty_stm
132         | stm = if_stm [parent]
133         | stm = iteration_stm [parent]
134         | stm = continue_stm [parent]
135         | stm = break_stm [parent]
136         | stm = return_stm [parent]
137         | stm = with_stm [parent]
138         | stm = switch_stm [parent]
139         | stm = throw_stm [parent]
140         | stm = try_stm [parent]
141         | stm = block [new Block (parent), parent]
142         ;
144 block [Block elems, AST parent] returns [AST _block]
146     AST stm = null;
147     _block = elems;
148     elems.parent = parent;
150     : OPEN_BRACE 
151           (stm = statement [elems]
152           {
153                   if (stm != null) {
154                           stm.parent = elems;
155                           elems.Add (stm);
156                   }
157           })*
158       CLOSE_BRACE
159     ;
162 try_stm [AST parent] returns [Try t]
164         t = new Try (parent);
166         : "try" block [t.guarded_block, t]
167         ((catch_exp [ref t.catch_id, t.catch_block, t] (finally_exp [t.finally_block, t] | ) | ) | finally_exp [t.finally_block, t])
168         ;
170 catch_exp [ref string id, Block catch_block, AST parent]
171         : "catch" OPEN_PARENS i:IDENTIFIER { id = i.getText (); } CLOSE_PARENS block [catch_block, parent]
172         ;
174 finally_exp [Block elems, AST parent]
175         : "finally" block [elems, parent]
176         ;
178 throw_stm [AST parent] returns [AST t]
180         t = null;
181         AST e = null;
183         : "throw" e = expr [parent] SEMI_COLON
184           {
185                   t = new Throw (e);
186           }
187         ;
189 switch_stm [AST parent] returns [Switch sw]
191         sw = new Switch (parent);
192         AST exp = null;
193         ArrayList [] clauses = null;
195         : "switch"  OPEN_PARENS exp = expr [sw] CLOSE_PARENS clauses = case_block [sw]
196           {
197                   sw.exp = exp;
198                   exp.parent = sw;            
200                   sw.case_clauses = clauses [0];
201                   sw.default_clauses = clauses [1];
202                   sw.sec_case_clauses = clauses [2];
204                   foreach (Clause cc in sw.case_clauses)
205                           foreach (AST ast in cc.stm_list)
206                                   ast.parent = sw;
207                   foreach (AST dc in sw.default_clauses)
208                                   dc.parent = sw;
209                   foreach (Clause cc in sw.case_clauses)
210                           foreach (AST ast in cc.stm_list)
211                                   ast.parent = sw;
212           }
213         ;
215 case_block [AST parent] returns [ArrayList [] clauses]
217         clauses = new ArrayList [3]; 
218         ArrayList c1_clauses, def_clauses, c2_clauses;
219         c1_clauses = def_clauses = c2_clauses = null;
221         : OPEN_BRACE c1_clauses = case_clauses [parent] def_clauses = default_clause [parent] c2_clauses = case_clauses [parent] CLOSE_BRACE
222           {
223                   clauses [0] = c1_clauses;
224                   clauses [1] = def_clauses;
225                   clauses [2] = c2_clauses;
226           }
227         ;
229 default_clause [AST parent] returns [ArrayList def_clause]
230         : "default" COLON def_clause = statement_list [parent]
231         ;
233 case_clauses [AST parent] returns [ArrayList clauses]
235         clauses = new ArrayList (); 
236         Clause clause = null;
238         : (clause = case_clause [parent] { if (clause != null) clauses.Add (clause); })*
239         ;
241 case_clause [AST parent] returns [Clause clause]
243         clause = new Clause (parent);
244         AST exp = null;
245         ArrayList stm_list = null;
247         : "case" exp = expr [parent] { clause.exp = exp; } COLON stm_list = statement_list [parent] { clause.stm_list = stm_list; }
248         ;
250 with_stm [AST parent] returns [AST with]
252         with = null;
253         AST exp, stm;
254         exp = stm = null;
256         : "with" OPEN_PARENS exp = expr [parent] CLOSE_PARENS stm = statement [null]
257           {
258                   with = new With (parent, exp, stm);  
259           }     
260         ;
262 return_stm [AST parent] returns [AST r]
264         r = null;
265         AST e = null;
267         : "return" (e = expr [parent] { r = new Return (parent, e); } | ) SEMI_COLON
268         ;
271 break_stm [AST parent] returns [AST b]
273         b = new Break ();
275         : "break" ( id:IDENTIFIER
276                     { ((Break) b).identifier = id.getText (); }
277                   | { ((Break) b).identifier = String.Empty; } ) SEMI_COLON
278         ;
279         
280 continue_stm [AST parent] returns [AST cont]
282         cont = new Continue (parent); 
284         : "continue" ( id:IDENTIFIER 
285                        { ((Continue) cont).identifier = id.getText (); } 
286                      | { ((Continue) cont).identifier = String.Empty; } ) SEMI_COLON
287         ;
289 iteration_stm [AST parent] returns [AST iter]
291         iter = null;
292         AST stm = null;
293         AST exprn = null;
294         AST [] exprs = null;
296         : "do" stm = statement [iter] "while" OPEN_PARENS exprn = expr [iter] CLOSE_PARENS SEMI_COLON
297           {
298                   iter = new DoWhile (parent, stm, exprn);
299                   exprn.parent = stm.parent = iter;
300           }
301         | "while" OPEN_PARENS exprn = expr [iter] CLOSE_PARENS stm = statement [iter]
302           {
303                   iter = new While (parent, exprn, stm);
304                   exprn.parent = stm.parent = iter;
305           }
306         | "for" OPEN_PARENS exprs = inside_for [iter] CLOSE_PARENS stm = statement [iter]
307           {
308                   iter = new For (parent, exprs, stm);
309                   stm.parent = iter;
311           }
312         ;
314 inside_for [AST parent] returns [AST [] exprs]
316         AST exp1, exp2, exp3;
317         exprs = null;
318         exp1 = exp2 = exp3 = null;
319         VariableStatement v_stm = new VariableStatement ();
321         : (exp1 = expr [parent] | ) SEMI_COLON (exp2 = expr [parent] | ) SEMI_COLON (exp3 = expr [parent] | )
322           {
323                   exprs = new AST [] {exp1, exp2, exp3};
324           }               
325         | "var" (var_decl_list [v_stm, parent]
326                   ( SEMI_COLON (exp2 = expr [parent] | ) SEMI_COLON (exp3 = expr [parent] | )
327           {
328                   exprs = new AST [] {v_stm, exp2, exp3};
329           }
330                   | IN exp3 = expr [parent]))
331         // FIXME: left_hand_side_expr in exp rule, missing
332         ;
333         
334 if_stm [AST parent] returns [AST if_stm]
336         if_stm = null;
337         AST cond, true_stm, false_stm;
338         cond = true_stm = false_stm = null;
340         : "if" OPEN_PARENS cond = expr [if_stm] CLOSE_PARENS true_stm = statement [if_stm]
341           (("else")=> "else" false_stm = statement [if_stm] | )
342           {
343                   if_stm = new If (parent, cond, true_stm, false_stm);
344                   cond.parent = true_stm.parent = if_stm;
345                   if (false_stm != null)
346                           false_stm.parent = if_stm;                    
347           }
348         ;
350 empty_stm
351         : SEMI_COLON
352         ;
354 var_stm [AST parent] returns [VariableStatement var_stm]
355 { var_stm = new VariableStatement (); }
356         : "var" var_decl_list [var_stm, parent] SEMI_COLON
357         ;
359 var_decl_list [VariableStatement var_stm, AST parent]
360 { VariableDeclaration var_decln = null; }
361         : var_decln = var_decl [parent]
362           { 
363                 if (var_decln != null && var_stm != null)
364                         var_stm.Add (var_decln);
365           }
366           (COMMA var_decln = var_decl [parent]
367           { 
368                   if (var_decln != null && var_stm != null) 
369                           var_stm.Add (var_decln);
370           }
371           )*
372         ;
373         
375 var_decl [AST parent] returns [VariableDeclaration var_decl]
377         var_decl = null;
378         AST init = null;
380         : id:IDENTIFIER (COLON type_annot:IDENTIFIER | )
381           (init = initializer [parent]
382            { 
383                   if (type_annot == null)
384                           var_decl = new VariableDeclaration (parent, id.getText (), null , init);
385                   else 
386                           var_decl = new VariableDeclaration (parent, id.getText (), type_annot.getText () , init); 
387            }
388           | 
389            {
390                   if (type_annot == null)
391                           var_decl = new VariableDeclaration (parent, id.getText (), null, null);
392                   else
393                           var_decl = new VariableDeclaration (parent, id.getText (), type_annot.getText (), null);
394            })
395         ;
397 initializer [AST parent] returns [AST init]
398 { init = null; }
399         : ASSIGN init = assignment_expr [parent]
400         ;
402 expr_stm [AST parent] returns [AST e]
403 { e = null; }
404         : e = expr [parent]
405         ;
408 statement_list [AST parent] returns [ArrayList stms]
410         stms = new ArrayList ();
411         AST stm = null;
413         : (stm = statement [null] { if (stm != null) stms.Add (stm); })*
414         ;
416 expr [AST parent] returns [Expression e]
418         e = new Expression (parent);
419         AST a = null;
421         : a = assignment_expr [parent] { e.Add (a); } 
422           (COMMA a = assignment_expr [parent] { e.Add (a); } )*
423         ;
424 assignment_expr [AST parent] returns [AST assign_expr]
425 {     
426         assign_expr = null;
427         JSToken op = JSToken.None;
428         AST left, right;
429         left = right = null;
431         : ((left_hand_side_expr [parent] assignment_op)=> 
432             left = left_hand_side_expr [parent] op = assignment_op right = assignment_expr [parent]
433             {
434                   Assign a;
435                   if (right is Assign)
436                           a = new Assign (parent, left, right, op, true);
437                   else
438                           a = new Assign (parent, left, right, op, false);
439                   assign_expr = a;
440             } 
441         | assign_expr = cond_expr [parent]
442         )
443         ;
445 member_expr [AST parent] returns [AST mem_exp]
447         mem_exp = null;
449         : ( mem_exp = primary_expr [parent]
450           | "new" member_expr [parent] arguments [parent]
451           ) member_aux [parent]
452         ;
454 member_aux [AST parent]
455         : 
456         ( DOT IDENTIFIER 
457         | OPEN_BRACKET expr [parent] CLOSE_BRACKET
458         ) member_aux [parent]
459         |
460         ;
462 new_expr [AST parent] returns [AST new_exp]
464         new_exp = null; 
465         AST mem_exp = null;
467         : mem_exp = member_expr [parent] { new_exp = mem_exp; }
468         ;
469         
470 call_expr [AST parent] returns [Call func_call]
472         func_call = null;
473         AST member = null;
474         AST args1 = null;
475         AST args2 = null;
477         : member = member_expr [parent] args1 = arguments [parent] args2 = call_aux [parent]
478           {
479                   func_call = new Call (parent, member, args1, args2);
480           }
481         ;
483 call_aux [AST parent] returns [AST args]
485         args = null;
487         : 
488         ( arguments [parent]
489         | OPEN_BRACKET expr [parent] CLOSE_BRACKET
490         | DOT IDENTIFIER
491         ) call_aux [parent]
492         |
493         ;
495 arguments [AST parent] returns [Args args]
497         Args tmp = new Args ();
498         args = null; 
500         : OPEN_PARENS (arguments_list [tmp, parent] { args = tmp; } | ) CLOSE_PARENS
501         ;
503 arguments_list [Args args, AST parent]
505         AST a = null;
507         : a = assignment_expr [parent] { args.Add (a); } 
508           (COMMA a = assignment_expr [parent] { args.Add (a); })*
509         ;
511 left_hand_side_expr [AST parent] returns [AST lhe]
513         lhe = null;
514         Call call = null;
516         : (call_expr [parent])=> call = call_expr [parent] { lhe = call; }
517         | lhe = new_expr [parent]
518         ;
520 postfix_expr [AST parent] returns [AST post_expr]
522         post_expr = null;
523         JSToken op = JSToken.None;
524         AST left = null;
526         : left = left_hand_side_expr [parent] ( INCREMENT { op = JSToken.Increment; } 
527                                               | DECREMENT { op = JSToken.Decrement; } 
528                                               | )
529           {
530                   if (op == JSToken.None)
531                           post_expr = left;
532                   else
533                           post_expr = new PostOrPrefixOperator (parent, left, op);
534           }
535         ;
537 unary_expr [AST parent] returns [AST unary_exprn]
539         unary_exprn = null;
540         JSToken op = JSToken.None;
541         AST u_expr = null;
543         : unary_exprn = postfix_expr [parent]
544         | op = unary_op u_expr = unary_expr [null]
545           { 
546                   unary_exprn = new Unary (parent, u_expr, op);
547                   u_expr.parent = unary_exprn; 
548           }
549         ;
551 unary_op returns [JSToken unary_op]
552 { unary_op = JSToken.None; }
553         : "delete" { unary_op = JSToken.Delete; }
554         | "void" { unary_op = JSToken.Void; }
555         | "typeof" { unary_op = JSToken.Typeof; }
556         | INCREMENT { unary_op = JSToken.Increment; }
557         | DECREMENT { unary_op = JSToken.Decrement; }
558         | PLUS { unary_op = JSToken.Plus; }
559         | MINUS { unary_op = JSToken.Minus; }
560         | BITWISE_NOT { unary_op = JSToken.BitwiseNot; }
561         | LOGICAL_NOT { unary_op = JSToken.LogicalNot; }
562         ;
564 multiplicative_expr [AST parent] returns [AST mult_expr]
566         mult_expr = null;
567         AST left = null;
568         AST right = null;
570         : left = unary_expr [parent] right = multiplicative_aux [parent]
571           {
572                   if (right == null)
573                           mult_expr = left;
574                   else
575                           mult_expr = new Binary (parent, left, right, ((Binary) right).old_op);
576           }
577         ;
579 multiplicative_aux [AST parent] returns [AST mult_aux]
581         mult_aux = null;
582         JSToken mult_op = JSToken.None;
583         AST left = null;
584         AST right = null;
586         : (( MULT { mult_op = JSToken.Multiply; }
587            | DIVISION { mult_op = JSToken.Divide; }
588            | MODULE { mult_op = JSToken.Modulo; }
589            ) left = unary_expr [parent] right = multiplicative_aux [parent]
590              {
591                           if (right == null)
592                                   mult_aux = new Binary (parent, left, null, JSToken.None);
593                           else
594                                   mult_aux = new Binary (parent, left, right, ((Binary) right).old_op);
595                           ((Binary) mult_aux).old_op = mult_op;
596              }
597           | )
598         ;
600 additive_expr [AST parent] returns [AST add_expr]
602         add_expr = null;
603         AST left, right;
604         left = right = null;
606         : left = multiplicative_expr [parent] right = additive_aux [parent]
607           {
608                           if (right == null)
609                                   add_expr = left;
610                           else
611                                   add_expr = new Binary (parent, left, right, ((Binary) right).old_op);
612           }
613         ;
615 additive_aux [AST parent] returns [AST add_aux]
617         add_aux = null;
618         JSToken op = JSToken.None;
619         AST left, right;
620         left = right = null;
622         : (( PLUS { op = JSToken.Plus; }
623            | MINUS { op = JSToken.Minus; }
624            ) left = multiplicative_expr [parent] right = additive_aux [parent]
625              {
626                      if (right == null)
627                              add_aux = new Binary (parent, left, null, JSToken.None);
628                      else
629                              add_aux = new Binary (parent, left, right, ((Binary) right).old_op);
630                      ((Binary) add_aux).old_op = op;
631              }
632         | )
633         ;
635 shift_expr [AST parent] returns [AST shift_expr]
637         shift_expr = null;
638         AST left, right;
639         left = right = null;
641         : left = additive_expr [parent] right = shift_aux [parent]
642           {
643                   if (right == null)
644                           shift_expr = left;
645                   else
646                           shift_expr = new Binary (parent, left, right, ((Binary) right).old_op);
647           }
648         ;
650 shift_aux [AST parent] returns [AST shift_auxr]
652         shift_auxr = null; 
653         JSToken op = JSToken.None;
654         AST left, right;
655         left = right = null;
657         : (op = shift_op left = additive_expr [parent] right = shift_aux [parent]
658            {
659                    if (right == null)
660                            shift_auxr = new Binary (parent, left, null, JSToken.None);
661                    else
662                            shift_auxr = new Binary (parent, left, right, ((Binary) right).old_op);
664                    ((Binary) shift_auxr).old_op = op;
665            }
666           | )
667         ;
669 shift_op returns [JSToken shift_op]
670 { shift_op = JSToken.None; }
671         : SHIFT_LEFT { shift_op = JSToken.LeftShift; }
672         | SHIFT_RIGHT { shift_op = JSToken.RightShift; }
673         | UNSIGNED_SHIFT_RIGHT { shift_op = JSToken.UnsignedRightShift; }
674         ;
676 relational_expr [AST parent] returns [AST rel_expr]
678         rel_expr = null;
679         AST left = null;
680         Relational right = null;
682         : left = shift_expr [parent] right = relational_aux [parent]
683           {
684                   if (right == null)
685                           rel_expr = left;
686                   else
687                           rel_expr = new Relational (parent, left, right, right.old_op);
688           }
689         ;
691 relational_aux [AST parent] returns [Relational rel_aux]
693         rel_aux = null;
694         JSToken op = JSToken.None;
695         AST left = null;
696         Relational right = null;
698         : (op = relational_op left = shift_expr [parent] right = relational_aux [parent]
699            {
700                    if (right == null)
701                           rel_aux = new Relational (parent, left, null, JSToken.None);
702                    else
703                            rel_aux = new Relational (parent, left, right, right.old_op);
704                    rel_aux.old_op = op;
706            }
707          | )
708         ;
710 relational_op returns [JSToken rel_op]
711 { rel_op = JSToken.None; }
712         : LESS_THAN { rel_op = JSToken.LessThan; }
713         | GREATER_THAN { rel_op = JSToken.GreaterThan; }
714         | LESS_EQ { rel_op = JSToken.LessThanEqual; }
715         | GREATER_EQ { rel_op = JSToken.GreaterThanEqual; }
716         | INSTANCE_OF { rel_op = JSToken.InstanceOf; }
717         | IN { rel_op = JSToken.In; }
718         ;
721 equality_expr [AST parent] returns [AST eq_expr]
723         eq_expr = null;
724         AST left = null;
725         AST right = null;
727         : left = relational_expr [parent] right = equality_aux [parent]
728           {
729                   if (right == null)
730                           eq_expr = left;
731                   else {
732                           eq_expr = new Equality (parent, left, right, ((Equality) right).old_op);
733                   }
734           }
735         ;
737 equality_aux [AST parent] returns [AST eq_aux]
739         eq_aux = null;
740         AST left = null;
741         AST right = null;
742         JSToken op = JSToken.None;
744         : (op = equality_op left = relational_expr [parent] right = equality_aux [parent]
745            {
746                    if (right == null)
747                           eq_aux = new Equality (parent, left, null, JSToken.None);
748                    else
749                           eq_aux = new Equality (parent, left, right, ((Equality) right).old_op);
750                   ((Equality) eq_aux).old_op = op;
751            }
752           | )
753         ;
755 equality_op returns [JSToken eq_op]
756 { eq_op = JSToken.None; }
757         : EQ { eq_op = JSToken.Equal; }
758         | NEQ { eq_op = JSToken.NotEqual; }
759         | STRICT_EQ { eq_op = JSToken.StrictEqual; }
760         | STRICT_NEQ { eq_op = JSToken.StrictNotEqual; }
761         ;
763 bitwise_and_expr [AST parent] returns [AST bit_and_expr]
765         bit_and_expr = null;
766     AST left;
767         AST right;
768         left = null;
769         right = null;
771         : left = equality_expr [parent]  right = bitwise_and_aux [parent]
772           {
773                   if (right == null)
774                           bit_and_expr = left;
775                   else
776                           bit_and_expr = new Binary (parent, left, right, JSToken.BitwiseAnd);
777           }
778         ;
780 bitwise_and_aux [AST parent] returns [AST bit_and_aux]
782         bit_and_aux = null;
783         AST left = null;
784         AST right = null;
786         : (BITWISE_AND left = equality_expr [parent] right = bitwise_and_aux [parent]
787            {
788                    if (right == null)
789                            bit_and_aux = left;
790                    else
791                            bit_and_aux = new Binary (parent, left, right, JSToken.BitwiseAnd);
792            }
793           | )
794                   
795         ;
797 bitwise_xor_expr [AST parent] returns [AST bit_xor_expr]
799         bit_xor_expr = null;
800         AST left, right;
801         left = right = null;
803         : left = bitwise_and_expr [parent] right = bitwise_xor_aux [parent]
804           {
805                   if (right == null)
806                           bit_xor_expr = left;
807                   else
808                           bit_xor_expr = new Binary (parent, left, right, JSToken.BitwiseXor);
809           }
810         ;
812 bitwise_xor_aux [AST parent] returns [AST bit_xor_aux]
814         bit_xor_aux = null;
815         AST left, right;
816         left = right = null;
818         : (BITWISE_XOR left = bitwise_and_expr [parent] right = bitwise_xor_aux [parent]
819            {
820                   if (right == null)
821                           bit_xor_aux = left;
822                   else
823                           bit_xor_aux = new Binary (parent, left, right, JSToken.BitwiseXor);
824            }
825           | )
826         ;
828 bitwise_or_expr [AST parent] returns [AST bit_or_expr]
830         bit_or_expr = null;
831         AST left, right;
832         left = right = null;
834         : left = bitwise_xor_expr [parent] right = bitwise_or_aux [parent]
835           {
836                   if (right == null)
837                           bit_or_expr = left;
838                   else
839                           bit_or_expr = new Binary (parent, left, right, JSToken.BitwiseOr);
840           }
841         ;
843 bitwise_or_aux [AST parent] returns [AST bit_or_aux]
845         bit_or_aux = null;
846         AST left, right;
847         left = right = null;
849         : (BITWISE_OR left = bitwise_xor_expr [parent] right = bitwise_or_aux [parent]
850            {
851                    if (right == null)
852                            bit_or_aux = left;
853                    else
854                            bit_or_aux = new Binary (parent, left, right, JSToken.BitwiseOr);
855            }
856           | )
857         ;
859 logical_and_expr [AST parent] returns [AST log_and_expr]
861         log_and_expr = null;
862         AST left, right;
863         left = right = null;
865         : left = bitwise_or_expr [parent] right = logical_and_aux [parent]
866           {
867                   if (right == null)
868                           log_and_expr = left;
869                   else
870                           log_and_expr = new Binary (parent, left, right, JSToken.LogicalAnd);
871           }
872         ;
874 logical_and_aux [AST parent] returns [AST log_and_aux]
876         log_and_aux = null;
877         AST left, right;
878         left = right = null;
880         : (LOGICAL_AND left = bitwise_or_expr [parent] right = logical_and_aux [parent]
881            {
882                    if (right == null)
883                            log_and_aux = left;
884                    else
885                            log_and_aux = new Binary (parent, left, right, JSToken.LogicalAnd);
886            }
887           | )
888         ;
890 logical_or_expr [AST parent] returns [AST log_or_expr]
892         log_or_expr = null; 
893         AST left, right;
894         left = right = null;
896         :  left = logical_and_expr [parent] right = logical_or_aux [parent]
897            {
898                   if (right == null)
899                           log_or_expr = left;
900                   else
901                           log_or_expr = new Binary (parent, left, right, JSToken.LogicalOr);
902            }
903                                                                 
904         ;
906 logical_or_aux [AST parent] returns [AST log_or_aux]
908         AST left, right;
909         log_or_aux = null;
910         left = right = null;    
912         : (LOGICAL_OR left = logical_and_expr [parent] right = logical_or_aux [parent]
913            {
914                   if (right == null)
915                           log_or_aux = left; 
916                   else
917                           log_or_aux = new Binary (parent, left, right, JSToken.LogicalOr);
918            }
919           | )
920         ;
922 cond_expr [AST parent] returns [AST conditional]
924         conditional = null; 
925         AST cond;
926         AST trueExpr, falseExpr;
927         cond = null;
928         trueExpr = falseExpr = null;
930         : cond = logical_or_expr [parent]
931           (INTERR trueExpr = assignment_expr [parent]
932            COLON falseExpr = assignment_expr [parent]
933            { 
934                   if (trueExpr != null && falseExpr != null) {
935                           Conditional c = new Conditional (parent, (AST) cond, trueExpr, falseExpr); 
936                           conditional =  c;
937                   }
938            }
939           | { conditional = cond; } )
941         ;
943 assignment_op returns [JSToken assign_op]
945     assign_op = JSToken.None;
947         : ASSIGN { assign_op = JSToken.Assign; }
948         | MULT_ASSIGN { assign_op = JSToken.MultiplyAssign; }
949         | DIV_ASSIGN { assign_op = JSToken.DivideAssign; }
950         | MOD_ASSIGN { assign_op = JSToken.ModuloAssign; }
951         | ADD_ASSIGN { assign_op = JSToken.PlusAssign; }
952         | SUB_ASSIGN { assign_op = JSToken.MinusAssign; }
953         | SHIFT_LEFT_ASSIGN { assign_op = JSToken.LeftShiftAssign; }
954         | SHIFT_RIGHT_ASSIGN { assign_op = JSToken.RightShiftAssign; }
955         | AND_ASSIGN { assign_op = JSToken.BitwiseAndAssign; }
956         | XOR_ASSIGN { assign_op = JSToken.BitwiseXorAssign; }
957         | OR_ASSIGN { assign_op = JSToken.BitwiseOrAssign; }
958         ;
959         
961 primary_expr [AST parent] returns [AST prim_exp]
963         prim_exp = null;
964         AST l = null;
965         Expression e = null;
967         : p:"this" { prim_exp = new This (); }
968 //      | l = object_literal [parent] { prim_exp = l; }
969         | id:IDENTIFIER 
970           { 
971                 Identifier ident = new Identifier (parent, id.getText ());
972                 prim_exp = (AST) ident;
973           }
974         | l = literal [parent] { prim_exp = l; }
975         | l = array_literal [parent] { prim_exp = l; }
976         | OPEN_PARENS e = expr [parent] { prim_exp = e; } CLOSE_PARENS
977         ; 
979 // object_literal [AST parent] returns [ObjectLiteral obj_lit]
980 // {
981 //      obj_lit = new ObjectLiteral (parent);
982 //      AST e = null;
983 //      ObjectLiteralItem item = null;
984 //      PropertyName pn = null;
985 // }
986 //      : OPEN_BRACE 
987 //         ((property_name COLON)=> pn = property_name COLON e = assignment_expr [obj_lit]
988 //          { 
989 //                  item = new ObjectLiteralItem ();
990 //                  item.property_name = pn.Name; 
991 //                  item.exp = e; 
992 //                  obj_lit.Add (item); 
993 //          } 
994 //          (COMMA pn = property_name COLON e = assignment_expr [obj_lit] 
995 //          { 
996 //                  item = new ObjectLiteralItem ();
997 //                  item.property_name = pn.Name;
998 //                  item.exp = e;
999 //                  obj_lit.Add (item); 
1000 //          })*
1001 //         )
1002 //        CLOSE_BRACE
1003 //      ;
1005 literal [AST parent] returns [AST l]
1007         l = null; 
1009         : "null"
1010         | "true"
1011           {
1012                   BooleanLiteral bl = new BooleanLiteral (parent, true);
1013                   l = bl;
1014           }
1015         | "false"
1016           {
1017                   BooleanLiteral bl = new BooleanLiteral (parent, false);
1018                   l = bl;
1019           }
1020         | s:STRING_LITERAL
1021           {
1022                   StringLiteral str = new StringLiteral (parent, s.getText ());
1023                   l = str;
1024           }      
1025         | l = numeric_literal [parent]
1026         ;
1028 property_name_and_value_list
1029         : (property_name COLON primary_expr [null])+
1030         ;
1032 property_name returns [PropertyName pn]
1033 { pn = new PropertyName (); }
1034         : (id:IDENTIFIER { pn.Name = id.getText (); } 
1035           |st:STRING_LITERAL { pn.Name = st.getText (); } 
1036           |numeric_literal [null] { pn.Name = string.Empty; }
1037           )
1038         ;
1040 array_literal [AST parent] returns [ArrayLiteral array_lit]
1042         array_lit = new ArrayLiteral (parent);
1043         AST e = null;
1044         ASTList elems = ((ArrayLiteral) array_lit).elems;
1045         int i = 0;
1047         : OPEN_BRACKET 
1048                   (e = primary_expr [array_lit] 
1049                   { if (e != null) { 
1050                           elems.Add (e); 
1051                           array_lit.size++;
1052                     } 
1053                   } (COMMA e = primary_expr [array_lit] 
1054                            { 
1055                                   if (e != null) { 
1056                                           elems.Add (e); 
1057                                           array_lit.size++; 
1058                                   }
1059                            }
1060                     )* | ) 
1061           CLOSE_BRACKET
1062         ;       
1064 numeric_literal [AST parent] returns [NumericLiteral num_lit]
1066         num_lit = null;
1068         : d:DECIMAL_LITERAL { num_lit = new NumericLiteral (parent, System.Convert.ToSingle (d.getText ())); }
1069         | HEX_INTEGER_LITERAL
1070         ;
1073 line_terminator
1074         : LINE_FEED
1075         | CARRIAGE_RETURN
1076         | LINE_SEPARATOR
1077         | PARAGRAPH_SEPARATOR
1078         ;
1080 white_space
1081         : TAB
1082         | VERTICAL_TAB
1083         | FORM_FEED
1084         | SPACE
1085         | NO_BREAK_SPACE
1086         ;
1089 // Lexer
1092 class JScriptLexer extends Lexer;
1094 options {
1095         charVocabulary = '\u0000'..'\uFFFE';
1096         testLiterals = false;
1097         k = 3;
1099 tokens {
1100         IN = "in";
1101         INSTANCE_OF = "instanceof";
1104 DECIMAL_LITERAL: ('0'  | ('1'..'9')('0'..'9')*) (DOT ('0'..'9')* | ) (('e' | 'E') (('+' | '-' | ) ('0'..'9')+) | )
1105     ;
1107 HEX_INTEGER_LITERAL: '0' ('x' | 'X') ('0'..'9' | 'a'..'f' | 'A'..'F')+
1108     ;
1110 STRING_LITERAL
1111         : '"'! (~('"' | '\\' | '\u000A' | '\u000D' | '\u2028' | '\u2029'))* '"'! | 
1112           '\''! (~('\'' | '\\' | '\u000A' | '\u000D' | '\u2028' | '\u2029'))*'\''!
1113         ;
1115 IDENTIFIER
1116 options { testLiterals = true; }
1117         : ('a'..'z' | 'A'..'Z') ('a'..'z' | 'A'..'Z' | '0'..'9')*
1118         ;
1121 // Operators
1123 DOT: '.';
1124 COMMA: ',';
1126 INCREMENT: "++";
1127 DECREMENT: "--";
1128 PLUS: '+';
1129 MINUS: '-';
1130 BITWISE_NOT: '~';
1131 LOGICAL_NOT: '!';
1133 MULT: '*';
1134 DIVISION: '/';
1135 MODULE: '%';
1136 ASSIGN: '=';
1139 SHIFT_LEFT: "<<";
1140 SHIFT_RIGHT: ">>";
1141 UNSIGNED_SHIFT_RIGHT: ">>>";
1142         
1143 LESS_THAN: '<';
1144 GREATER_THAN: '>';
1145 LESS_EQ: "<=";
1146 GREATER_EQ: ">=";
1148 EQ: "==";
1149 NEQ: "!=";
1150 STRICT_EQ: "===";
1151 STRICT_NEQ: "!==";
1153 MULT_ASSIGN: "*=";
1154 DIV_ASSIGN: "/=";
1155 MOD_ASSIGN: "%=";
1156 ADD_ASSIGN: "+=";
1157 SUB_ASSIGN: "-=";
1158 SHIFT_LEFT_ASSIGN: "<<=";
1159 SHIFT_RIGHT_ASSIGN: ">>=";
1160 AND_ASSIGN: "&=";
1161 XOR_ASSIGN: "^=";
1162 OR_ASSIGN: "|=";
1163 INTERR: '?';
1164 LOGICAL_OR: "||";
1165 LOGICAL_AND: "&&";
1166 BITWISE_OR: '|';
1167 BITWISE_AND: '&';
1168 BITWISE_XOR: '^';
1171 OPEN_PARENS: '(';
1172 CLOSE_PARENS: ')';
1173 OPEN_BRACKET: '[';
1174 CLOSE_BRACKET: ']';
1175 OPEN_BRACE: '{';
1176 CLOSE_BRACE: '}';
1179 // Punctuators
1181 SEMI_COLON: ';';
1182 COLON: ':';
1186 // Comments
1189 SL_COMMENT
1190         : "//" (~('\u000A' | '\u000D' | '\u2028' | '\u2029'))*
1191           { $setType (Token.SKIP); }
1192         ;
1194 ML_COMMENT
1195         : "/*"
1196         (options {
1197                 generateAmbigWarnings=false;
1198         }
1199         :
1200                 { LA(2)!='/' }? '*'
1201         |       '\r' '\n'               { newline(); }
1202         |       '\r'                    { newline(); }
1203         |       '\n'                    { newline(); }
1204         |       ~('*'|'\n'|'\r')
1205         )*
1206         "*/"
1207         { $setType (Token.SKIP); }
1208         ;
1211 // Line terminator tokens
1213 LINE_FEED
1214         : '\u000A' { $setType (Token.SKIP); newline (); }
1215         ;
1217 CARRIAGE_RETURN
1218         : '\u000D' { $setType (Token.SKIP); newline ();}
1219         ;
1221 LINE_SEPARATOR
1222         : '\u2028' { $setType (Token.SKIP); newline ();}
1223         ;
1225 PARAGRAPH_SEPARATOR
1226         : '\u2029' { $setType (Token.SKIP); newline ();}
1227         ;
1230 // White space tokens
1233         : '\u0009' { $setType (Token.SKIP); }
1234         ;
1236 VERTICAL_TAB
1237         : '\u000B' { $setType (Token.SKIP); }
1238         ;
1240 FORM_FEED
1241         : '\u000C' { $setType (Token.SKIP); }
1242         ;
1244 SPACE
1245         : '\u0020' { $setType (Token.SKIP); }
1246         ;
1248 NO_BREAK_SPACE
1249         : '\u00A0' { $setType (Token.SKIP); }
1250         ;