Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Perlito5 - parser - precedence fix; Tests=863
  • Loading branch information
fglock committed Nov 29, 2012
1 parent 3b33471 commit 283ea50
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 17 deletions.
48 changes: 44 additions & 4 deletions html/perlito5.js
Expand Up @@ -527,6 +527,17 @@ p5decr = function(o) {
return p5num(o) - 1;
};

p5modulo = function(o, k) {
var m = o % k;
if ( k < 0 && m > 0 ) {
m = m + k;
}
else if ( k > 0 && m < 0 ) {
m = m + k;
}
return m;
};

p5shift_left = function(o, k) {
return k < 31 ? o << k : o * Math.pow(2, k);
};
Expand Down Expand Up @@ -2299,7 +2310,7 @@ var p5100 = p5pkg['main'];
// our p5pkg["Perlito5::Javascript2"]["Hash_op_infix_js_str"]
(p5pkg["Perlito5::Javascript2"]["Hash_op_infix_js_str"] = {'infix:<eq>' : ' == ', 'infix:<ne>' : ' != ', 'infix:<le>' : ' <= ', 'infix:<ge>' : ' >= ', 'infix:<lt>' : ' < ', 'infix:<gt>' : ' > '});
// our p5pkg["Perlito5::Javascript2"]["Hash_op_infix_js_num"]
(p5pkg["Perlito5::Javascript2"]["Hash_op_infix_js_num"] = {'infix:<==>' : ' == ', 'infix:<!=>' : ' != ', 'infix:<+>' : ' + ', 'infix:<->' : ' - ', 'infix:<*>' : ' * ', 'infix:</>' : ' / ', 'infix:<%>' : ' % ', 'infix:<>>' : ' > ', 'infix:<<>' : ' < ', 'infix:<>=>' : ' >= ', 'infix:<<=>' : ' <= ', 'infix:<&>' : ' & ', 'infix:<|>' : ' | ', 'infix:<^>' : ' ^ ', 'infix:<>>>' : ' >>> '});
(p5pkg["Perlito5::Javascript2"]["Hash_op_infix_js_num"] = {'infix:<==>' : ' == ', 'infix:<!=>' : ' != ', 'infix:<+>' : ' + ', 'infix:<->' : ' - ', 'infix:<*>' : ' * ', 'infix:</>' : ' / ', 'infix:<>>' : ' > ', 'infix:<<>' : ' < ', 'infix:<>=>' : ' >= ', 'infix:<<=>' : ' <= ', 'infix:<&>' : ' & ', 'infix:<|>' : ' | ', 'infix:<^>' : ' ^ ', 'infix:<>>>' : ' >>> '});
// our p5pkg["Perlito5::Javascript2"]["Hash_op_to_bool"]
(p5pkg["Perlito5::Javascript2"]["Hash_op_to_bool"] = p5a_to_h(p5list_to_a(p5map(p5pkg["Perlito5::Javascript2"], function (p5want) {
return ((p5context([p5pkg["Perlito5::Javascript2"]["v__"], 1], p5want)));
Expand Down Expand Up @@ -3632,6 +3643,12 @@ var p5100 = p5pkg['main'];
(v_self = (List__.p5aget(0)));
return (p5context([('p5shift_left(' + p5pkg["Perlito5::AST::Apply"].join([', ', p5list_to_a(p5map(p5pkg["Perlito5::AST::Apply"], function (p5want) {
return (p5pkg["Perlito5::Javascript2"].to_num([p5pkg["Perlito5::AST::Apply"]["v__"]], p5want));
}, p5list_to_a((v_self || (v_self = new p5HashRef({})))._hash_.p5hget_array('arguments')._array_)))], 0) + ')')], p5want));
}, 'infix:<%>', function (List__, p5want) {
var v_self;
(v_self = (List__.p5aget(0)));
return (p5context([('p5modulo(' + p5pkg["Perlito5::AST::Apply"].join([', ', p5list_to_a(p5map(p5pkg["Perlito5::AST::Apply"], function (p5want) {
return (p5pkg["Perlito5::Javascript2"].to_num([p5pkg["Perlito5::AST::Apply"]["v__"]], p5want));
}, p5list_to_a((v_self || (v_self = new p5HashRef({})))._hash_.p5hget_array('arguments')._array_)))], 0) + ')')], p5want));
}, 'prefix:<!>', function (List__, p5want) {
var v_self;
Expand Down Expand Up @@ -4681,6 +4698,8 @@ var p5100 = p5pkg['main'];
(v_Operator = ((new p5HashRef({}))));
var v_Precedence;
(v_Precedence = ((new p5HashRef({}))));
var v_PrefixPrecedence;
(v_PrefixPrecedence = ((new p5HashRef({}))));
var v_Assoc;
(v_Assoc = ((new p5HashRef({}))));
p5make_sub("Perlito5::Precedence", "is_assoc_type", function (List__, p5want) {
Expand Down Expand Up @@ -4894,6 +4913,9 @@ var p5100 = p5pkg['main'];
(v_assoc = (p5or((v_param || (v_param = new p5HashRef({})))._hash_.p5hget('assoc'), function () { return 'left' })));
(v_Operator || (v_Operator = new p5HashRef({})))._hash_.p5hget_hash(p5str(v_fixity))._hash_.p5hset(p5str(v_name), (1));
(v_Precedence || (v_Precedence = new p5HashRef({})))._hash_.p5hset(p5str(v_name), (v_precedence));
if ( (p5str(v_fixity) == 'prefix') ) {
(v_PrefixPrecedence || (v_PrefixPrecedence = new p5HashRef({})))._hash_.p5hset(p5str(v_name), (v_precedence));
};
(v_Assoc || (v_Assoc = new p5HashRef({})))._hash_.p5hget_hash(p5str(v_assoc))._hash_.p5hset(p5str(v_name), (1));
return (Hash_Op.p5hset(p5str(v_name), (1)));
});
Expand Down Expand Up @@ -5005,6 +5027,24 @@ var p5100 = p5pkg['main'];
p5pkg["Perlito5::Precedence"].add_op(['infix', 'xor', v_prec], null);
(v_prec = ((p5num(v_prec) - 1)));
p5pkg["Perlito5::Precedence"].add_op(['infix', '*start*', v_prec], null);
p5make_sub("Perlito5::Precedence", "get_token_precedence", function (List__, p5want) {
try {
var v_token;
(v_token = (List__.p5aget(0)));
if ( (p5str((v_token || (v_token = new p5ArrayRef([])))._array_.p5aget(0)) == 'prefix') ) {
throw((v_PrefixPrecedence || (v_PrefixPrecedence = new p5HashRef({})))._hash_.p5hget(p5str((v_token || (v_token = new p5ArrayRef([])))._array_.p5aget(1))));
};
return ((v_Precedence || (v_Precedence = new p5HashRef({})))._hash_.p5hget(p5str((v_token || (v_token = new p5ArrayRef([])))._array_.p5aget(1))));
}
catch(err) {
if ( err instanceof Error ) {
throw(err);
}
else {
return(err);
}
}
});
p5make_sub("Perlito5::Precedence", "precedence_parse", function (List__, p5want) {
var v_self;
(v_self = (List__.shift()));
Expand Down Expand Up @@ -5048,7 +5088,7 @@ var p5100 = p5pkg['main'];
(v_pr = ((v_Precedence || (v_Precedence = new p5HashRef({})))._hash_.p5hget(p5str((v_token || (v_token = new p5ArrayRef([])))._array_.p5aget(1)))));
p5while(function () {
(v_reduce)([v_op_stack, v_num_stack], null);
}, function () { return p5and(((v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_), function () { return p5context([(p5num(v_pr) <= p5num((v_Precedence || (v_Precedence = new p5HashRef({})))._hash_.p5hget(p5str((p5context([(v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_.p5aget(0)], 0) || (p5context([(v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_.p5aget(0)], 0) = new p5ArrayRef([])))._array_.p5aget(1)))))], 0) }) }, false, "");
}, function () { return p5and(((v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_), function () { return p5context([(p5num(v_pr) <= p5num(p5pkg["Perlito5::Precedence"].get_token_precedence(p5list_to_a((v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_.p5aget(0)), 0)))], 0) }) }, false, "");
if ( (p5str((v_token || (v_token = new p5ArrayRef([])))._array_.p5aget(0)) != 'postfix_or_term') ) {
(v_token || (v_token = new p5ArrayRef([])))._array_.p5aset(0, ('postfix'));
};
Expand All @@ -5074,12 +5114,12 @@ var p5100 = p5pkg['main'];
if ( p5bool((v_Assoc || (v_Assoc = new p5HashRef({})))._hash_.p5hget_hash('right')._hash_.p5hget(p5str((v_token || (v_token = new p5ArrayRef([])))._array_.p5aget(1)))) ) {
p5while(function () {
(v_reduce)([v_op_stack, v_num_stack], null);
}, function () { return p5and(((v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_), function () { return p5context([(p5num(v_pr) < p5num((v_Precedence || (v_Precedence = new p5HashRef({})))._hash_.p5hget(p5str((p5context([(v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_.p5aget(0)], 0) || (p5context([(v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_.p5aget(0)], 0) = new p5ArrayRef([])))._array_.p5aget(1)))))], 0) }) }, false, "");
}, function () { return p5and(((v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_), function () { return p5context([(p5num(v_pr) < p5num(p5pkg["Perlito5::Precedence"].get_token_precedence(p5list_to_a((v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_.p5aget(0)), 0)))], 0) }) }, false, "");
}
else {
p5while(function () {
(v_reduce)([v_op_stack, v_num_stack], null);
}, function () { return p5and(((v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_), function () { return p5context([(p5num(v_pr) <= p5num((v_Precedence || (v_Precedence = new p5HashRef({})))._hash_.p5hget(p5str((p5context([(v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_.p5aget(0)], 0) || (p5context([(v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_.p5aget(0)], 0) = new p5ArrayRef([])))._array_.p5aget(1)))))], 0) }) }, false, "");
}, function () { return p5and(((v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_), function () { return p5context([(p5num(v_pr) <= p5num(p5pkg["Perlito5::Precedence"].get_token_precedence(p5list_to_a((v_op_stack || (v_op_stack = new p5ArrayRef([])))._array_.p5aget(0)), 0)))], 0) }) }, false, "");
};
if ( p5bool((v_Operator || (v_Operator = new p5HashRef({})))._hash_.p5hget_hash('ternary')._hash_.p5hget(p5str((v_token || (v_token = new p5ArrayRef([])))._array_.p5aget(1)))) ) {
(v_token || (v_token = new p5ArrayRef([])))._array_.p5aset(0, ('ternary'));
Expand Down
24 changes: 19 additions & 5 deletions perlito5.pl

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion src5/lib/Perlito5/Javascript2/Emitter.pm
Expand Up @@ -54,7 +54,7 @@ package Perlito5::Javascript2;
'infix:<->' => ' - ',
'infix:<*>' => ' * ',
'infix:</>' => ' / ',
'infix:<%>' => ' % ',
# 'infix:<%>' => ' % ',
'infix:<>>' => ' > ',
'infix:<<>' => ' < ',
'infix:<>=>' => ' >= ',
Expand Down Expand Up @@ -1392,6 +1392,10 @@ package Perlito5::AST::Apply;
my $self = $_[0];
'p5shift_left(' . join( ', ', map( Perlito5::Javascript2::to_num($_), @{ $self->{arguments} } ) ) . ')';
},
'infix:<%>' => sub {
my $self = $_[0];
'p5modulo(' . join( ', ', map( Perlito5::Javascript2::to_num($_), @{ $self->{arguments} } ) ) . ')';
},
'prefix:<!>' => sub {
my $self = shift;
my $level = shift;
Expand Down
11 changes: 11 additions & 0 deletions src5/lib/Perlito5/Javascript2/Runtime.pm
Expand Up @@ -533,6 +533,17 @@ p5decr = function(o) {
return p5num(o) - 1;
};
p5modulo = function(o, k) {
var m = o % k;
if ( k < 0 && m > 0 ) {
m = m + k;
}
else if ( k > 0 && m < 0 ) {
m = m + k;
}
return m;
};
p5shift_left = function(o, k) {
return k < 31 ? o << k : o * Math.pow(2, k);
};
Expand Down
22 changes: 16 additions & 6 deletions src5/lib/Perlito5/Precedence.pm
Expand Up @@ -14,9 +14,10 @@ sub new {
bless {@_}, $class
}

my $Operator = {};
my $Precedence = {}; # integer 0..100
my $Assoc = {}; # right, left, list
my $Operator = {};
my $Precedence = {}; # integer 0..100
my $PrefixPrecedence = {}; # integer 0..100; 'prefix' operations
my $Assoc = {}; # right, left, list

sub is_assoc_type {
my $assoc_type = shift;
Expand Down Expand Up @@ -201,6 +202,7 @@ sub add_op {
my $assoc = $param->{assoc} || 'left';
$Operator->{$fixity}{$name} = 1;
$Precedence->{$name} = $precedence;
$PrefixPrecedence->{$name} = $precedence if $fixity eq 'prefix';
$Assoc->{$assoc}{$name} = 1;
$Op{$name} = 1;
}
Expand Down Expand Up @@ -381,6 +383,14 @@ $prec = $prec - 1;
add_op( 'infix', '*start*', $prec );


sub get_token_precedence {
my $token = $_[0];
if ( $token->[0] eq 'prefix' ) {
return $PrefixPrecedence->{ $token->[1] }
}
return $Precedence->{ $token->[1] }
}

sub precedence_parse {

# this routine implements operator precedence
Expand Down Expand Up @@ -427,7 +437,7 @@ sub precedence_parse {
elsif ( $Operator->{postfix}{$token->[1]} && $last_is_term )
{
my $pr = $Precedence->{$token->[1]};
while (scalar(@$op_stack) && ($pr <= $Precedence->{ ($op_stack->[0])[1] })) {
while (scalar(@$op_stack) && ($pr <= get_token_precedence($op_stack->[0]))) {
$reduce->($op_stack, $num_stack);
}
if ($token->[0] ne 'postfix_or_term') {
Expand All @@ -450,12 +460,12 @@ sub precedence_parse {
elsif ($Precedence->{$token->[1]}) {
my $pr = $Precedence->{$token->[1]};
if ($Assoc->{right}{$token->[1]}) {
while (scalar(@$op_stack) && ( $pr < $Precedence->{ ($op_stack->[0])[1] } )) {
while (scalar(@$op_stack) && ( $pr < get_token_precedence($op_stack->[0]))) {
$reduce->($op_stack, $num_stack);
}
}
else {
while (scalar(@$op_stack) && ( $pr <= $Precedence->{ ($op_stack->[0])[1] } )) {
while (scalar(@$op_stack) && ( $pr <= get_token_precedence($op_stack->[0]))) {
$reduce->($op_stack, $num_stack);
}
}
Expand Down
2 changes: 1 addition & 1 deletion t5/op/arith.t
Expand Up @@ -5,7 +5,7 @@ BEGIN {
@INC = '../lib';
}

print "1..145\n";
print "1..144\n";

sub try ($$) {
print +($_[1] ? "ok" : "not ok"), " $_[0]\n";
Expand Down

0 comments on commit 283ea50

Please sign in to comment.