#!perl
use
5.010001;
sub
subtraction {
shift
;
my
(
$right_string
,
$right_value
) = (
$_
[2] =~ /^(.*)==(.*)$/xms );
my
(
$left_string
,
$left_value
) = (
$_
[0] =~ /^(.*)==(.*)$/xms );
my
$value
=
$left_value
-
$right_value
;
return
'('
.
$left_string
.
q{-}
.
$right_string
.
')=='
.
$value
;
}
sub
postfix_decr {
shift
;
my
(
$string
,
$value
) = (
$_
[0] =~ /^(.*)==(.*)$/xms );
return
'('
.
$string
.
q{--}
.
')=='
.
$value
--;
}
sub
prefix_decr {
shift
;
my
(
$string
,
$value
) = (
$_
[1] =~ /^(.*)==(.*)$/xms );
return
'('
.
q{--}
.
$string
.
')=='
. --
$value
;
}
sub
negation {
shift
;
my
(
$string
,
$value
) = (
$_
[1] =~ /^(.*)==(.*)$/xms );
return
'('
.
q{-}
.
$string
.
')=='
. -
$value
;
}
sub
number {
shift
;
my
$value
=
$_
[0];
return
"$value==$value"
;
}
sub
minusminus {
return
q{--}
;
}
sub
default_action {
shift
;
return
q{}
if
scalar
@_
<= 0;
return
$_
[0]
if
scalar
@_
== 1;
return
'('
.
join
(
q{;}
,
@_
) .
')'
;
}
my
$grammar
= Marpa::R3::Scanless::G->new(
{
source
=> \
<<'END_OF_DSL',
:default ::= action => default_action
E ::= E Minus E action => subtraction
E ::= E MinusMinus action => postfix_decr
E ::= MinusMinus E action => prefix_decr
E ::= Minus E action => negation
E ::= Number action => number
MinusMinus ::= Minus Minus action => minusminus
Minus ~ '-'
Number ~ [\d]+
END_OF_DSL
}
);
my
$recce
= Marpa::R3::Scanless::R->new( {
grammar
=>
$grammar
,
semantics_package
=>
'main'
,
} );
Marpa::R3::Test::is(
$grammar
->show_rules,
<<'END_RULES', 'Minuses Equation Rules' );
G1 R0 E ::= E Minus E
G1 R1 E ::= E MinusMinus
G1 R2 E ::= MinusMinus E
G1 R3 E ::= Minus E
G1 R4 E ::= Number
G1 R5 MinusMinus ::= Minus Minus
G1 R6 [:start] ::= E
END_RULES
Marpa::R3::Test::is(
$grammar
->show_ahms,
<<'END_AHMS', 'Minuses Equation AHMs' );
AHM 0: postdot = "E"
E ::= . E Minus E
AHM 1: postdot = "Minus"
E ::= E . Minus E
AHM 2: postdot = "E"
E ::= E Minus . E
AHM 3: completion
E ::= E Minus E .
AHM 4: postdot = "E"
E ::= . E MinusMinus
AHM 5: postdot = "MinusMinus"
E ::= E . MinusMinus
AHM 6: completion
E ::= E MinusMinus .
AHM 7: postdot = "MinusMinus"
E ::= . MinusMinus E
AHM 8: postdot = "E"
E ::= MinusMinus . E
AHM 9: completion
E ::= MinusMinus E .
AHM 10: postdot = "Minus"
E ::= . Minus E
AHM 11: postdot = "E"
E ::= Minus . E
AHM 12: completion
E ::= Minus E .
AHM 13: postdot = "Number"
E ::= . Number
AHM 14: completion
E ::= Number .
AHM 15: postdot = "Minus"
MinusMinus ::= . Minus Minus
AHM 16: postdot = "Minus"
MinusMinus ::= Minus . Minus
AHM 17: completion
MinusMinus ::= Minus Minus .
AHM 18: postdot = "E"
[:start] ::= . E
AHM 19: completion
[:start] ::= E .
AHM 20: postdot = "[:start]"
[:start]['] ::= . [:start]
AHM 21: completion
[:start]['] ::= [:start] .
END_AHMS
my
%expected
=
map
{ (
$_
=> 1 ) } (
'(((6--)--)-1)==5'
,
'((6--)-(--1))==6'
,
'((6--)-(-(-1)))==5'
,
'(6-(--(--1)))==7'
,
'(6-(--(-(-1))))==6'
,
'(6-(-(--(-1))))==4'
,
'(6-(-(-(--1))))==6'
,
'(6-(-(-(-(-1)))))==5'
,
);
$recce
->
read
( \
q{6-----1}
);
$recce
->set( {
max_parses
=> 20 } );
while
(
my
$value_ref
=
$recce
->value() ) {
my
$value
=
$value_ref
? ${
$value_ref
} :
'No parse'
;
if
(
defined
$expected
{
$value
} ) {
delete
$expected
{
$value
};
Test::More::pass(
"Expected Value $value"
);
}
else
{
Test::More::fail(
"Unexpected Value $value"
);
}
}
1;