Home | History | Annotate | Download | only in dasm
      1 /*
      2  * parser.cup - Java CUP file containing LALR(1) grammar for DASM
      3  */
      4 
      5 package dasm;
      6 
      7 import java_cup.runtime.*;
      8 
      9 import dasm.tokens.number_token;
     10 import dasm.tokens.relative_number_token;
     11 import dasm.tokens.variant_token;
     12 
     13 action code {:
     14     int access_val;
     15     public DAsm dAsm;
     16     public Scanner scanner;
     17     public boolean isInterface;
     18 :};
     19 
     20 parser 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 
     48 init with {:
     49     action_obj.scanner = scanner;
     50     action_obj.dAsm = dAsm;
     51 :};
     52 
     53 scan with {:
     54     return scanner.next_token();
     55 :};
     56 
     57 
     58 
     59 /* Terminals (tokens returned by the scanner). */
     60 terminal 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 
     86 terminal str_token Str, Word, Insn;
     87 terminal int_token Int;
     88 terminal number_token Num;
     89 terminal relative_number_token Relative;
     90 
     91 non terminal str_token classname, inner_name, inner_inner, inner_outer, optional_signature;
     92 non terminal variant_token optional_default, item, any_item;
     93 
     94 /* Non terminals */
     95 non 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 
    122 non terminal int_token access;
    123 
    124 /* The grammar */
    125 
    126 dasm_file ::= dasm_file_classes;
    127 
    128 dasm_file_classes ::= dasm_file_classes dasm_file_class | dasm_file_class;
    129 
    130 dasm_file_class ::=
    131         dasm_header
    132         inners
    133         fields
    134         methods
    135 ;
    136 
    137 dasm_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 
    153 dex_version_spec ::=
    154     DBYTECODE Num:n SEP
    155         {: dAsm.setVersion(n.number_val); :}
    156     |
    157     /* nothing */
    158 ;
    159 
    160 /* ========== Source specification ========== */
    161 
    162 source_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 
    175 class_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 
    188 classname ::= Word:w
    189         {: RESULT.str_val = Utils.convertDotsToSlashes(w.str_val); :}
    190 ;
    191 
    192 access ::=
    193     {: access_val = 0; :}
    194         access_list
    195     {: RESULT.int_val = access_val; :}
    196 ;
    197 
    198 
    199 access_list ::= access_items | ;
    200 access_items ::= access_items access_item | access_item ;
    201 
    202 access_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 
    242 super_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 
    256 implements ::= implements_list | /* empty */ ;
    257 
    258 implements_list ::= implements_list implements_spec | implements_spec ;
    259 
    260 implements_spec ::= DIMPLEMENTS classname:name SEP
    261     {: dAsm.addInterface(name.str_val); :}
    262 ;
    263 
    264 /* ========== Signature specification  ========== */
    265 
    266 signature_spec ::=
    267     DSIGNATURE signature_expr SEP
    268     |
    269     /* nothing */
    270 ;
    271 
    272 signature_expr ::= Str:sig
    273         {: dAsm.setSignature(sig.str_val); :}
    274 ;
    275 
    276 /* ========== EnclosingMethod attribute specification ========== */
    277 
    278 enclosing_spec ::=
    279     DENCLOSING METHOD Word:w SEP
    280         {: dAsm.setEnclosingMethod(w.str_val); :}
    281     |
    282     /* nothing */
    283 ;
    284 
    285 
    286 
    287 /* ========== Deprecated attribute ========== */
    288 
    289 deprecated_spec ::=
    290     DDEPRECATED deprecated_expr SEP
    291     |
    292     /* nothing */
    293 ;
    294 
    295 deprecated_expr ::=
    296     {: /*dAsm.setDeprecated();*/dAsm.report_error("WARNING: @deprecated is not supported"); :}
    297 ;
    298 
    299 
    300 /* ========== Annotation specification ========== */
    301 annotations ::= ann_cls_list |
    302     // empty
    303     ;
    304 
    305 ann_cls_list ::= ann_cls_list ann_cls_spec | ann_cls_spec ;
    306 
    307 ann_cls_spec ::= ann_cls_expr ann_arglist endannotationsep ;
    308 
    309 endannotationsep ::= endannotation SEP ;
    310 
    311 endannotation ::= DEND ANNOTATION
    312     {: //TODO: NOT SUPPORTED dAsm.endAnnotation();
    313             dAsm.report_error("WARNING: Annotations are not supported"); :}
    314 ;
    315 
    316 ann_cls_expr ::= DANNOTATION ann_clf_expr ;
    317 
    318 ann_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 ;
    327 ann_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 
    345 ann_arglist ::= ann_arg_list |
    346                 // empty
    347 ;
    348 
    349 ann_arg_list ::= ann_arg_list ann_arg_spec | ann_arg_spec ;
    350 
    351 ann_arg_spec ::= ann_arg_expr EQ ann_value_list ;
    352 
    353 ann_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 
    363 ann_def_spec ::= DEFAULT SEP
    364     {: //TODO: NOT SUPPORTED dAsm.addAnnotation();
    365             dAsm.report_error("WARNING: Annotations are not supported"); :}
    366 ;
    367 
    368 ann_value_list ::= ann_value_items SEP | ann_ann_list ;
    369 
    370 ann_value_items ::= ann_value_items ann_value | ann_value ;
    371 
    372 ann_value ::= any_item:v
    373     {: //TODO: NOT SUPPORTED dAsm.addAnnotationValue(v.variant_val);
    374             dAsm.report_error("WARNING: Annotations are not supported"); :}
    375 ;
    376 ann_ann_list ::= ann_ann_list ann_ann_value | ann_ann_value ;
    377 
    378 ann_ann_value ::= DANNOTATION ann_nest ann_arglist endannotationsep ;
    379 
    380 ann_nest ::= SEP
    381     {: //TODO: NOT SUPPORTED dAsm.nestAnnotation();
    382             dAsm.report_error("WARNING: Annotations are not supported"); :}
    383 ;
    384 
    385 ann_def_val ::= ann_def_expr EQ ann_value_list ;
    386 
    387 ann_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 
    401 generic_attributes ::= generic_list | /* empty */ ;
    402 
    403 generic_list ::= generic_list generic_spec | generic_spec ;
    404 
    405 generic_spec ::= DATTRIBUTE generic_expr SEP ;
    406 
    407 generic_expr ::= Word:name Str:file
    408         {: dAsm.addGenericAttr(name.str_val, file.str_val); :}
    409 ;
    410 
    411 
    412 /* ========== Fields ========== */
    413 
    414 fields ::= field_list | /* empty */ ;
    415 
    416 field_list ::= field_list field_spec | field_spec ;
    417 
    418 field_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
    431 optional_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
    440 field_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 
    445 endfield ::= DEND FIELD SEP
    446       {: dAsm.endField(); :}
    447 ;
    448 
    449 field_exts ::= field_ext_list | /* empty */ ;
    450 
    451 field_ext_list ::= field_ext_list field_ext_expr | field_ext_expr ;
    452 
    453 field_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
    465 item ::=
    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
    473 any_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 ========== */
    480 inners ::= inner_list |
    481     // empty
    482 ;
    483 
    484 inner_list ::= inner_list inner_spec | inner_spec ;
    485 
    486 inner_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 
    497 inner_name ::=
    498     Word:w
    499         {: RESULT.str_val = w.str_val; :}
    500     |
    501     // empty
    502         {: RESULT.str_val = null; :}
    503 ;
    504 
    505 inner_inner ::=
    506     INNER classname:w
    507         {: RESULT.str_val = w.str_val; :}
    508     |
    509     // empty
    510         {: RESULT.str_val = null; :}
    511 ;
    512 
    513 inner_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 
    524 methods ::= method_list | /* empty */;
    525 
    526 method_list ::= method_list method_spec | method_spec ;
    527 
    528 method_spec ::=
    529     defmethod
    530     statements
    531     endmethod
    532     |
    533     defmethod endmethod
    534  ;
    535 
    536 defmethod ::=
    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 
    542 endmethod ::=
    543     DEND METHOD SEP
    544         {: dAsm.endMethod(); :}
    545 ;
    546 
    547 
    548 /* ========== Statements in a method ========== */
    549 
    550 statements ::= statements statement | statement ;
    551 
    552 statement ::=
    553         {: dAsm.setLine(scanner.token_line_num); :}
    554     stmnt SEP
    555 ;
    556 
    557 stmnt ::=
    558     instruction
    559     |
    560     directive
    561     |
    562     error
    563     |
    564     label
    565     |
    566     /* empty */
    567 ;
    568 
    569 
    570 // label:
    571 label ::=
    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 
    581 directive ::=
    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 //
    610 var_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
    625 optional_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>
    635 limit_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>
    645 line_expr ::= Int:v
    646       {: dAsm.addLine(v.int_val); :}
    647 ;
    648 
    649 // .throws <class>
    650 throws_expr ::= classname:s
    651       {: dAsm.addThrow(s.str_val); :}
    652 ;
    653 
    654 // .catch <class> from <label1> to <label2> using <branchlab>
    655 catch_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>
    670 set_expr ::=
    671     Word:name any_item:v
    672         {: scanner.dict.put(name.str_val, v); :}
    673 ;
    674 
    675 instruction ::=
    676     simple_instruction
    677     |
    678     complex_instruction
    679 ;
    680 
    681 // Various patterns of instruction:
    682 //      instruction [<pattern>]
    683 simple_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 
    738 complex_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
    751 fa_data ::=
    752    fa_data_args
    753    fa_data_list
    754    fa_data_end
    755 ;
    756 
    757 fa_data_args ::=
    758     Word:r Word:t SEP     // <register> <type>
    759         {: dAsm.newFillArrayData(r.str_val, t.str_val); :}
    760 ;
    761 
    762 fa_data_list ::= fa_data_list fa_data_entry | fa_data_entry ;
    763 
    764 fa_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 
    772 fa_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
    783 ps_table ::=
    784    ps_table_args
    785    ps_table_list
    786    ps_table_end
    787 ;
    788 
    789 ps_table_args ::=
    790     Word:r Int:k SEP     // <register> <first_key>
    791         {: dAsm.newPackedSwitch(r.str_val, k.int_val); :}
    792 ;
    793 
    794 ps_table_list ::= ps_table_list ps_table_entry | ps_table_entry ;
    795 
    796 ps_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 
    804 ps_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
    814 ss_table ::=
    815     ss_table_args
    816     ss_table_list
    817     ss_table_end
    818 ;
    819 
    820 ss_table_args ::=
    821     Word:r SEP     // <register>
    822         {: dAsm.newSparseSwitch(r.str_val); :}
    823 ;
    824 
    825 ss_table_list ::= ss_table_list ss_table_entry | ss_table_entry ;
    826 
    827 ss_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 
    835 ss_table_end ::=
    836     SPARSE_SWITCH_END
    837         {: dAsm.endSwitch(); :}
    838 ;
    839