_p_casttype:
    INT
|
    LIST
|
    STRINGTYPE
;

_string:
    _string STRING
    {                                       
        ssAppendBuf(util_string());         // append the next string 
    }
|
    STRING
    {
        ssSetBuf(util_string());            // assign the 1st string
    }
;

_func_or_var:
    function closeParen
|
    IDENTIFIER
    {
        msg("identifier: %s", util_string());
        $$ = pmv_fetchVar();
    }
;

_backtick:   
    {
        gp_parse_error = err_backtick_expected;
    }
    '`' 
;

expression:
    expression '=' expression
    {
        msg("inc/expression.5: assignment (=)");
        $$ = pmv_assign(&$1, &$3);
    }
|
    expression '[' expression ']'
    {
        $$ = pmv_indexOp(&$1, &$3);
    }
|
    expression MUL_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_multiply, "*=");
    }
|
    expression DIV_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_divide, "/=");
    }
|
    expression MOD_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_modulo, "%=");
    }
|
    expression PLUS_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_addition, "+=");
    }
|
    expression MINUS_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_subtract, "-=");
    }
|
    expression AND_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_bitand, "&=");
    }
|
    expression OR_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_bitor, "|=");
    }
|
    expression XOR_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_xor, "^=");
    }
|
    expression SHL_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_shl, "<<=");
    }
|
    expression SHR_IS expression
    {
        $$ = pmv_compoundAss(&$1, &$3, pmv_shr, ">>=");
    }
|
    expression OR expression
    {
        $$ = pmv_or(&$1, &$3);
    }
|
    expression AND expression
    {
        $$ = pmv_and(&$1, &$3);
    }
|
    expression EQUAL expression
    {
        $$ = pmv_equal(&$1, &$3);
    }
|
    expression NOT_EQUAL expression
    {
        $$ = pmv_notEqual(&$1, &$3);
    }
|
    expression '?' expression ':' expression
    {
        $$ = pmv_ternary(&$1, &$3, &$5);
    }
|
    expression '<' expression
    {
        $$ = pmv_smaller(&$1, &$3);
    }
|
    expression '>' expression
    {
        $$ = pmv_greater(&$1, &$3);
    }
|
    expression SMALLER_EQUAL expression
    {
        $$ = pmv_smEqual(&$1, &$3);
    }
|
    expression GREATER_EQUAL expression
    {
        $$ = pmv_grEqual(&$1, &$3);
    }
|
    expression '+' expression
    {
        $$ = pmv_addition(&$1, &$3);
    }
|
    expression '&' expression
    {
        $$ = pmv_bitand(&$1, &$3);
    }
|
    expression '|' expression
    {
        $$ = pmv_bitor(&$1, &$3);
    }
|
    expression '^' expression
    {
        $$ = pmv_xor(&$1, &$3);
    }
|
    expression SHL expression
    {
        $$ = pmv_shl(&$1, &$3);
    }
|
    expression SHR expression
    {
        $$ = pmv_shr(&$1, &$3);
    }
|
    expression '-' expression
    {
        $$ = pmv_subtract(&$1, &$3);
    }
|
    expression '*' expression
    {
        $$ = pmv_multiply(&$1, &$3);
    }
|
    expression YOUNGER expression
    {
        $$ = pmv_young(&$1, &$3);
    }
|
    expression OLDER expression
    {
        $$ = pmv_old(&$1, &$3);
    }
|
    expression '/' expression
    {
        $$ = pmv_divide(&$1, &$3);
    }
|
    expression '%' expression
    {
        $$ = pmv_modulo(&$1, &$3);
    }
|
    '-' expression          %prec '!'
    {
        $$ = pmv_negate(&$2);
    }
|
    INC expression
    {
        $$ = pmv_incDec(pre_op, op_inc, &$2);
    }
|
    expression INC
    {
        $$ = pmv_incDec(post_op, op_inc, &$1);
    }
|
    DEC expression
    {
        $$ = pmv_incDec(pre_op, op_dec, &$2);
    }
|
    expression DEC
    {
        $$ = pmv_incDec(post_op, op_dec, &$1);
    }
|
    '+' expression          %prec '!'
    {
        $$ = SVmove(&$2);
    }
|
    '~'
    expression          %prec '!'
    {
        $$ = pmv_compl(&$2);
    }
|
    '!' expression
    {
        $$ = pmv_not(&$2);
    }
|
    '(' _p_casttype ')' expression         %prec '!'
    {
        $$ = pmv_cast(svType(&$2), &$4);
    }
|
    _string
    {
        $$ = SVtype(e_str | e_const, ssBuf());
    }
|
    NUMBER
    {
        $$ = SVtype(e_int | e_const, util_string());
    }
|
    '[' args ']'
    {
        msg("[ list ]");
        $$ = pmv_listConst(&$2);
    }
|
    '(' expression closeParen
    {
        $$ = SVmove(&$2);
    }
|
    _func_or_var
|
    '`' expression _backtick
    {
        $$ = pmv_oneArg(f_backtick, &$2);
    }
;
