grammar PIR::Grammar;


#
# pasm_ops.g - contains grammar for all PASM instructions [1].
#
# [1] all except for:
#   dot gnu
#   experimental
#   obscure
#   python
# ops.
#
# The math ops may be implemented as a library instead in the future?
#
#
# For most instructions, the arguments are handled by the rule
# <arg_hack>, which takes 0 or more (comma-separated) arguments.
# it is *a lot* of work to fix this, so for now just want to test
# general working of the PIR parser.


#
# PASM instructions (pure PASM) go here
#
rule pasm_instr {
    <core_op>
  | <bitwise_op>
  | <comparison_op>
  | <io_op>
  | <debug_op>
  | <math_op>
  | <pmc_op>
  | <loading_op>
  | <string_op>
  | <stack_op>
  | <system_op>
  | <var_op>
}



rule bitwise_op {
    band                <target> \, <simple_expr> [ \, <simple_expr> ]?
  | bands               <target> \, <simple_expr> [ \, <simple_expr> ]?
  | bnot                <target> [ \, <simple_expr> ]?
  | bnots               <target> [ \, <simple_expr> ]?
  | bor                 <target> \, <simple_expr> [ \, <simple_expr> ]?
  | bors                <target> \, <simple_expr> [ \, <simple_expr> ]?
  | shl                 <target> \, <simple_expr> [ \, <simple_expr> ]?
  | shr                 <target> \, <simple_expr> [ \, <simple_expr> ]?
  | lsr                 <target> \, <simple_expr> [ \, <simple_expr> ]?
  | rot                 <target> \, <simple_expr>  \, <simple_expr> \, <simple_expr>
  | bxor                <target> \, <simple_expr> [ \, <simple_expr> ]?
  | bxors               <target> \, <simple_expr> [ \, <simple_expr> ]?
}

rule comparison_op {
    eq                  <arg_exp_exp_lab>
  | eq_str              <arg_exp_exp_lab>
  | eq_num              <arg_exp_exp_lab>
  | eq_addr             <arg_exp_exp_lab>
  | ne                  <arg_exp_exp_lab>
  | ne_str              <arg_exp_exp_lab>
  | ne_num              <arg_exp_exp_lab>
  | ne_addr             <arg_exp_exp_lab>
  | lt                  <arg_exp_exp_lab>
  | lt_str              <arg_exp_exp_lab>
  | lt_num              <arg_exp_exp_lab>
  | lt_addr             <arg_exp_exp_lab>
  | le                  <arg_exp_exp_lab>
  | le_str              <arg_exp_exp_lab>
  | le_num              <arg_exp_exp_lab>
  | le_addr             <arg_exp_exp_lab>
  | gt                  <arg_exp_exp_lab>
  | gt_str              <arg_exp_exp_lab>
  | gt_num              <arg_exp_exp_lab>
  | gt_addr             <arg_exp_exp_lab>
  | ge                  <arg_exp_exp_lab>
  | ge_str              <arg_exp_exp_lab>
  | ge_num              <arg_exp_exp_lab>
  | ge_addr             <arg_exp_exp_lab>
  | if_null             <target> \, <id>
  | unless_null         <target> \, <id>
  | cmp                 <isXX_args>
  | cmp_str             <isXX_args>
  | cmp_num             <isXX_args>
  | issame              <isXX_args>
  | isntsame            <isXX_args>
  | istrue              [ <int_reg> | <id> ] \, <target>
  | isfalse             [ <int_reg> | <id> ] \, <target>
  | isnull              [ <int_reg> | <id> ] \, <target>
  | isge                <isXX_args>
  | isgt                <isXX_args>
  | isle                <isXX_args>
  | islt                <isXX_args>
  | iseq                <isXX_args>
  | isne                <isXX_args>
  | and                 [ <int_reg> | <id> ] \, <simple_expr> \, <simple_expr>
  | not                 <target> [ \, <target> ]?
  | or                  [ <int_reg> | <id> ] \,<simple_expr> \, <simple_expr>
  | xor                 [ <int_reg> | <id> ] \, <simple_expr> \, <simple_expr>
}

rule debug_op {
    debug_init
  | debug_load          <target>
  | debug_break
  | debug_print
  | backtrace
  | getline             <target>
  | getfile             <target>
}


rule loading_op {
    clone
  | exchange
  | set                 <target> \, <simple_expr>
  | assign              <arg_hack> #
  | setref              <arg_hack> #
  | deref               <arg_hack> #
  | setp_ind            <arg_hack> #
  | setn_ind            <arg_hack> #
  | sets_ind            <arg_hack> #
  | seti_ind            <arg_hack> #
  | null                <arg_hack> #
  | cleari              <arg_hack> #
  | clearn              <arg_hack> #
  | clearp              <arg_hack> #
  | clears              <arg_hack> #
}

rule stack_op {
    saveall             <arg_hack> #
  | restoreall          <arg_hack> #
  | entrytype           <arg_hack> #
  | depth               <arg_hack> #
  | lookback            <arg_hack> #
  | save                <arg_hack> #
  | savec               <arg_hack> #
  | restore             <arg_hack> #
  | rotate_up           <arg_hack> #
}

rule system_op {
    spawnw              <arg_hack> #
  | err                 <arg_hack> #
  | time                <arg_hack> #
  | gmtime              <arg_hack> #
  | localtime           <arg_hack> #
  | decodetime          <arg_hack> #
  | decodelocaltime     <arg_hack> #
  | sysinfo             <arg_hack> #
  | sleep               <arg_hack> #
  | sizeof              <arg_hack> #
}


rule var_op {
    store_lex           <arg_hack> #
  | find_lex            <arg_hack> #
  | get_namespace       <arg_hack> #
  | get_hll_namespace   <arg_hack> #
  | get_root_namespace  <arg_hack> #
  | get_global          <arg_hack> #
  | get_hll_global      <arg_hack> #
  | get_root_global     <arg_hack> #
  | set_global          <arg_hack> #
  | set_hll_global      <arg_hack> #
  | set_root_global     <arg_hack> #
}

# TODO:
#
# define "argument" rules, so that not each instruction has to
# define it's specific number and types of args.
# for instance: args_v_i_s for matching a <target> argument,
# <int_constant> argument and a <string_constant> argument
#

