// `script/gammar-src.js` is for human editing // `grammar.js` is generated by `opcode_processor.py` // Downstream tools must resolve the following: // * matching start and end of macro // * use of `]0` through `]8` in an invalid context // * limitations on use of local labels // * limitations of 6502 and 65C02 // * limitations of Merlin 8 // * identifying implied macro calls that overlap with (pseudo)opcode mnemonics // * verify that literal addresses or offsets are valid, e.g., lda -1 is accepted by the parser // * verify that label and column lengths are within limits // Known differences with legacy Merlin syntax: // Here semicolons and curly braces are unconditionally forbidden in labels // Here square brackets are forbidden in labels, except for start the start of variable token // dstrings must always be terminated const language_name = 'merlin6502'; const alphachars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; const prodoschars = '.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; // Define constants const ANYCHAR = /[\x20-\x7e]/; const DSTR_BR_BEG = /[\x20-\x2f\x39-\x7e]/; const ARG = "!\"#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; const GLOB_LAB_BEG = /[\x3f-\x5a\x5c\x5f-\x7a\x7e]/; const VAR_LAB_BEG = /[\x39-\x3a\x3f-\x5a\x5c\x5e-\x7a\x7c\x7e]/; const LAB_CHAR = /[\x30-\x3a\x3f-\x5a\x5c\x5e-\x7a\x7c\x7e]/; const DOS33_CHARS = " !\"#$%&'()*+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; const DOS33_TFLAG = "!\"#$%&'()*+,-./0123456789:;<=>?"; // Tree-sitter grammar definition module.exports = grammar({ name: language_name, extras: $ => [], conflicts: $ => [ [$.label_def,$.macro_def], [$.prodos_filename,$.dos33], ], rules: { source_file: $ => repeat($._factor), _factor: $ => choice( $._newline, seq($.heading,$._newline), // vscode highlights don't like newline included in the highlight seq(optional($._sep),$.comment, $._newline), $.program_counter, $.macro_call, alias($.macro_call_forced,$.macro_call), // downstream must activate this in line by line parsing $.operation, $.pseudo_operation // excludes implicit macro calls ), program_counter: $ => seq($.label_def,optional(seq($._sep,$.comment)),$._newline), // set label to program counter // Macros and labels macro_call: $ => seq(optional($.label_def),$._sep,$.macro_ref,optional(seq($._sep,$.arg_macro)),optional(seq($._sep,$.comment)),$._newline), macro_call_forced: $ => seq('\u0100',optional($.label_def),$._sep,$.macro_ref,optional(seq($._sep,$.arg_macro)),optional(seq($._sep,$.comment)),$._newline), _newline: $ => seq(optional($._sep),/\r?\n/), _sep: $ => /[ \t]+/, _arg_sep: $ => choice('.',',','/','-','(',' '), // separates macro call from arguments in the long form, e.g., PMC mymacro,myargs label_ref: $ => choice($.global_label,$.local_label,$.var_label), label_def: $ => choice($.global_label, $.local_label, $.var_label), macro_ref: $ => $.global_label, macro_def: $ => prec.dynamic(1,$.global_label), global_label: $ => token(seq(GLOB_LAB_BEG,repeat(LAB_CHAR))), // max 13 (8bit) or 26 (16bit) local_label: $ => token(seq(':',repeat1(LAB_CHAR))), // max 13 (8bit) or 26 (16bit),cannot be first label in program,in macro,MAC,ENT,EXT, or EQU var_label: $ => choice($._var,$.var_mac,$.var_cnt), _var: $ => token(seq(']', VAR_LAB_BEG, repeat(LAB_CHAR))), var_mac: $ => /\][1-8]/, var_cnt: $ => ']0', // dstrings delimited by quotes are specially treated in macro calls dq_str: $ => seq('"',/[\x20-\x21\x23-\x7e]*/,'"'), sq_str: $ => seq("'",/[\x20-\x26\x28-\x7e]*/,"'"), arg_macro: $ => seq($._arg,repeat(seq(';',$._arg))), _arg: $ => choice( $.imm, $.addr, $.addr_x, $.addr_y, $.iaddr_ix, $.iaddr_y, $.iaddr, $.daddr, $.daddr_y, $.addr_s, $.iaddr_is_y, alias($.dq_str,$.dstring), alias($.sq_str,$.dstring), $.arg_literal, ), arg_literal: $ => token(prec.left(-1,repeat1(choice(...ARG)))), // Operations op_adc: $ => seq(token(prec(1,caseTS('adc'))),optional($.trailing)), op_and: $ => seq(token(prec(1,caseTS('and'))),optional($.trailing)), op_asl: $ => seq(token(prec(1,caseTS('asl'))),optional($.trailing)), op_bcc: $ => seq(token(prec(1,choice(caseTS('bcc'),caseTS('blt')))),optional($.trailing)), op_bcs: $ => seq(token(prec(1,choice(caseTS('bcs'),caseTS('bge')))),optional($.trailing)), op_beq: $ => seq(token(prec(1,caseTS('beq'))),optional($.trailing)), op_bit: $ => seq(token(prec(1,caseTS('bit'))),optional($.trailing)), op_bmi: $ => seq(token(prec(1,caseTS('bmi'))),optional($.trailing)), op_bne: $ => seq(token(prec(1,caseTS('bne'))),optional($.trailing)), op_bpl: $ => seq(token(prec(1,caseTS('bpl'))),optional($.trailing)), op_bra: $ => seq(token(prec(1,caseTS('bra'))),optional($.trailing)), op_brk: $ => seq(token(prec(1,caseTS('brk'))),optional($.trailing)), op_brl: $ => seq(token(prec(1,caseTS('brl'))),optional($.trailing)), op_bvc: $ => seq(token(prec(1,caseTS('bvc'))),optional($.trailing)), op_bvs: $ => seq(token(prec(1,caseTS('bvs'))),optional($.trailing)), op_clc: $ => seq(token(prec(1,caseTS('clc'))),optional($.trailing)), op_cld: $ => seq(token(prec(1,caseTS('cld'))),optional($.trailing)), op_cli: $ => seq(token(prec(1,caseTS('cli'))),optional($.trailing)), op_clv: $ => seq(token(prec(1,caseTS('clv'))),optional($.trailing)), op_cmp: $ => seq(token(prec(1,caseTS('cmp'))),optional($.trailing)), op_cop: $ => seq(token(prec(1,caseTS('cop'))),optional($.trailing)), op_cpx: $ => seq(token(prec(1,caseTS('cpx'))),optional($.trailing)), op_cpy: $ => seq(token(prec(1,caseTS('cpy'))),optional($.trailing)), op_dec: $ => seq(token(prec(1,caseTS('dec'))),optional($.trailing)), op_dex: $ => seq(token(prec(1,caseTS('dex'))),optional($.trailing)), op_dey: $ => seq(token(prec(1,caseTS('dey'))),optional($.trailing)), op_eor: $ => seq(token(prec(1,caseTS('eor'))),optional($.trailing)), op_inc: $ => seq(token(prec(1,caseTS('inc'))),optional($.trailing)), op_inx: $ => seq(token(prec(1,caseTS('inx'))),optional($.trailing)), op_iny: $ => seq(token(prec(1,caseTS('iny'))),optional($.trailing)), op_jml: $ => seq(token(prec(1,caseTS('jml'))),optional($.trailing)), op_jmp: $ => seq(token(prec(1,caseTS('jmp'))),optional($.trailing)), op_jsl: $ => seq(token(prec(1,caseTS('jsl'))),optional($.trailing)), op_jsr: $ => seq(token(prec(1,caseTS('jsr'))),optional($.trailing)), op_lda: $ => seq(token(prec(1,caseTS('lda'))),optional($.trailing)), op_ldx: $ => seq(token(prec(1,caseTS('ldx'))),optional($.trailing)), op_ldy: $ => seq(token(prec(1,caseTS('ldy'))),optional($.trailing)), op_lsr: $ => seq(token(prec(1,caseTS('lsr'))),optional($.trailing)), op_mvn: $ => seq(token(prec(1,caseTS('mvn'))),optional($.trailing)), op_mvp: $ => seq(token(prec(1,caseTS('mvp'))),optional($.trailing)), op_nop: $ => seq(token(prec(1,caseTS('nop'))),optional($.trailing)), op_ora: $ => seq(token(prec(1,caseTS('ora'))),optional($.trailing)), op_pea: $ => seq(token(prec(1,caseTS('pea'))),optional($.trailing)), op_pei: $ => seq(token(prec(1,caseTS('pei'))),optional($.trailing)), op_per: $ => seq(token(prec(1,caseTS('per'))),optional($.trailing)), op_pha: $ => seq(token(prec(1,caseTS('pha'))),optional($.trailing)), op_phb: $ => seq(token(prec(1,caseTS('phb'))),optional($.trailing)), op_phd: $ => seq(token(prec(1,caseTS('phd'))),optional($.trailing)), op_phk: $ => seq(token(prec(1,caseTS('phk'))),optional($.trailing)), op_php: $ => seq(token(prec(1,caseTS('php'))),optional($.trailing)), op_phx: $ => seq(token(prec(1,caseTS('phx'))),optional($.trailing)), op_phy: $ => seq(token(prec(1,caseTS('phy'))),optional($.trailing)), op_pla: $ => seq(token(prec(1,caseTS('pla'))),optional($.trailing)), op_plb: $ => seq(token(prec(1,caseTS('plb'))),optional($.trailing)), op_pld: $ => seq(token(prec(1,caseTS('pld'))),optional($.trailing)), op_plp: $ => seq(token(prec(1,caseTS('plp'))),optional($.trailing)), op_plx: $ => seq(token(prec(1,caseTS('plx'))),optional($.trailing)), op_ply: $ => seq(token(prec(1,caseTS('ply'))),optional($.trailing)), op_rep: $ => seq(token(prec(1,caseTS('rep'))),optional($.trailing)), op_rol: $ => seq(token(prec(1,caseTS('rol'))),optional($.trailing)), op_ror: $ => seq(token(prec(1,caseTS('ror'))),optional($.trailing)), op_rti: $ => seq(token(prec(1,caseTS('rti'))),optional($.trailing)), op_rtl: $ => seq(token(prec(1,caseTS('rtl'))),optional($.trailing)), op_rts: $ => seq(token(prec(1,caseTS('rts'))),optional($.trailing)), op_sbc: $ => seq(token(prec(1,caseTS('sbc'))),optional($.trailing)), op_sec: $ => seq(token(prec(1,caseTS('sec'))),optional($.trailing)), op_sed: $ => seq(token(prec(1,caseTS('sed'))),optional($.trailing)), op_sei: $ => seq(token(prec(1,caseTS('sei'))),optional($.trailing)), op_sep: $ => seq(token(prec(1,caseTS('sep'))),optional($.trailing)), op_sta: $ => seq(token(prec(1,caseTS('sta'))),optional($.trailing)), op_stp: $ => seq(token(prec(1,caseTS('stp'))),optional($.trailing)), op_stx: $ => seq(token(prec(1,caseTS('stx'))),optional($.trailing)), op_sty: $ => seq(token(prec(1,caseTS('sty'))),optional($.trailing)), op_stz: $ => seq(token(prec(1,caseTS('stz'))),optional($.trailing)), op_tax: $ => seq(token(prec(1,caseTS('tax'))),optional($.trailing)), op_tay: $ => seq(token(prec(1,caseTS('tay'))),optional($.trailing)), op_tcd: $ => seq(token(prec(1,choice(caseTS('tcd'),caseTS('tad')))),optional($.trailing)), op_tcs: $ => seq(token(prec(1,choice(caseTS('tcs'),caseTS('tas')))),optional($.trailing)), op_tdc: $ => seq(token(prec(1,choice(caseTS('tdc'),caseTS('tda')))),optional($.trailing)), op_trb: $ => seq(token(prec(1,caseTS('trb'))),optional($.trailing)), op_tsb: $ => seq(token(prec(1,caseTS('tsb'))),optional($.trailing)), op_tsc: $ => seq(token(prec(1,choice(caseTS('tsc'),caseTS('tsa')))),optional($.trailing)), op_tsx: $ => seq(token(prec(1,caseTS('tsx'))),optional($.trailing)), op_txa: $ => seq(token(prec(1,caseTS('txa'))),optional($.trailing)), op_txs: $ => seq(token(prec(1,caseTS('txs'))),optional($.trailing)), op_txy: $ => seq(token(prec(1,caseTS('txy'))),optional($.trailing)), op_tya: $ => seq(token(prec(1,caseTS('tya'))),optional($.trailing)), op_tyx: $ => seq(token(prec(1,caseTS('tyx'))),optional($.trailing)), op_wai: $ => seq(token(prec(1,caseTS('wai'))),optional($.trailing)), op_wdm: $ => seq(token(prec(1,caseTS('wdm'))),optional($.trailing)), op_xba: $ => seq(token(prec(1,choice(caseTS('xba'),caseTS('swa')))),optional($.trailing)), op_xce: $ => seq(token(prec(1,caseTS('xce'))),optional($.trailing)), arg_adc: $ => choice($.addr,$.addr_s,$.addr_x,$.addr_y,$.daddr,$.daddr_y,$.iaddr,$.iaddr_is_y,$.iaddr_ix,$.iaddr_y,$.imm), arg_and: $ => choice($.addr,$.addr_s,$.addr_x,$.addr_y,$.daddr,$.daddr_y,$.iaddr,$.iaddr_is_y,$.iaddr_ix,$.iaddr_y,$.imm), arg_asl: $ => choice($.addr,$.addr_x), arg_bcc: $ => $.addr, arg_bcs: $ => $.addr, arg_beq: $ => $.addr, arg_bit: $ => choice($.addr,$.addr_x,$.imm), arg_bmi: $ => $.addr, arg_bne: $ => $.addr, arg_bpl: $ => $.addr, arg_bra: $ => $.addr, arg_brk: $ => $.imm, arg_brl: $ => $.addr, arg_bvc: $ => $.addr, arg_bvs: $ => $.addr, arg_cmp: $ => choice($.addr,$.addr_s,$.addr_x,$.addr_y,$.daddr,$.daddr_y,$.iaddr,$.iaddr_is_y,$.iaddr_ix,$.iaddr_y,$.imm), arg_cop: $ => $.addr, arg_cpx: $ => choice($.addr,$.imm), arg_cpy: $ => choice($.addr,$.imm), arg_dec: $ => choice($.addr,$.addr_x), arg_eor: $ => choice($.addr,$.addr_s,$.addr_x,$.addr_y,$.daddr,$.daddr_y,$.iaddr,$.iaddr_is_y,$.iaddr_ix,$.iaddr_y,$.imm), arg_inc: $ => choice($.addr,$.addr_x), arg_jml: $ => choice($.addr,$.iaddr), arg_jmp: $ => choice($.addr,$.iaddr,$.iaddr_ix), arg_jsl: $ => $.addr, arg_jsr: $ => choice($.addr,$.iaddr_ix), arg_lda: $ => choice($.addr,$.addr_s,$.addr_x,$.addr_y,$.daddr,$.daddr_y,$.iaddr,$.iaddr_is_y,$.iaddr_ix,$.iaddr_y,$.imm), arg_ldx: $ => choice($.addr,$.addr_y,$.imm), arg_ldy: $ => choice($.addr,$.addr_x,$.imm), arg_lsr: $ => choice($.addr,$.addr_x), arg_mvn: $ => $.xyc, arg_mvp: $ => $.xyc, arg_ora: $ => choice($.addr,$.addr_s,$.addr_x,$.addr_y,$.daddr,$.daddr_y,$.iaddr,$.iaddr_is_y,$.iaddr_ix,$.iaddr_y,$.imm), arg_pea: $ => $.data, arg_pei: $ => $.iaddr, arg_per: $ => $.addr, arg_rep: $ => $.data, arg_rol: $ => choice($.addr,$.addr_x), arg_ror: $ => choice($.addr,$.addr_x), arg_sbc: $ => choice($.addr,$.addr_s,$.addr_x,$.addr_y,$.daddr,$.daddr_y,$.iaddr,$.iaddr_is_y,$.iaddr_ix,$.iaddr_y,$.imm), arg_sep: $ => $.data, arg_sta: $ => choice($.addr,$.addr_s,$.addr_x,$.addr_y,$.daddr,$.daddr_y,$.iaddr,$.iaddr_is_y,$.iaddr_ix,$.iaddr_y), arg_stx: $ => choice($.addr,$.addr_y), arg_sty: $ => choice($.addr,$.addr_x), arg_stz: $ => choice($.addr,$.addr_x), arg_trb: $ => $.addr, arg_tsb: $ => $.addr, operation: $ => choice( seq(optional($.label_def), $._sep, $.op_adc, $._sep, $.arg_adc, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_and, $._sep, $.arg_and, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_asl, optional(seq($._sep, $.arg_asl)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_bcc, $._sep, $.arg_bcc, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_bcs, $._sep, $.arg_bcs, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_beq, $._sep, $.arg_beq, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_bit, $._sep, $.arg_bit, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_bmi, $._sep, $.arg_bmi, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_bne, $._sep, $.arg_bne, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_bpl, $._sep, $.arg_bpl, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_bra, $._sep, $.arg_bra, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_brk, $._sep, $.arg_brk, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_brl, $._sep, $.arg_brl, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_bvc, $._sep, $.arg_bvc, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_bvs, $._sep, $.arg_bvs, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_clc, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_cld, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_cli, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_clv, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_cmp, $._sep, $.arg_cmp, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_cop, $._sep, $.arg_cop, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_cpx, $._sep, $.arg_cpx, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_cpy, $._sep, $.arg_cpy, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_dec, optional(seq($._sep, $.arg_dec)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_dex, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_dey, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_eor, $._sep, $.arg_eor, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_inc, optional(seq($._sep, $.arg_inc)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_inx, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_iny, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_jml, $._sep, $.arg_jml, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_jmp, $._sep, $.arg_jmp, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_jsl, $._sep, $.arg_jsl, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_jsr, $._sep, $.arg_jsr, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_lda, $._sep, $.arg_lda, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_ldx, $._sep, $.arg_ldx, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_ldy, $._sep, $.arg_ldy, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_lsr, optional(seq($._sep, $.arg_lsr)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_mvn, $._sep, $.arg_mvn, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_mvp, $._sep, $.arg_mvp, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_nop, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_ora, $._sep, $.arg_ora, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_pea, $._sep, $.arg_pea, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_pei, $._sep, $.arg_pei, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_per, $._sep, $.arg_per, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_pha, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_phb, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_phd, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_phk, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_php, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_phx, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_phy, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_pla, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_plb, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_pld, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_plp, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_plx, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_ply, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_rep, $._sep, $.arg_rep, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_rol, optional(seq($._sep, $.arg_rol)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_ror, optional(seq($._sep, $.arg_ror)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_rti, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_rtl, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_rts, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_sbc, $._sep, $.arg_sbc, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_sec, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_sed, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_sei, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_sep, $._sep, $.arg_sep, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_sta, $._sep, $.arg_sta, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_stp, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_stx, $._sep, $.arg_stx, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_sty, $._sep, $.arg_sty, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_stz, $._sep, $.arg_stz, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tax, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tay, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tcd, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tcs, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tdc, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_trb, $._sep, $.arg_trb, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tsb, $._sep, $.arg_tsb, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tsc, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tsx, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_txa, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_txs, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_txy, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tya, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_tyx, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_wai, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_wdm, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_xba, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.op_xce, optional(seq($._sep,$.comment)), $._newline) ), // Pseudo-operations psop_end_lup: $ => seq(token(prec(1,caseTS('--^'))),optional($.trailing)), psop_adr: $ => seq(token(prec(1,caseTS('adr'))),optional($.trailing)), psop_adrl: $ => seq(token(prec(1,caseTS('adrl'))),optional($.trailing)), psop_asc: $ => seq(token(prec(1,caseTS('asc'))),optional($.trailing)), psop_ast: $ => seq(token(prec(1,caseTS('ast'))),optional($.trailing)), psop_cas: $ => seq(token(prec(1,caseTS('cas'))),optional($.trailing)), psop_chk: $ => seq(token(prec(1,caseTS('chk'))),optional($.trailing)), psop_cyc: $ => seq(token(prec(1,caseTS('cyc'))),optional($.trailing)), psop_da: $ => seq(token(prec(1,choice(caseTS('da'),caseTS('dw')))),optional($.trailing)), psop_dat: $ => seq(token(prec(1,caseTS('dat'))),optional($.trailing)), psop_dci: $ => seq(token(prec(1,caseTS('dci'))),optional($.trailing)), psop_ddb: $ => seq(token(prec(1,caseTS('ddb'))),optional($.trailing)), psop_dend: $ => seq(token(prec(1,caseTS('dend'))),optional($.trailing)), psop_dfb: $ => seq(token(prec(1,choice(caseTS('dfb'),caseTS('db')))),optional($.trailing)), psop_do: $ => seq(token(prec(1,caseTS('do'))),optional($.trailing)), psop_ds: $ => seq(token(prec(1,caseTS('ds'))),optional($.trailing)), psop_dsk: $ => seq(token(prec(1,caseTS('dsk'))),optional($.trailing)), psop_dum: $ => seq(token(prec(1,caseTS('dum'))),optional($.trailing)), psop_else: $ => seq(token(prec(1,caseTS('else'))),optional($.trailing)), psop_end: $ => seq(token(prec(1,caseTS('end'))),optional($.trailing)), psop_ent: $ => seq(token(prec(1,caseTS('ent'))),optional($.trailing)), psop_eom: $ => seq(token(prec(1,choice(caseTS('eom'),caseTS('<<<')))),optional($.trailing)), psop_equ: $ => seq(token(prec(1,choice(caseTS('equ'),caseTS('=')))),optional($.trailing)), psop_err: $ => seq(token(prec(1,caseTS('err'))),optional($.trailing)), psop_exd: $ => seq(token(prec(1,caseTS('exd'))),optional($.trailing)), psop_exp: $ => seq(token(prec(1,caseTS('exp'))),optional($.trailing)), psop_ext: $ => seq(token(prec(1,caseTS('ext'))),optional($.trailing)), psop_fin: $ => seq(token(prec(1,caseTS('fin'))),optional($.trailing)), psop_flo: $ => seq(token(prec(1,caseTS('flo'))),optional($.trailing)), psop_fls: $ => seq(token(prec(1,caseTS('fls'))),optional($.trailing)), psop_hex: $ => seq(token(prec(1,caseTS('hex'))),optional($.trailing)), psop_if: $ => seq(token(prec(1,caseTS('if'))),optional($.trailing)), psop_inv: $ => seq(token(prec(1,caseTS('inv'))),optional($.trailing)), psop_kbd: $ => seq(token(prec(1,caseTS('kbd'))),optional($.trailing)), psop_lst: $ => seq(token(prec(1,caseTS('lst'))),optional($.trailing)), psop_lstdo: $ => seq(token(prec(1,caseTS('lstdo'))),optional($.trailing)), psop_lup: $ => seq(token(prec(1,caseTS('lup'))),optional($.trailing)), psop_mac: $ => seq(token(prec(1,caseTS('mac'))),optional($.trailing)), psop_mx: $ => seq(token(prec(1,caseTS('mx'))),optional($.trailing)), psop_obj: $ => seq(token(prec(1,caseTS('obj'))),optional($.trailing)), psop_org: $ => seq(token(prec(1,caseTS('org'))),optional($.trailing)), psop_pag: $ => seq(token(prec(1,caseTS('pag'))),optional($.trailing)), psop_pau: $ => seq(token(prec(1,caseTS('pau'))),optional($.trailing)), psop_pmc: $ => seq(token(prec(1,choice(caseTS('pmc'),caseTS('>>>')))),optional($.trailing)), psop_put: $ => seq(token(prec(1,caseTS('put'))),optional($.trailing)), psop_rel: $ => seq(token(prec(1,caseTS('rel'))),optional($.trailing)), psop_rev: $ => seq(token(prec(1,caseTS('rev'))),optional($.trailing)), psop_sav: $ => seq(token(prec(1,caseTS('sav'))),optional($.trailing)), psop_skp: $ => seq(token(prec(1,caseTS('skp'))),optional($.trailing)), psop_str: $ => seq(token(prec(1,caseTS('str'))),optional($.trailing)), psop_strl: $ => seq(token(prec(1,caseTS('strl'))),optional($.trailing)), psop_sw: $ => seq(token(prec(1,caseTS('sw'))),optional($.trailing)), psop_tr: $ => seq(token(prec(1,caseTS('tr'))),optional($.trailing)), psop_ttl: $ => seq(token(prec(1,caseTS('ttl'))),optional($.trailing)), psop_typ: $ => seq(token(prec(1,caseTS('typ'))),optional($.trailing)), psop_use: $ => seq(token(prec(1,caseTS('use'))),optional($.trailing)), psop_usr: $ => seq(token(prec(1,caseTS('usr'))),optional($.trailing)), psop_var: $ => seq(token(prec(1,caseTS('var'))),optional($.trailing)), psop_xc: $ => seq(token(prec(1,caseTS('xc'))),optional($.trailing)), arg_adr: $ => seq($.data,repeat(seq(',',$.data))), arg_adrl: $ => seq($.data,repeat(seq(',',$.data))), arg_asc: $ => choice($.var_mac,choice($._string_operand,$._num_str)), arg_ast: $ => $._aexpr, arg_cas: $ => choice($.var_mac,alias(choice(caseRe('se'),caseRe('in')),$.enum)), arg_cyc: $ => choice($.var_mac,alias(choice(caseRe('off'),caseRe('ave'),caseRe('flags')),$.enum)), arg_da: $ => seq($.data,repeat(seq(',',$.data))), arg_dat: $ => $._aexpr, arg_dci: $ => choice($.var_mac,$._string_operand), arg_ddb: $ => seq($.data,repeat(seq(',',$.data))), arg_dfb: $ => seq($.data,repeat(seq(',',$.data))), arg_do: $ => $._aexpr, arg_ds: $ => choice($.data,seq($.data,',',$.data),$.new_page,seq($.new_page,',',$.data)), arg_dsk: $ => choice($.var_mac,$.filename), arg_dum: $ => $._aexpr, arg_ent: $ => seq($.label_ref,repeat(seq(',',$.label_ref))), arg_equ: $ => $._aexpr, arg_err: $ => choice($.ptr_check,seq(optional('\\'),$._aexpr)), arg_exd: $ => seq($.label_def,repeat(seq(',',$.label_def))), arg_exp: $ => choice($.var_mac,alias(choice(caseRe('on'),caseRe('off'),caseRe('only')),$.enum)), arg_ext: $ => seq($.label_def,repeat(seq(',',$.label_def))), arg_flo: $ => choice($.var_mac,$.dstring), arg_fls: $ => choice($.var_mac,$._string_operand), arg_hex: $ => choice($.var_mac,$.hex_data), arg_if: $ => choice($.if_char,$.if_mx), arg_inv: $ => choice($.var_mac,$._string_operand), arg_kbd: $ => choice($.var_mac,$.dstring), arg_lst: $ => choice($.var_mac,choice(alias(choice(caseRe('on'),caseRe('off'),caseRe('rtn')),$.enum),seq(alias(caseRe('file'),$.enum),',',$.filename))), arg_lstdo: $ => choice($.var_mac,alias(caseRe('off'),$.enum)), arg_lup: $ => $._aexpr, arg_mx: $ => $._aexpr, arg_obj: $ => $._aexpr, arg_org: $ => $._aexpr, arg_pmc: $ => seq($.macro_ref,optional(seq($._arg_sep,$.arg_macro))), arg_put: $ => choice($.var_mac,$.filename), arg_rev: $ => choice($.var_mac,$.dstring), arg_sav: $ => choice($.var_mac,$.filename), arg_skp: $ => $._aexpr, arg_str: $ => choice($.var_mac,$._string_operand), arg_strl: $ => choice($.var_mac,$._string_operand), arg_tr: $ => choice($.var_mac,alias(choice(caseRe('on'),caseRe('off'),caseRe('adr')),$.enum)), arg_ttl: $ => choice($.var_mac,$.dstring), arg_typ: $ => $._aexpr, arg_use: $ => choice($.var_mac,$.filename), arg_usr: $ => $.literal, arg_var: $ => seq($._aexpr,repeat(seq(';',$._aexpr))), arg_xc: $ => alias(caseRe('off'),$.enum), pseudo_operation: $ => choice( seq(optional($.label_def), $._sep, $.psop_end_lup, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_adr, $._sep, $.arg_adr, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_adrl, $._sep, $.arg_adrl, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_asc, $._sep, $.arg_asc, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_ast, $._sep, $.arg_ast, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_cas, $._sep, $.arg_cas, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_chk, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_cyc, optional(seq($._sep, $.arg_cyc)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_da, $._sep, $.arg_da, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_dat, optional(seq($._sep, $.arg_dat)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_dci, $._sep, $.arg_dci, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_ddb, $._sep, $.arg_ddb, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_dend, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_dfb, $._sep, $.arg_dfb, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_do, $._sep, $.arg_do, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_ds, $._sep, $.arg_ds, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_dsk, $._sep, $.arg_dsk, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_dum, $._sep, $.arg_dum, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_else, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_end, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_ent, optional(seq($._sep, $.arg_ent)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_eom, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_equ, $._sep, $.arg_equ, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_err, $._sep, $.arg_err, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_exd, optional(seq($._sep, $.arg_exd)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_exp, $._sep, $.arg_exp, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_ext, optional(seq($._sep, $.arg_ext)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_fin, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_flo, $._sep, $.arg_flo, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_fls, $._sep, $.arg_fls, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_hex, $._sep, $.arg_hex, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_if, $._sep, $.arg_if, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_inv, $._sep, $.arg_inv, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_kbd, optional(seq($._sep, $.arg_kbd)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_lst, optional(seq($._sep, $.arg_lst)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_lstdo, optional(seq($._sep, $.arg_lstdo)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_lup, $._sep, $.arg_lup, optional(seq($._sep,$.comment)), $._newline), seq($.macro_def, $._sep, $.psop_mac, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_mx, $._sep, $.arg_mx, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_obj, $._sep, $.arg_obj, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_org, optional(seq($._sep, $.arg_org)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_pag, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_pau, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_pmc, $._sep, $.arg_pmc, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_put, $._sep, $.arg_put, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_rel, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_rev, $._sep, $.arg_rev, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_sav, $._sep, $.arg_sav, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_skp, $._sep, $.arg_skp, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_str, $._sep, $.arg_str, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_strl, $._sep, $.arg_strl, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_sw, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_tr, optional(seq($._sep, $.arg_tr)), optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_ttl, $._sep, $.arg_ttl, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_typ, $._sep, $.arg_typ, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_use, $._sep, $.arg_use, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_usr, $._sep, $.arg_usr, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_var, $._sep, $.arg_var, optional(seq($._sep,$.comment)), $._newline), seq(optional($.label_def), $._sep, $.psop_xc, optional(seq($._sep, $.arg_xc)), optional(seq($._sep,$.comment)), $._newline) ), // special arguments trailing: $ => /\S+/, if_mx: $ => seq('MX', optional(seq(choice($.eop_plus, $.eop_minus, $.eop_times, $.eop_div, $.eop_or, $.eop_and, $.eop_xor), $._aexpr))), // For IF, any literal can be on the right, but this would only be expected after expansion. // In other words, the IF is only useful to the programmer if a macro variable is on the right. if_char: $ => seq(ANYCHAR,ANYCHAR,choice($.var_mac,$.arg_literal)), new_page: $ => '\\', ptr_check: $ => seq('(',$.num,')-',$.num), // Strings _string_operand: $ => seq($.dstring,repeat(seq(',',$.hex_data,',',$.dstring)),optional(seq(',',$.hex_data))), _num_str: $ => seq($.num_str_prefix,$._aexpr), num_str_prefix: $ => choice('#',"#'",'#"','#>',"#'>",'#">'), // dstring dstring: $ => choice( seq("!",repeat(ANYCHAR),"!"), seq('"',repeat(ANYCHAR),'"'), seq("#",repeat(ANYCHAR),"#"), seq("$",repeat(ANYCHAR),"$"), seq("%",repeat(ANYCHAR),"%"), seq("&",repeat(ANYCHAR),"&"), seq("'",repeat(ANYCHAR),"'"), seq("(",repeat(ANYCHAR),"("), seq(")",repeat(ANYCHAR),")"), seq("*",repeat(ANYCHAR),"*"), seq("+",repeat(ANYCHAR),"+"), seq("-",repeat(ANYCHAR),"-"), seq(".",repeat(ANYCHAR),"."), seq(":",repeat(ANYCHAR),":"), seq(";",repeat(ANYCHAR),";"), seq("<",repeat(ANYCHAR),"<"), seq("=",repeat(ANYCHAR),"="), seq(">",repeat(ANYCHAR),">"), seq("?",repeat(ANYCHAR),"?"), seq("@",repeat(ANYCHAR),"@"), seq("A",repeat(ANYCHAR),"A"), seq("B",repeat(ANYCHAR),"B"), seq("C",repeat(ANYCHAR),"C"), seq("D",repeat(ANYCHAR),"D"), seq("E",repeat(ANYCHAR),"E"), seq("F",repeat(ANYCHAR),"F"), seq("G",repeat(ANYCHAR),"G"), seq("H",repeat(ANYCHAR),"H"), seq("I",repeat(ANYCHAR),"I"), seq("J",repeat(ANYCHAR),"J"), seq("K",repeat(ANYCHAR),"K"), seq("L",repeat(ANYCHAR),"L"), seq("M",repeat(ANYCHAR),"M"), seq("N",repeat(ANYCHAR),"N"), seq("O",repeat(ANYCHAR),"O"), seq("P",repeat(ANYCHAR),"P"), seq("Q",repeat(ANYCHAR),"Q"), seq("R",repeat(ANYCHAR),"R"), seq("S",repeat(ANYCHAR),"S"), seq("T",repeat(ANYCHAR),"T"), seq("U",repeat(ANYCHAR),"U"), seq("V",repeat(ANYCHAR),"V"), seq("W",repeat(ANYCHAR),"W"), seq("X",repeat(ANYCHAR),"X"), seq("Y",repeat(ANYCHAR),"Y"), seq("Z",repeat(ANYCHAR),"Z"), seq("[",repeat(ANYCHAR),"["), seq("\\",repeat(ANYCHAR),"\\"), seq("]",optional(seq(DSTR_BR_BEG,repeat(ANYCHAR))),"]"), seq("^",repeat(ANYCHAR),"^"), seq("_",repeat(ANYCHAR),"_"), seq("`",repeat(ANYCHAR),"`"), seq("a",repeat(ANYCHAR),"a"), seq("b",repeat(ANYCHAR),"b"), seq("c",repeat(ANYCHAR),"c"), seq("d",repeat(ANYCHAR),"d"), seq("e",repeat(ANYCHAR),"e"), seq("f",repeat(ANYCHAR),"f"), seq("g",repeat(ANYCHAR),"g"), seq("h",repeat(ANYCHAR),"h"), seq("i",repeat(ANYCHAR),"i"), seq("j",repeat(ANYCHAR),"j"), seq("k",repeat(ANYCHAR),"k"), seq("l",repeat(ANYCHAR),"l"), seq("m",repeat(ANYCHAR),"m"), seq("n",repeat(ANYCHAR),"n"), seq("o",repeat(ANYCHAR),"o"), seq("p",repeat(ANYCHAR),"p"), seq("q",repeat(ANYCHAR),"q"), seq("r",repeat(ANYCHAR),"r"), seq("s",repeat(ANYCHAR),"s"), seq("t",repeat(ANYCHAR),"t"), seq("u",repeat(ANYCHAR),"u"), seq("v",repeat(ANYCHAR),"v"), seq("w",repeat(ANYCHAR),"w"), seq("x",repeat(ANYCHAR),"x"), seq("y",repeat(ANYCHAR),"y"), seq("z",repeat(ANYCHAR),"z"), seq("{",repeat(ANYCHAR),"{"), seq("|",repeat(ANYCHAR),"|"), seq("}",repeat(ANYCHAR),"}"), seq("~",repeat(ANYCHAR),"~"), ), // 6502 and 65C02 addressing Modes // The 65C02 added (ZP) and (ABS,X), but these are indistinguishable from (ABS) and (ZP,X) // until the arguments are actually evaluated. imm: $ => seq($.imm_prefix,$._aexpr), addr: $ => $._addr_aexpr, addr_x: $ => seq($._addr_aexpr,alias(choice(',X',',x'),$.mode)), addr_y: $ => seq($._addr_aexpr,alias(choice(',Y',',y'),$.mode)), iaddr_ix: $ => seq(alias('(',$.mode),$._aexpr,alias(choice(',X)',',x)'),$.mode)), iaddr_y: $ => seq(alias('(',$.mode),$._aexpr,alias(choice('),Y','),y'),$.mode)), iaddr: $ => seq(alias('(',$.mode),$._aexpr,alias(')',$.mode)), // 65C816 addressing modes daddr: $ => seq(alias('[',$.mode),$._aexpr,alias(']',$.mode)), daddr_y: $ => seq(alias('[',$.mode),$._aexpr,alias(choice('],Y','],y'),$.mode)), addr_s: $ => seq($._aexpr,alias(choice(',S',',s'),$.mode)), iaddr_is_y: $ => seq(alias('(',$.mode),$._aexpr,alias(choice(',S),Y',',s),y',',S),y',',s),Y'),$.mode)), xyc: $ => seq($.data,',',$.data), // Expressions data: $ => seq(optional($.data_prefix),$._aexpr), _addr_aexpr: $ => seq(optional($.addr_prefix),$._aexpr), _aexpr: $ => choice( $.braced_aexpr, $.label_ref, $.num, $.pchar, $.nchar, $.current_addr, $.unary_aexpr, $.binary_aexpr ), unary_aexpr: $ => prec(1,choice(seq($.eop_plus,$._aexpr),seq($.eop_minus,$._aexpr))), // MERLIN 8/16 has no operator precedence: left to right always prevails binary_aexpr: $ => prec.left(seq($._aexpr,choice( $.eop_plus,$.eop_minus,$.eop_times,$.eop_div,$.eop_or,$.eop_and,$.eop_xor, $.cop_less,$.cop_gtr,$.cop_eq,$.cop_neq ),$._aexpr)), // MERLIN 16+ added precedence within curly braced expressions braced_aexpr: $ => prec(1,seq('{',$._aexpr_prec,'}')), _aexpr_prec: $ => choice( $.braced_aexpr, $.label_ref, $.num, $.pchar, $.nchar, $.current_addr, alias($.unary_aexpr_prec,$.unary_aexpr), alias($.binary_aexpr_prec,$.binary_aexpr) ), unary_aexpr_prec: $ => prec(5,choice(seq($.eop_plus,$._aexpr_prec),seq($.eop_minus,$._aexpr_prec))), binary_aexpr_prec: $ => choice( prec.left(4,seq($._aexpr_prec,choice($.eop_or,$.eop_and,$.eop_xor),$._aexpr_prec)), prec.left(3,seq($._aexpr_prec,choice($.eop_times,$.eop_div),$._aexpr_prec)), prec.left(2,seq($._aexpr_prec,choice($.eop_plus,$.eop_minus),$._aexpr_prec)), prec.left(1,seq($._aexpr_prec,choice($.cop_less,$.cop_gtr,$.cop_eq,$.cop_neq),$._aexpr_prec)), ), eop_plus: $ => '+', eop_minus: $ => '-', eop_times: $ => '*', eop_div: $ => '/', eop_or: $ => '.', eop_and: $ => '&', eop_xor: $ => '!', // Merlin 16+ added these operators cop_less: $ => '<', cop_gtr: $ => '>', cop_eq: $ => '=', cop_neq: $ => '#', // Primitive Expressions imm_prefix: $ => choice('#','#<','#>','#^'), addr_prefix: $ => choice('<','>','^','|'), data_prefix: $ => choice('#', '#<', '#>', '#^', '<', '>', '^'), hex_data: $ => /[0-9A-Fa-f][0-9A-Fa-f](,?[0-9A-Fa-f][0-9A-Fa-f])*/, filename: $ => choice($.prodos,$.dos33), prodos: $ => seq(optional('/'),repeat(seq($.prodos_filename,'/')),$.prodos_filename), prodos_filename: $ => prec.dynamic(1,seq(choice(...alphachars),repeat(choice(...prodoschars)))), dos33: $ => seq(optional(choice(...DOS33_TFLAG)),choice(...alphachars),repeat(choice(...DOS33_CHARS)), optional(/,S[1-7]/), optional(/,D[1-2]/)), num: $ => choice($._dec,$._hex,$._bin), _dec: $ => repeat1(choice(...'0123456789')), _hex: $ => seq('$',repeat1(choice(...'0123456789ABCDEFabcdef'))), _bin: $ => seq('%',repeat1(choice(...'01_'))), pchar: $ => seq("'",ANYCHAR,optional("'")), // ''' is OK nchar: $ => seq('"',ANYCHAR,optional('"')), // """ is OK current_addr: $ => '*', literal: $ => /.*/, // Comments comment: $ => seq(';',$.txt), // max 64/80 - len(operand) heading: $ => seq('*',$.txt), // max 64/80 txt: $ => /.*/ } }); function caseRe (keyword) { let result = new RegExp(keyword .split('') .map(c => c.toLowerCase() != c.toUpperCase() ? `[${c.toLowerCase()}${c.toUpperCase()}]` : c) .join('') ); return result; } function caseTS (keyword) { let chars = keyword .split('') .map(c => c.toLowerCase() != c.toUpperCase() ? choice(c.toLowerCase(),c.toUpperCase()) : c); return seq(...chars); }