
/*
   phrase(prio, a0, a1, a2, a3, suffix) defines a sequence of 1..4 token
  classes with a priority  and a reduce function suffix.

   If suffix is "" (aka. DITO below) then the reduce function is
   reduce_a0_a1_a2_a3(), otherwise reduce_suffix(). The suffix is used to
   map different phrases to the same reduce function, as to avoid trivial
   reduce functions that only call some other reduce function.

   prio is a priority for resolving reduce/reduce conflicts.
   a0, a1, ... are groups of token classes:
   inl is true for trivial wrappers

   group     token class(es)
   ─────────────────────────
   ASS:      ←
   GOTO:     →
   ESC:      →
   F, G:     TC_FUN12
   N:    :   TC_FUN0
   M:        TC_OP1
   D:        TC_OP2
   SEMI:     ;
   LBRA:     [
   END:      TC_END
   LPAR:     (
   RBRA:     ]
   MISC:     ← → FUN ; [ END ( ]   (i.e. any of the above)
   RPAR:     )
   A, B:     TC_VALUE
   C:        TC_INDEX
   V:        TC_SYMBOL
   I:        TC_PINDEX
   RETC:     TC_RETURN
   ─────────────────────────

   Normally the priority is the priority of the prefix plus the number of items
   so that the longest match of the same prefix wins.
 */

#define DITO ""

//    (prio          , TC0  , TC1  , TC2  , TC3  ,  reduce_ suffix)
//=================================================================
// remove parentheses
//
phrase(BS_ANY+3      , LPAR , B    , RPAR ,      , DITO )
phrase(BS_ANY+3      , LPAR , F    , RPAR ,      , "LPAR_B_RPAR_")
phrase(BS_ANY+4      , LPAR , F    , C    , RPAR , ""    )

// niladic function call
phrase(BS_ANY+ 1,      N    ,      ,      ,      , DITO )

// function called monadically
//
phrase_MISC (BS_F_B+2,        F    , B    ,      , DITO )
phrase_MISC (BS_F_B+3,        F    , C    , B    , DITO )

// function called dyadically
//                                                             examples
phrase(BS_A_F+3      , A    , F    , B    ,      , DITO )
phrase(BS_A_F+3      , A    , M    , B    ,      , DITO )   // A / B
phrase(BS_A_F+4      , A    , F    , C    , B    , DITO )
phrase(BS_A_F+4      , A    , M    , C    , B    , DITO )   // A /[X] B

// monadic operator
//
phrase(BS_LO_OP+2    , F    , M    ,      ,      , DITO )   // +/
phrase(BS_LO_OP+2    , M    , M    ,      ,      , DITO )   // /¨
phrase(BS_LO_OP+3    , F    , M    , C    ,      , DITO )   // +/[2]
phrase(BS_LO_OP+3    , F    , C    , M    ,      , DITO )   // ,[2]/
phrase(BS_LO_OP+4    , F    , C    , M    , C    , DITO )   // ,[2]/[2]
phrase(BS_LO_OP+2    , A    , M    ,      ,      , DITO )   // A/

// dyadic operator
//
phrase(BS_OP_RO+2    , D    , V    ,      ,      , DITO )   // .MEMBER
phrase(BS_OP_RO+3    , A    , D    , B    ,      , "F_D_G_")
phrase(BS_OP_RO+3    , A    , D    , G    ,      , "F_D_G_")
phrase(BS_OP_RO+3    , F    , D    , B    ,      , DITO )
phrase(BS_OP_RO+3    , F    , D    , G    ,      , DITO )
phrase(BS_OP_RO+4    , F    , D    , C    , B    , DITO )

// indexed reference and assignment
phrase(BS_ANY_BRA+2  , A    , C    ,      ,      , DITO )
phrase(BS_ANY_BRA+2  , V    , C    ,      ,      , DITO )
phrase(BS_ANY_BRA+4  , V    , C    , ASS  , B    , DITO )

// selective specification
phrase(BS_F_B+2,       F    , V    ,     ,       , DITO )

// (reference) and assignment
phrase(BS_V_ASS+3    , A    , ASS  , B    ,      , DITO )       // sel. ass.
phrase(BS_V_ASS+3    , V    , ASS  , B    ,      , DITO )       // V←B
phrase(BS_V_ASS+4    , D    , V    , ASS  , B    , DITO )       // .MEMBER ← B
phrase(BS_V_ASS+3    , V    , ASS  , F    ,      , DITO )       // λ: V ← { ... } ⍺ ⍵
phrase(BS_V_ASS+3    , V    , ASS  , N    ,      , "V_ASS_F_")  // λ: V ← { ... }
phrase(BS_V_ASS+3    , V    , ASS  , M    ,      , "V_ASS_F_")  // λ: V ← { ... } ⍶
phrase(BS_V_ASS+3    , V    , ASS  , D    ,      , "V_ASS_F_")  // λ: V ← { ... } ⍶ ⍹

// build index list
//
phrase(BS_ANY+1      , RBRA ,      ,      ,      , DITO )
phrase(BS_ANY+2      , LBRA , I    ,      ,      , DITO )
phrase(BS_ANY+3      , LBRA , B    , I    ,      , DITO )

// vector notation
phrase(BS_VAL_VAL+2  , A    , B    ,      ,      , DITO )

// vector assignment (A B ... C) ← B or selective specification (f g ... C) ← B
//
phrase(BS_VAL_VAL+2  , V    , RPAR , ASS  , B    , DITO )

// end of statement
//
phrase(BS_ANY+1      , END  ,      ,      ,      , DITO )
phrase(BS_ANY+2      , END  , VOID ,      ,      , DITO )
phrase(BS_ANY+2      , END  , B    ,      ,      , DITO )
phrase(BS_ANY+2      , END  , GOTO ,      ,      , DITO )
phrase(BS_ANY+3      , END  , GOTO , B    ,      , DITO )
phrase(BS_ANY+3      , F    , GOTO , B    ,      , "END_GOTO_B_")
phrase(BS_ANY+3      , M    , GOTO , B    ,      , "END_GOTO_B_")
phrase(BS_ANY+3      , A    , GOTO , B    ,      , DITO )

// end of user defined function, ⍎, or ◊ context
//
phrase(BS_ANY+1      , RETC ,      ,      ,      , DITO )
phrase(BS_ANY+2      , RETC , VOID ,      ,      , DITO )
phrase(BS_ANY+2      , RETC , A    ,      ,      , DITO )
phrase(BS_ANY+2      , RETC , GOTO ,      ,      , DITO )
phrase(BS_ANY+3      , RETC , GOTO , B    ,      , DITO )
phrase(BS_ANY+4      , RETC , A    , GOTO , B    , DITO )

#undef DITO
#undef phrase

