Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Perlito5 - parser - implement 5.20 "prototype" attribute
  • Loading branch information
fglock committed May 28, 2014
1 parent b3219ea commit 2223dad
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 29 deletions.
81 changes: 59 additions & 22 deletions html/perlito5.js
Expand Up @@ -2813,6 +2813,8 @@ var List__ = [];
};
var v_to;
p5while(function () {
var v_attr;
v_attr = ((new p5ArrayRef(p5list_to_a(p5pkg["Perlito5::Match"].flat([v_m], 1), null))));
v_to = ((v_m || (v_m = new p5HashRef({})))._hash_.p5hget('to'));
var v_delimiter;
v_delimiter = (p5pkg["Perlito5::Grammar::Attribute"].substr([v_str, v_to, 1], 0));
Expand All @@ -2823,10 +2825,11 @@ var List__ = [];
if ( !( p5bool(v_params)) ) {
p5pkg["Perlito5::Grammar::Attribute"].die([['syntax error']], null)
};
(v_attr || (v_attr = new p5ArrayRef([])))._array_.p5aset(1, ((p5pkg["Perlito5::Match"].flat([v_params], p5want) || (p5pkg["Perlito5::Match"].flat([v_params], p5want) = new p5HashRef({})))._hash_.p5hget('buf')));
v_to = ((v_params || (v_params = new p5HashRef({})))._hash_.p5hget('to'));
})();
};
List_attributes.p5push([p5pkg["Perlito5::Grammar::Attribute"].substr([v_str, v_p, (p5num(v_to) - p5num(v_p))], 1)]);
List_attributes.p5push([v_attr]);
v_ws = (p5call(p5pkg["Perlito5::Grammar::Space"], "opt_ws", [v_str, v_to], 0));
if ( (p5pkg["Perlito5::Grammar::Attribute"].substr([v_str, (v_ws || (v_ws = new p5HashRef({})))._hash_.p5hget('to'), 1], 0) == ':') ) {
v_ws = (p5call(p5pkg["Perlito5::Grammar::Space"], "opt_ws", [v_str, (p5num((v_ws || (v_ws = new p5HashRef({})))._hash_.p5hget('to')) + 1)], 0));
Expand Down Expand Up @@ -8109,6 +8112,23 @@ return (p5call(p5pkg["Perlito5::AST::Val::Buf"], "new", ['buf', p5pkg["Perlito5:
if ( (p5str(v_sig) == '*undef*') ) {
v_sig = (null)
};
var v_attributes;
v_attributes = (p5pkg["Perlito5::Match"].flat(p5list_to_a((v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hget('Perlito5::Grammar::Attribute.opt_attribute')), 0));
var v_proto;
(function () {
var tmp102 = p5list_to_a(p5grep(p5pkg["Perlito5::Grammar::Block"], function (p5want) {
return (p5context([(p5str((p5pkg["Perlito5::Grammar::Block"]["v__"] || (p5pkg["Perlito5::Grammar::Block"]["v__"] = new p5ArrayRef([])))._array_.p5aget(0)) == 'prototype')], p5want));
}, p5list_to_a((v_attributes || (v_attributes = new p5ArrayRef([])))._array_)));
var tmp103 = tmp102.slice(0);
v_proto = tmp102.shift();
return tmp103
})();
if ( p5bool(v_proto) ) {
v_attributes = ((new p5ArrayRef(p5list_to_a(p5grep(p5pkg["Perlito5::Grammar::Block"], function (p5want) {
return (p5context([(p5str((p5pkg["Perlito5::Grammar::Block"]["v__"] || (p5pkg["Perlito5::Grammar::Block"]["v__"] = new p5ArrayRef([])))._array_.p5aget(0)) != 'prototype')], p5want));
}, p5list_to_a((v_attributes || (v_attributes = new p5ArrayRef([])))._array_))))));
v_sig = ((v_proto || (v_proto = new p5ArrayRef([])))._array_.p5aget(1));
};
var v_namespace;
v_namespace = (p5pkg["Perlito5::Match"].flat(p5list_to_a((v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hget('Perlito5::Grammar.optional_namespace_before_ident')), 0));
if ( p5bool(v_name) ) {
Expand All @@ -8121,7 +8141,7 @@ return (p5call(p5pkg["Perlito5::AST::Val::Buf"], "new", ['buf', p5pkg["Perlito5:
(p5make_package("Perlito5")["v_PROTO"] || (p5make_package("Perlito5")["v_PROTO"] = new p5HashRef({})))._hash_.p5hset(p5str(v_full_name), (v_sig));
})();
};
(v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hset('capture', (p5call(p5pkg["Perlito5::AST::Sub"], "new", p5list_to_a('name', v_name, 'namespace', v_namespace, 'sig', v_sig, 'block', (v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hget('_tmp'), 'attributes', p5pkg["Perlito5::Match"].flat(p5list_to_a((v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hget('Perlito5::Grammar::Attribute.opt_attribute')), 1)), 0)));
(v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hset('capture', (p5call(p5pkg["Perlito5::AST::Sub"], "new", p5list_to_a('name', v_name, 'namespace', v_namespace, 'sig', v_sig, 'block', (v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hget('_tmp'), 'attributes', v_attributes), 0)));
return (p5context([1], p5want));
})()], 0) })], 0)], 0));
return (( p5bool(v_tmp) ? v_MATCH : 0));
Expand Down Expand Up @@ -8492,7 +8512,24 @@ return (p5call(p5pkg["Perlito5::AST::Val::Buf"], "new", ['buf', p5pkg["Perlito5:
if ( (p5str(v_sig) == '*undef*') ) {
v_sig = (null)
};
(v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hset('capture', (p5call(p5pkg["Perlito5::AST::Sub"], "new", p5list_to_a('name', null, 'namespace', null, 'sig', v_sig, 'block', p5pkg["Perlito5::Match"].flat(p5list_to_a((v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hget('Perlito5::Grammar.exp_stmts')), 1), 'attributes', p5pkg["Perlito5::Match"].flat(p5list_to_a((v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hget('Perlito5::Grammar::Attribute.opt_attribute')), 1)), 0)));
var v_attributes;
v_attributes = (p5pkg["Perlito5::Match"].flat(p5list_to_a((v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hget('Perlito5::Grammar::Attribute.opt_attribute')), 0));
var v_proto;
(function () {
var tmp104 = p5list_to_a(p5grep(p5pkg["Perlito5::Grammar::Block"], function (p5want) {
return (p5context([(p5str((p5pkg["Perlito5::Grammar::Block"]["v__"] || (p5pkg["Perlito5::Grammar::Block"]["v__"] = new p5ArrayRef([])))._array_.p5aget(0)) == 'prototype')], p5want));
}, p5list_to_a((v_attributes || (v_attributes = new p5ArrayRef([])))._array_)));
var tmp105 = tmp104.slice(0);
v_proto = tmp104.shift();
return tmp105
})();
if ( p5bool(v_proto) ) {
v_attributes = ((new p5ArrayRef(p5list_to_a(p5grep(p5pkg["Perlito5::Grammar::Block"], function (p5want) {
return (p5context([(p5str((p5pkg["Perlito5::Grammar::Block"]["v__"] || (p5pkg["Perlito5::Grammar::Block"]["v__"] = new p5ArrayRef([])))._array_.p5aget(0)) != 'prototype')], p5want));
}, p5list_to_a((v_attributes || (v_attributes = new p5ArrayRef([])))._array_))))));
v_sig = ((v_proto || (v_proto = new p5ArrayRef([])))._array_.p5aget(1));
};
(v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hset('capture', (p5call(p5pkg["Perlito5::AST::Sub"], "new", p5list_to_a('name', null, 'namespace', null, 'sig', v_sig, 'block', p5pkg["Perlito5::Match"].flat(p5list_to_a((v_MATCH || (v_MATCH = new p5HashRef({})))._hash_.p5hget('Perlito5::Grammar.exp_stmts')), 1), 'attributes', v_attributes), 0)));
return (p5context([1], p5want));
})()], 0) })], 0)], 0));
return (( p5bool(v_tmp) ? v_MATCH : 0));
Expand Down Expand Up @@ -9308,12 +9345,12 @@ return (p5call(p5pkg["Perlito5::AST::Val::Buf"], "new", ['buf', p5pkg["Perlito5:
var v_the_object;
var v_expr;
(function () {
var tmp102 = p5list_to_a(List__);
var tmp103 = tmp102.slice(0);
v_decl = tmp102.shift();
v_the_object = tmp102.shift();
v_expr = tmp102.shift();
return tmp103
var tmp106 = p5list_to_a(List__);
var tmp107 = tmp106.slice(0);
v_decl = tmp106.shift();
v_the_object = tmp106.shift();
v_expr = tmp106.shift();
return tmp107
})();
return (p5call(p5pkg["Perlito5::AST::Apply"], "new", ['namespace', '', 'code', v_decl, 'special_arg', v_the_object, 'arguments', v_expr], p5want));
}, null));
Expand Down Expand Up @@ -11874,13 +11911,13 @@ return (p5pkg["Perlito5::Match"].flat([p5pkg["Perlito5::Grammar::Number"]["v__"]
var v_seen;
var v_pos;
(function () {
var tmp104 = p5list_to_a(List__);
var tmp105 = tmp104.slice(0);
v_obj = tmp104.shift();
v_tab = tmp104.shift();
v_seen = tmp104.shift();
v_pos = tmp104.shift();
return tmp105
var tmp108 = p5list_to_a(List__);
var tmp109 = tmp108.slice(0);
v_obj = tmp108.shift();
v_tab = tmp108.shift();
v_seen = tmp108.shift();
v_pos = tmp108.shift();
return tmp109
})();
if ( !( (v_obj != null)) ) {
(function () { throw(p5context(['undef'], p5want)) })()
Expand Down Expand Up @@ -14901,12 +14938,12 @@ return ((p5context([p5pkg["Perlito5::AST::Apply"].ref([p5pkg["Perlito5::AST::App
var v_namespace;
var v_var_env_js;
(function () {
var tmp106 = p5list_to_a(List__);
var tmp107 = tmp106.slice(0);
v_source = tmp106.shift();
v_namespace = tmp106.shift();
v_var_env_js = tmp106.shift();
return tmp107
var tmp110 = p5list_to_a(List__);
var tmp111 = tmp110.slice(0);
v_source = tmp110.shift();
v_namespace = tmp110.shift();
v_var_env_js = tmp110.shift();
return tmp111
})();
var v_strict_old;
v_strict_old = (p5make_package("Perlito5")["v_STRICT"]);
Expand Down
28 changes: 25 additions & 3 deletions perlito5.pl
Expand Up @@ -877,15 +877,17 @@ sub Perlito5::Grammar::Attribute::opt_attribute {
if !$m;
my $to;
while (1) {
my $attr = [Perlito5::Match::flat($m), undef];
$to = $m->{'to'};
my $delimiter = substr($str, $to, 1);
if ($delimiter eq '(') {
my $params = Perlito5::Grammar::String->string_interpolation_parse($str, $m->{'to'} + 1, '(', ')', 0);
die('syntax error')
if !$params;
$attr->[1] = Perlito5::Match::flat($params)->{'buf'};
$to = $params->{'to'}
}
push(@attributes, substr($str, $p, $to - $p));
push(@attributes, $attr);
$ws = Perlito5::Grammar::Space->opt_ws($str, $to);
if (substr($str, $ws->{'to'}, 1) eq ':') {
$ws = Perlito5::Grammar::Space->opt_ws($str, $ws->{'to'} + 1)
Expand Down Expand Up @@ -5579,6 +5581,16 @@ sub Perlito5::Grammar::Block::named_sub_def {
my $sig = Perlito5::Match::flat($MATCH->{'Perlito5::Grammar::Block.prototype'});
$sig = undef
if $sig eq '*undef*';
my $attributes = Perlito5::Match::flat($MATCH->{'Perlito5::Grammar::Attribute.opt_attribute'});
my($proto) = grep {
$_->[0] eq 'prototype'
} @{$attributes};
if ($proto) {
$attributes = [grep {
$_->[0] ne 'prototype'
} @{$attributes}];
$sig = $proto->[1]
}
my $namespace = Perlito5::Match::flat($MATCH->{'Perlito5::Grammar.optional_namespace_before_ident'});
if ($name) {
if (!$namespace) {
Expand All @@ -5587,7 +5599,7 @@ sub Perlito5::Grammar::Block::named_sub_def {
my $full_name = $namespace . '::' . $name;
$Perlito5::PROTO->{$full_name} = $sig
}
$MATCH->{'capture'} = Perlito5::AST::Sub->new('name' => $name, 'namespace' => $namespace, 'sig' => $sig, 'block' => $MATCH->{'_tmp'}, 'attributes' => Perlito5::Match::flat($MATCH->{'Perlito5::Grammar::Attribute.opt_attribute'}));
$MATCH->{'capture'} = Perlito5::AST::Sub->new('name' => $name, 'namespace' => $namespace, 'sig' => $sig, 'block' => $MATCH->{'_tmp'}, 'attributes' => $attributes);
1
})));
$tmp ? $MATCH : 0
Expand Down Expand Up @@ -5885,7 +5897,17 @@ sub Perlito5::Grammar::Block::anon_sub_def {
my $sig = Perlito5::Match::flat($MATCH->{'prototype'});
$sig = undef
if $sig eq '*undef*';
$MATCH->{'capture'} = Perlito5::AST::Sub->new('name' => undef, 'namespace' => undef, 'sig' => $sig, 'block' => Perlito5::Match::flat($MATCH->{'Perlito5::Grammar.exp_stmts'}), 'attributes' => Perlito5::Match::flat($MATCH->{'Perlito5::Grammar::Attribute.opt_attribute'}));
my $attributes = Perlito5::Match::flat($MATCH->{'Perlito5::Grammar::Attribute.opt_attribute'});
my($proto) = grep {
$_->[0] eq 'prototype'
} @{$attributes};
if ($proto) {
$attributes = [grep {
$_->[0] ne 'prototype'
} @{$attributes}];
$sig = $proto->[1]
}
$MATCH->{'capture'} = Perlito5::AST::Sub->new('name' => undef, 'namespace' => undef, 'sig' => $sig, 'block' => Perlito5::Match::flat($MATCH->{'Perlito5::Grammar.exp_stmts'}), 'attributes' => $attributes);
1
})));
$tmp ? $MATCH : 0
Expand Down
4 changes: 3 additions & 1 deletion src5/lib/Perlito5/Grammar/Attribute.pm
Expand Up @@ -21,15 +21,17 @@ sub opt_attribute {
my $to;
while (1) {

my $attr = [ Perlito5::Match::flat($m), undef ];
$to = $m->{to};
my $delimiter = substr( $str, $to, 1 );
if ($delimiter eq '(') {
# "ident(params)"
my $params = Perlito5::Grammar::String->string_interpolation_parse($str, $m->{to} + 1, '(', ')', 0);
die "syntax error" if !$params;
$attr->[1] = Perlito5::Match::flat($params)->{buf};
$to = $params->{to};
}
push @attributes, substr( $str, $p, $to - $p );
push @attributes, $attr;

# check if the attribute list continues
$ws = Perlito5::Grammar::Space->opt_ws( $str, $to );
Expand Down
20 changes: 18 additions & 2 deletions src5/lib/Perlito5/Grammar/Block.pm
Expand Up @@ -129,6 +129,14 @@ token named_sub_def {
my $name = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar.ident"});
my $sig = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::Block.prototype"});
$sig = undef if $sig eq '*undef*';

my $attributes = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::Attribute.opt_attribute"});
my ($proto) = grep { $_->[0] eq 'prototype' } @$attributes;
if ($proto) {
$attributes = [grep { $_->[0] ne 'prototype' } @$attributes];
$sig = $proto->[1];
}

my $namespace = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar.optional_namespace_before_ident"});
if ( $name ) {
# say "sub $Perlito5::PKG_NAME :: $name ( $sig )";
Expand Down Expand Up @@ -159,7 +167,7 @@ token named_sub_def {
namespace => $namespace,
sig => $sig,
block => $MATCH->{_tmp},
attributes => Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::Attribute.opt_attribute"}),
attributes => $attributes,
)
}
};
Expand Down Expand Up @@ -219,12 +227,20 @@ token anon_sub_def {
{
my $sig = Perlito5::Match::flat($MATCH->{prototype});
$sig = undef if $sig eq '*undef*';

my $attributes = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::Attribute.opt_attribute"});
my ($proto) = grep { $_->[0] eq 'prototype' } @$attributes;
if ($proto) {
$attributes = [grep { $_->[0] ne 'prototype' } @$attributes];
$sig = $proto->[1];
}

$MATCH->{capture} = Perlito5::AST::Sub->new(
name => undef,
namespace => undef,
sig => $sig,
block => Perlito5::Match::flat($MATCH->{'Perlito5::Grammar.exp_stmts'}),
attributes => Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::Attribute.opt_attribute"}),
attributes => $attributes,
)
}
};
Expand Down
20 changes: 19 additions & 1 deletion t5/01-perlito/410-ampersand.t
@@ -1,7 +1,7 @@
use feature 'say';
use strict;

say "1..30";
say "1..32";

my $v = 0;
my $r = 0;
Expand Down Expand Up @@ -194,4 +194,22 @@ print "ok 29 - with_proto $v\n";
print "not " if $r != 7;
print "ok 30 - with_proto $r\n";

# sanity test with proto attribute

sub with_proto_attr :prototype() {
if (@_) {
$v += $_[0]
}
else {
$v += 8
}
}

$v = 3;
$r = with_proto_attr + 4;
print "not " if $v != 11;
print "ok 31 - with_proto_attr $v\n";
print "not " if $r != 15;
print "ok 32 - with_proto_attr $r\n";


0 comments on commit 2223dad

Please sign in to comment.