diff --git a/src/NQP/Actions.pm b/src/NQP/Actions.pm index 2154aa8..fa56c01 100644 --- a/src/NQP/Actions.pm +++ b/src/NQP/Actions.pm @@ -252,6 +252,7 @@ NQP::Grammar.O(':prec, :assoc', '%concatenation'); NQP::Grammar.O(':prec, :assoc', '%relational'); NQP::Grammar.O(':prec, :assoc', '%tight_and'); NQP::Grammar.O(':prec, :assoc', '%tight_or'); +NQP::Grammar.O(':prec, :assoc', '%conditional'); NQP::Grammar.O(':prec, :assoc', '%assignment'); NQP::Grammar.O(':prec, :assoc, :nextterm', '%comma'); NQP::Grammar.O(':prec, :assoc', '%list_infix'); diff --git a/src/NQP/Grammar.pm b/src/NQP/Grammar.pm index a11cc1e..62132b9 100644 --- a/src/NQP/Grammar.pm +++ b/src/NQP/Grammar.pm @@ -1,6 +1,8 @@ grammar NQP::Grammar is HLL::Grammar; -token TOP { } +token TOP { + +} token comp_unit { <.newpad> @@ -219,6 +221,14 @@ token infix:sym<&&> { ')> } token infix:sym<||> { ')> } token infix:sym { ')> } +token infix:sym { + '??' + <.ws> + + '!!' + , :pasttype')> +} + token infix:sym<:=> { ')> } token infix:sym<::=> { ')> } diff --git a/src/cheats/hll-grammar.pir b/src/cheats/hll-grammar.pir index 2bb0bee..8f90c51 100644 --- a/src/cheats/hll-grammar.pir +++ b/src/cheats/hll-grammar.pir @@ -424,6 +424,13 @@ An operator precedence parser. =cut .sub 'EXPR' :method + .param string preclim :optional + .param int has_preclim :opt_flag + + if has_preclim goto have_preclim + preclim = '' + have_preclim: + .const 'Sub' reduce = 'EXPR_reduce' .local string termish termish = 'termish' @@ -520,6 +527,7 @@ An operator precedence parser. .local string inprec, inassoc, opprec inprec = inO['prec'] unless inprec goto err_inprec + if inprec <= preclim goto term_done inassoc = inO['assoc'] reduce_loop: @@ -591,6 +599,10 @@ An operator precedence parser. left = pop termstack op[0] = left op[1] = right + $S0 = opO['reducecheck'] + unless $S0 goto op_infix_1 + self.$S0(op) + op_infix_1: self.'!reduce'('EXPR', 'INFIX', op) goto done diff --git a/src/cheats/nqp-builtins.pir b/src/cheats/nqp-builtins.pir index 35f95b4..18fc57f 100644 --- a/src/cheats/nqp-builtins.pir +++ b/src/cheats/nqp-builtins.pir @@ -48,3 +48,15 @@ $P0 = box 0 set_global '$test_counter', $P0 .end + + +.namespace ['NQP';'Grammar'] + +.sub 'ternary' :method + .param pmc match + $P0 = match[1] + $P1 = match['infix'] + $P1 = $P1['EXPR'] + match[1] = $P1 + match[2] = $P0 +.end diff --git a/t/nqp/16-ternary.t b/t/nqp/16-ternary.t new file mode 100644 index 0000000..8eab8da --- /dev/null +++ b/t/nqp/16-ternary.t @@ -0,0 +1,23 @@ +#!./parrot nqp.pbc + +# the ternary ?? !! operator + +plan(8); + +ok( 1 ?? 1 !! 0 ); +ok( 0 ?? 0 !! 1 ); + +my $a := 1 ?? 'yes' !! 'no'; +ok( $a eq 'yes' ); + +my $b := 0 ?? 'yes' !! 'no'; +ok( $b eq 'no' ); + +my $c := 1 ?? 'yes' !! ( $a := 'no' ); +ok( $c eq 'yes' ); +ok( $a eq 'yes' ); + +my $d := 0 ?? ( $a := 'no' ) !! 'yes'; +ok( $d eq 'yes' ); +ok( $a eq 'yes' ); +