1/*
2 * parser.cup - Java CUP file containing LALR(1) grammar for DASM
3 */
4
5package dasm;
6
7import java_cup.runtime.*;
8
9import dasm.tokens.number_token;
10import dasm.tokens.relative_number_token;
11import dasm.tokens.variant_token;
12
13action code {:
14    int access_val;
15    public DAsm dAsm;
16    public Scanner scanner;
17    public boolean isInterface;
18:};
19
20parser code {:
21
22    public boolean isInterface;
23    public Scanner scanner;
24    public DAsm dAsm;
25
26    public void report_error(String message, Object info) {
27            if(info != null)
28                dAsm.report_error("Warning: " + message + "(" + info.toString() + ")");
29            else
30                dAsm.report_error("Warning: " + message);
31    }
32
33    public void report_fatal_error(String message, Object info)  {
34            if(info != null)
35                dAsm.report_error("Error: " + message + "(" + info.toString() + ")");
36            else
37                dAsm.report_error("Error: " + message);
38    }
39
40    parser(DAsm dAsm, Scanner scanner) {
41        super();
42
43        this.scanner = scanner;
44        this.dAsm = dAsm;
45    }
46:};
47
48init with {:
49    action_obj.scanner = scanner;
50    action_obj.dAsm = dAsm;
51:};
52
53scan with {:
54    return scanner.next_token();
55:};
56
57
58
59/* Terminals (tokens returned by the scanner). */
60terminal token
61    // Directives (words beginning with a '.')
62    DCATCH, DCLASS, DEND, DFIELD, DLIMIT, DLINE, DMETHOD, DSET, DSUPER,
63    DSOURCE, DTHROWS, DVAR, DIMPLEMENTS, DINTERFACE, DBYTECODE, DDEBUG,
64    DENCLOSING, DSIGNATURE, DATTRIBUTE, DDEPRECATED, DINNER,
65    DANNOTATION,
66
67    // keywords for directives
68    USING, IS, FROM, METHOD, SIGNATURE, REGS, FIELD, CLASS,
69    TO, INNER, OUTER, VISIBLE, INVISIBLE, VISIBLEPARAM, INVISIBLEPARAM,
70
71    // access types
72    ABSTRACT, FINAL, INTERFACE, NATIVE, PRIVATE, PROTECTED, PUBLIC, STATIC,
73    SYNCHRONIZED, DECLARED_SYNCHRONIZED, TRANSIENT, VOLATILE,
74    // added these for java 1.5 compliance :
75    ANNOTATION, ENUM, BRIDGE, VARARGS, STRICT, SYNTHETIC,
76    // complex instructions
77    FILL_ARRAY_DATA, FILL_ARRAY_DATA_END,
78    PACKED_SWITCH, PACKED_SWITCH_END,
79    SPARSE_SWITCH, SPARSE_SWITCH_END,
80    DEFAULT,
81
82    // special symbols
83    EQ, SEP, COLON
84 ;
85
86terminal str_token Str, Word, Insn;
87terminal int_token Int;
88terminal number_token Num;
89terminal relative_number_token Relative;
90
91non terminal str_token classname, inner_name, inner_inner, inner_outer, optional_signature;
92non terminal variant_token optional_default, item, any_item;
93
94/* Non terminals */
95non terminal symbol
96       access_item, access_items, access_list, catch_expr, class_spec,
97       complex_instruction, defmethod, directive, endmethod, field_list,
98       field_spec, fields, instruction, implements, implements_list, implements_spec,
99       dasm_file, dasm_file_classes, dasm_file_class, label, limit_expr,
100       method_list,
101       method_spec, methods, set_expr, simple_instruction, source_spec,
102       statement, statements, stmnt, super_spec, line_expr,
103       throws_expr, var_expr, dex_version_spec,
104       enclosing_spec, signature_spec, signature_expr, dasm_header,
105       deprecated_spec, deprecated_expr,
106       generic_attributes, generic_list, generic_spec, generic_expr,
107       field_start, endfield, field_exts, field_ext_list, field_ext_expr,
108       inners, inner_list, inner_spec,
109       fa_data, fa_data_args, fa_data_list, fa_data_entry, fa_data_end,
110       ps_table, ps_table_args, ps_table_list, ps_table_entry, ps_table_end,
111       ss_table, ss_table_args, ss_table_list, ss_table_entry, ss_table_end,
112
113   // used for Annotation attributes :
114       annotations, ann_cls_list, ann_cls_spec, endannotation, ann_cls_expr,
115       ann_clf_expr, ann_met_expr, ann_arglist, ann_arg_list, ann_arg_spec,
116       ann_def_spec, ann_def_val, ann_value_items, ann_value, ann_def_expr,
117       ann_arg_expr, ann_nest, endannotationsep, ann_ann_value, ann_ann_list,
118       ann_value_list
119
120;
121
122non terminal int_token access;
123
124/* The grammar */
125
126dasm_file ::= dasm_file_classes;
127
128dasm_file_classes ::= dasm_file_classes dasm_file_class | dasm_file_class;
129
130dasm_file_class ::=
131        dasm_header
132        inners
133        fields
134        methods
135;
136
137dasm_header ::=
138    dex_version_spec
139    source_spec
140    class_spec
141    super_spec
142    implements
143    signature_spec
144    enclosing_spec
145    deprecated_spec
146    annotations
147    generic_attributes
148  {: dAsm.endHeader(); :}
149;
150
151/* ========== Dex version specification ========== */
152
153dex_version_spec ::=
154    DBYTECODE Num:n SEP
155        {: dAsm.setVersion(n.number_val); :}
156    |
157    /* nothing */
158;
159
160/* ========== Source specification ========== */
161
162source_spec ::=
163    DSOURCE Str:s SEP
164        {: dAsm.setSource(s.str_val); :}
165    |
166    DSOURCE Word:w SEP
167        {: dAsm.setSource(w.str_val); :}
168    |
169    /* nothing */
170;
171
172
173/* ========== Class specification ========== */
174
175class_spec ::=
176    DCLASS access:a classname:name SEP
177        {: isInterface = false;
178           dAsm.setClass(name.str_val,
179                (a.int_val)); :}
180    |
181    DINTERFACE access:a classname:name SEP
182        {: isInterface = true;
183           dAsm.setClass(name.str_val,
184                (a.int_val |
185                        com.android.dx.rop.code.AccessFlags.ACC_INTERFACE)); :}
186;
187
188classname ::= Word:w
189        {: RESULT.str_val = Utils.convertDotsToSlashes(w.str_val); :}
190;
191
192access ::=
193    {: access_val = 0; :}
194        access_list
195    {: RESULT.int_val = access_val; :}
196;
197
198
199access_list ::= access_items | ;
200access_items ::= access_items access_item | access_item ;
201
202access_item ::=
203    PUBLIC       {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_PUBLIC; :}
204    |
205    PRIVATE      {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_PRIVATE; :}
206    |
207    PROTECTED    {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_PROTECTED; :}
208    |
209    STATIC       {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_STATIC; :}
210    |
211    FINAL        {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_FINAL; :}
212    |
213    SYNCHRONIZED {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_SYNCHRONIZED; :}
214    |
215    VOLATILE     {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_VOLATILE; :}
216    |
217    TRANSIENT    {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_TRANSIENT; :}
218    |
219    NATIVE       {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_NATIVE; :}
220    |
221    INTERFACE    {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_INTERFACE; :}
222    |
223    ABSTRACT     {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_ABSTRACT; :}
224    |
225    ANNOTATION   {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_ANNOTATION; :}
226    |
227    ENUM         {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_ENUM; :}
228    |
229    BRIDGE       {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_BRIDGE; :}
230    |
231    VARARGS      {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_VARARGS; :}
232    |
233    STRICT       {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_STRICT; :}
234    |
235    SYNTHETIC    {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_SYNTHETIC; :}
236    |
237    DECLARED_SYNCHRONIZED {: access_val |= com.android.dx.rop.code.AccessFlags.ACC_DECLARED_SYNCHRONIZED; :}
238;
239
240/* ========== Superclass specification ========== */
241
242super_spec ::=
243    DSUPER classname:name SEP
244        {: dAsm.setSuperClass(name.str_val); :}
245        |
246        /* nothing */
247        {: if(isInterface == false)
248               dAsm.setSuperClass("java/lang/Object");
249           else
250           // Dalvik requires interfaces to have superclass
251               dAsm.setSuperClass("java/lang/Object"); :}
252;
253
254/* ========== Implements specification ========== */
255
256implements ::= implements_list | /* empty */ ;
257
258implements_list ::= implements_list implements_spec | implements_spec ;
259
260implements_spec ::= DIMPLEMENTS classname:name SEP
261    {: dAsm.addInterface(name.str_val); :}
262;
263
264/* ========== Signature specification  ========== */
265
266signature_spec ::=
267    DSIGNATURE signature_expr SEP
268    |
269    /* nothing */
270;
271
272signature_expr ::= Str:sig
273        {: dAsm.setSignature(sig.str_val); :}
274;
275
276/* ========== EnclosingMethod attribute specification ========== */
277
278enclosing_spec ::=
279    DENCLOSING METHOD Word:w SEP
280        {: dAsm.setEnclosingMethod(w.str_val); :}
281    |
282    /* nothing */
283;
284
285
286
287/* ========== Deprecated attribute ========== */
288
289deprecated_spec ::=
290    DDEPRECATED deprecated_expr SEP
291    |
292    /* nothing */
293;
294
295deprecated_expr ::=
296    {: /*dAsm.setDeprecated();*/dAsm.report_error("WARNING: @deprecated is not supported"); :}
297;
298
299
300/* ========== Annotation specification ========== */
301annotations ::= ann_cls_list |
302    // empty
303    ;
304
305ann_cls_list ::= ann_cls_list ann_cls_spec | ann_cls_spec ;
306
307ann_cls_spec ::= ann_cls_expr ann_arglist endannotationsep ;
308
309endannotationsep ::= endannotation SEP ;
310
311endannotation ::= DEND ANNOTATION
312    {: //TODO: NOT SUPPORTED dAsm.endAnnotation();
313            dAsm.report_error("WARNING: Annotations are not supported"); :}
314;
315
316ann_cls_expr ::= DANNOTATION ann_clf_expr ;
317
318ann_clf_expr ::=
319    VISIBLE classname:name SEP
320        {: //TODO: NOT SUPPORTED dAsm.addAnnotation(true, name.str_val);
321            dAsm.report_error("WARNING: Annotations are not supported"); :}
322    |
323    INVISIBLE classname:name SEP
324        {: //TODO: NOT SUPPORTED dAsm.addAnnotation(false, name.str_val);
325            dAsm.report_error("WARNING: Annotations are not supported"); :}
326;
327ann_met_expr ::=
328    VISIBLE classname:name SEP
329        {: //TODO: NOT SUPPORTED dAsm.addAnnotation(true, name.str_val);
330            dAsm.report_error("WARNING: Annotations are not supported"); :}
331    |
332    INVISIBLE classname:name SEP
333        {: //TODO: NOT SUPPORTED dAsm.addAnnotation(false, name.str_val);
334            dAsm.report_error("WARNING: Annotations are not supported"); :}
335    |
336    VISIBLEPARAM Int:n classname:name SEP
337        {: //TODO: NOT SUPPORTED dAsm.addAnnotation(true, name.str_val, n.int_val);
338            dAsm.report_error("WARNING: Annotations are not supported"); :}
339    |
340    INVISIBLEPARAM Int:n classname:name SEP
341        {: //TODO: NOT SUPPORTED dAsm.addAnnotation(false, name.str_val, n.int_val);
342            dAsm.report_error("WARNING: Annotations are not supported"); :}
343;
344
345ann_arglist ::= ann_arg_list |
346                // empty
347;
348
349ann_arg_list ::= ann_arg_list ann_arg_spec | ann_arg_spec ;
350
351ann_arg_spec ::= ann_arg_expr EQ ann_value_list ;
352
353ann_arg_expr ::=
354    Word:n Word:dsc
355    {: //TODO: NOT SUPPORTED dAsm.addAnnotationField(n.str_val, dsc.str_val, null);
356            dAsm.report_error("WARNING: Annotations are not supported"); :}
357    |
358    Word:n Word:dsc Word:sub
359    {: //TODO: NOT SUPPORTED dAsm.addAnnotationField(n.str_val, dsc.str_val, sub.str_val);
360            dAsm.report_error("WARNING: Annotations are not supported"); :}
361;
362
363ann_def_spec ::= DEFAULT SEP
364    {: //TODO: NOT SUPPORTED dAsm.addAnnotation();
365            dAsm.report_error("WARNING: Annotations are not supported"); :}
366;
367
368ann_value_list ::= ann_value_items SEP | ann_ann_list ;
369
370ann_value_items ::= ann_value_items ann_value | ann_value ;
371
372ann_value ::= any_item:v
373    {: //TODO: NOT SUPPORTED dAsm.addAnnotationValue(v.variant_val);
374            dAsm.report_error("WARNING: Annotations are not supported"); :}
375;
376ann_ann_list ::= ann_ann_list ann_ann_value | ann_ann_value ;
377
378ann_ann_value ::= DANNOTATION ann_nest ann_arglist endannotationsep ;
379
380ann_nest ::= SEP
381    {: //TODO: NOT SUPPORTED dAsm.nestAnnotation();
382            dAsm.report_error("WARNING: Annotations are not supported"); :}
383;
384
385ann_def_val ::= ann_def_expr EQ ann_value_list ;
386
387ann_def_expr ::=
388    Word:dsc
389    {: //TODO: NOT SUPPORTED dAsm.addAnnotationField(null, dsc.str_val, null);
390            dAsm.report_error("WARNING: Annotations are not supported"); :}
391    |
392    Word:dsc Word:sub
393    {: //TODO: NOT SUPPORTED dAsm.addAnnotationField(null, dsc.str_val, sub.str_val);
394            dAsm.report_error("WARNING: Annotations are not supported"); :}
395;
396
397
398
399/* ========== Generic attributes specification ========== */
400
401generic_attributes ::= generic_list | /* empty */ ;
402
403generic_list ::= generic_list generic_spec | generic_spec ;
404
405generic_spec ::= DATTRIBUTE generic_expr SEP ;
406
407generic_expr ::= Word:name Str:file
408        {: dAsm.addGenericAttr(name.str_val, file.str_val); :}
409;
410
411
412/* ========== Fields ========== */
413
414fields ::= field_list | /* empty */ ;
415
416field_list ::= field_list field_spec | field_spec ;
417
418field_spec ::=
419    DFIELD access:a Word:name Word:desc SIGNATURE Str:sig optional_default:v SEP
420        {: dAsm.addField((short)a.int_val, name.str_val, desc.str_val,
421                              sig.str_val, v.variant_val); :}
422    |
423    DFIELD access:a Word:name Word:desc optional_default:v SEP
424        {: dAsm.addField((short)a.int_val, name.str_val, desc.str_val,
425                               null, v.variant_val); :}
426    |
427    DFIELD field_start field_exts endfield
428;
429
430// default value for a field
431optional_default ::=
432     EQ item:v
433        {: RESULT.variant_val = v.variant_val; :}
434     |
435     /* empty */
436        {: RESULT.variant_val = null; :}
437;
438
439// multiline form of field description
440field_start ::= access:a Word:name Word:desc optional_default:v SEP
441      {: dAsm.beginField((short)a.int_val, name.str_val,
442                              desc.str_val, v.variant_val); :}
443;
444
445endfield ::= DEND FIELD SEP
446      {: dAsm.endField(); :}
447;
448
449field_exts ::= field_ext_list | /* empty */ ;
450
451field_ext_list ::= field_ext_list field_ext_expr | field_ext_expr ;
452
453field_ext_expr ::=
454   DSIGNATURE signature_expr SEP
455   |
456   DATTRIBUTE generic_expr SEP
457   |
458   DDEPRECATED deprecated_expr SEP
459   |
460   DANNOTATION ann_clf_expr ann_arglist endannotationsep
461;
462
463
464// an item is an integer, a float/double/long, or a quoted string
465item ::=
466    Int:i       {: RESULT.variant_val = new Integer(i.int_val); :}
467    |
468    Num:n       {: RESULT.variant_val = n.number_val; :}
469    |
470    Str:s       {: RESULT.variant_val = s.str_val; :}
471;
472// an item is any possible type
473any_item ::=
474    Word:w      {: RESULT.variant_val = w.str_val; :}       // for enum
475    |
476    item:v      {: RESULT.variant_val = v.variant_val; :}
477;
478
479/* ========== Inner classes ========== */
480inners ::= inner_list |
481    // empty
482;
483
484inner_list ::= inner_list inner_spec | inner_spec ;
485
486inner_spec ::=
487    DINNER CLASS access:a inner_name:n inner_inner:i inner_outer:o SEP
488        {: dAsm.addInner((short)a.int_val,
489                              n.str_val, i.str_val, o.str_val); :}
490    |
491    DINNER INTERFACE access:a inner_name:n inner_inner:i inner_outer:o SEP
492        {: dAsm.addInner((short)(a.int_val |
493                              com.android.dx.rop.code.AccessFlags.ACC_INTERFACE),
494                                n.str_val, i.str_val, o.str_val); :}
495;
496
497inner_name ::=
498    Word:w
499        {: RESULT.str_val = w.str_val; :}
500    |
501    // empty
502        {: RESULT.str_val = null; :}
503;
504
505inner_inner ::=
506    INNER classname:w
507        {: RESULT.str_val = w.str_val; :}
508    |
509    // empty
510        {: RESULT.str_val = null; :}
511;
512
513inner_outer ::=
514    OUTER classname:w
515        {: RESULT.str_val = w.str_val; :}
516    |
517    // empty
518        {: RESULT.str_val = null; :}
519;
520
521
522/* ========== Methods ========== */
523
524methods ::= method_list | /* empty */;
525
526method_list ::= method_list method_spec | method_spec ;
527
528method_spec ::=
529    defmethod
530    statements
531    endmethod
532    |
533    defmethod endmethod
534 ;
535
536defmethod ::=
537    DMETHOD access:i Word:name SEP
538        {: String split[] = Utils.getMethodSignatureFromString(name.str_val);
539           dAsm.newMethod(split[0], split[1], i.int_val); :}
540;
541
542endmethod ::=
543    DEND METHOD SEP
544        {: dAsm.endMethod(); :}
545;
546
547
548/* ========== Statements in a method ========== */
549
550statements ::= statements statement | statement ;
551
552statement ::=
553        {: dAsm.setLine(scanner.token_line_num); :}
554    stmnt SEP
555;
556
557stmnt ::=
558    instruction
559    |
560    directive
561    |
562    error
563    |
564    label
565    |
566    /* empty */
567;
568
569
570// label:
571label ::=
572    Word:label COLON
573        {: dAsm.plantLabel(label.str_val); :}
574    |
575    Int:label COLON instruction
576        {: dAsm.plantLabel(String.valueOf(label.int_val)); :}
577;
578
579// Directives (.catch, .set, .limit, etc.)
580
581directive ::=
582    DVAR var_expr
583    |
584    DLIMIT limit_expr
585    |
586    DLINE line_expr
587    |
588    DTHROWS throws_expr
589    |
590    DCATCH catch_expr
591    |
592    DSET set_expr
593    |
594    DSIGNATURE signature_expr
595    |
596    DATTRIBUTE generic_expr
597    |
598    DDEPRECATED deprecated_expr
599    |
600    DANNOTATION ann_met_expr ann_arglist endannotation
601    |
602    DANNOTATION ann_def_spec ann_def_val endannotation
603;
604
605
606//
607// .var <num> is <name> <desc> from StartLab to EndLab
608// .var <num> is <name> <desc> signature <sign> from StartLab to EndLab
609//
610var_expr ::=
611    Int:reg IS Word:name Word:desc optional_signature:sign FROM Word:slab TO Word:elab
612        {: dAsm.addVar(slab.str_val, elab.str_val, name.str_val,
613                            desc.str_val, sign.str_val, reg.int_val); :}
614    |
615    Int:reg IS Word:name Word:desc optional_signature:sign
616        {: dAsm.addVar(null, null, name.str_val, desc.str_val,
617                            sign.str_val,  reg.int_val); :}
618    |
619    Int:reg IS Word:name Word:desc optional_signature:sign FROM Int:soff TO Int:eoff
620        {: dAsm.addVar(soff.int_val, eoff.int_val, name.str_val,
621                            desc.str_val, sign.str_val, reg.int_val); :}
622;
623
624// optional signature specification for a .var
625optional_signature ::=
626     SIGNATURE Str:s
627        {: RESULT.str_val = s.str_val; :}
628     |
629     /* empty */
630        {: RESULT.str_val = null; :}
631;
632
633
634// .limit regs <val>
635limit_expr ::=
636    REGS Int:v        // .limit regs
637      {: dAsm.setRegsSize(v.int_val); :}
638   |
639   Word:w Int:v
640      {: dAsm.report_error(".limit expected \"regs\" , but got "
641                                + w.str_val); :}
642;
643
644// .line <num>
645line_expr ::= Int:v
646      {: dAsm.addLine(v.int_val); :}
647;
648
649// .throws <class>
650throws_expr ::= classname:s
651      {: dAsm.addThrow(s.str_val); :}
652;
653
654// .catch <class> from <label1> to <label2> using <branchlab>
655catch_expr ::=
656    classname:aclass FROM Word:fromlab TO Word:tolab USING Word:branchlab
657        {: dAsm.addCatch(aclass.str_val,
658                              fromlab.str_val,
659                              tolab.str_val,
660                              branchlab.str_val); :}
661    |
662    classname:aclass FROM Int:fromoff TO Int:tooff USING Int:branchoff
663        {: dAsm.addCatch(aclass.str_val,
664                              fromoff.int_val,
665                              tooff.int_val,
666                              branchoff.int_val); :}
667;
668
669// .set <var> = <val>
670set_expr ::=
671    Word:name any_item:v
672        {: scanner.dict.put(name.str_val, v); :}
673;
674
675instruction ::=
676    simple_instruction
677    |
678    complex_instruction
679;
680
681// Various patterns of instruction:
682//      instruction [<pattern>]
683simple_instruction ::=
684    /* Format: 10x */
685    Insn:i
686        {: dAsm.addOpcode(i.str_val); :}
687    |
688    /* Format: 11x, 10t, 20t, 30t */
689    Insn:i Word:n
690        {: dAsm.addOpcode(i.str_val, n.str_val); :}
691    |
692    /* Format: relative 10t, 20t, 30t */
693    Insn:i Relative:n
694        {: dAsm.addRelativeGoto(i.str_val, n.int_val); :}
695    |
696    /* Format: 11n, 21s, 31i, 21h, 51l */
697    Insn:i Word:n1 Num:n2
698        {: dAsm.addOpcode(i.str_val, n1.str_val, n2.number_val); :}
699    |
700    /* Format: same as above. Handles the case when last argument is integer */
701    Insn:i Word:n1 Int:n2
702        {: dAsm.addOpcode(i.str_val, n1.str_val, new Integer(n2.int_val)); :}
703    |
704    /* Format: 12x, 22x, 32x, 21t, 21c (string@, type@), 31c, 35c, 3rc */
705    Insn:i Word:n1 Word:n2
706        {: dAsm.addOpcode(i.str_val, n1.str_val, n2.str_val); :}
707    |
708    /* Format: relative 21t */
709    Insn:i Word:n1 Relative:n2
710        {: dAsm.addRelativeGoto(i.str_val, n1.str_val, n2.int_val); :}
711    |
712    /* Format: 23x, 22t, 21c (field@), 22c */
713    Insn:i Word:n1 Word:n2 Word:n3
714        {: dAsm.addOpcode(i.str_val, n1.str_val, n2.str_val, n3.str_val); :}
715    |
716    /* Format: relative 22t */
717    Insn:i Word:n1 Word:n2 Relative:n3
718        {: dAsm.addRelativeGoto(i.str_val, n1.str_val, n2.str_val, n3.int_val); :}
719    |
720    /* Format: 22b, 22s */
721    Insn:i Word:n1 Word:n2 Int:n3
722        {: dAsm.addOpcode(i.str_val, n1.str_val, n2.str_val, n3.int_val); :}
723    |
724    /* Format: 21c (string@) */
725    Insn:i Word:n1 Str:n2
726        {: dAsm.addOpcode(i.str_val, n1.str_val, n2.str_val); :}
727    |
728    /* Format: 22c (field@)*/
729    Insn:i Word:n1 Word:n2 Word:n3 Word:n4
730        {: dAsm.addOpcode(i.str_val, n1.str_val, n2.str_val, n3.str_val, n4.str_val); :}
731  ;
732
733// complex (multiline) instructions
734//      fill-array-data <data>
735//      packed-switch  <table>
736//      sparse-switch <table>
737
738complex_instruction ::=
739    FILL_ARRAY_DATA fa_data
740    |
741    PACKED_SWITCH ps_table
742    |
743    SPARSE_SWITCH ss_table
744;
745
746// fill-array-data register type
747//      <value1>
748//      ...
749//      <valueN>
750// fill-array-data-end
751fa_data ::=
752   fa_data_args
753   fa_data_list
754   fa_data_end
755;
756
757fa_data_args ::=
758    Word:r Word:t SEP     // <register> <type>
759        {: dAsm.newFillArrayData(r.str_val, t.str_val); :}
760;
761
762fa_data_list ::= fa_data_list fa_data_entry | fa_data_entry ;
763
764fa_data_entry ::=
765    Num:data SEP
766        {: dAsm.addFillArrayData(data.number_val); :}
767    |
768    Int:data SEP
769        {: dAsm.addFillArrayData(new Integer(data.int_val)); :}
770;
771
772fa_data_end ::=
773    FILL_ARRAY_DATA_END
774        {: dAsm.endFillArrayData(); :}
775;
776
777
778// packed-switch register first_key
779//      <target1>
780//      ...
781//      <targetN>
782// packed-switch-end
783ps_table ::=
784   ps_table_args
785   ps_table_list
786   ps_table_end
787;
788
789ps_table_args ::=
790    Word:r Int:k SEP     // <register> <first_key>
791        {: dAsm.newPackedSwitch(r.str_val, k.int_val); :}
792;
793
794ps_table_list ::= ps_table_list ps_table_entry | ps_table_entry ;
795
796ps_table_entry ::=
797    Word:target SEP
798        {: dAsm.addPackedSwitchData(target.str_val); :}
799    |
800    Relative:target SEP
801        {: dAsm.addPackedSwitchData(target.int_val); :}
802;
803
804ps_table_end ::=
805    PACKED_SWITCH_END
806        {: dAsm.endSwitch(); :}
807;
808
809// sparse-switch register
810//     <value> : <label>
811//     <value> : <label>
812//     ...
813//     sparse-switch-end
814ss_table ::=
815    ss_table_args
816    ss_table_list
817    ss_table_end
818;
819
820ss_table_args ::=
821    Word:r SEP     // <register>
822        {: dAsm.newSparseSwitch(r.str_val); :}
823;
824
825ss_table_list ::= ss_table_list ss_table_entry | ss_table_entry ;
826
827ss_table_entry ::=
828    Int:i COLON Word:w SEP
829        {: dAsm.addSparseSwitchData(i.int_val, w.str_val); :}
830    |
831    Int:i COLON Relative:off SEP
832        {: dAsm.addSparseSwitchData(i.int_val, off.int_val); :}
833;
834
835ss_table_end ::=
836    SPARSE_SWITCH_END
837        {: dAsm.endSwitch(); :}
838;
839