From 1f055d6a66f97020c2b8aac0837bb128d4c696f5 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 4 Oct 2012 15:26:48 -0500 Subject: make functions able to take arbitrary arguments --- lib/Text/Xslate/Syntax/Handlebars.pm | 94 +++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/Text/Xslate/Syntax/Handlebars.pm b/lib/Text/Xslate/Syntax/Handlebars.pm index 5ec07b5..ef0ee9c 100644 --- a/lib/Text/Xslate/Syntax/Handlebars.pm +++ b/lib/Text/Xslate/Syntax/Handlebars.pm @@ -196,7 +196,11 @@ sub preprocess { sub init_symbols { my $self = shift; - $self->symbol('(variable)')->set_nud($self->can('nud_variable')); + for my $type (qw(name variable literal)) { + my $symbol = $self->symbol("($type)"); + $symbol->set_led($self->can("led_$type")); + $symbol->lbp(10); + } $self->infix('.', 256, $self->can('led_dot')); $self->infix('/', 256, $self->can('led_dot')); @@ -217,11 +221,15 @@ sub nud_name { my $self = shift; my ($symbol) = @_; - return $self->call( - $self->SUPER::nud_name($symbol), - # XXX this won't handle multiple arguments - $self->expression($symbol->lbp), - ); + my $name = $self->SUPER::nud_name($symbol); + + return $self->call($name); +} + +sub led_name { + my $self = shift; + + $self->_unexpected("a variable or literal", $self->token); } sub nud_variable { @@ -230,15 +238,47 @@ sub nud_variable { my $var = $self->SUPER::nud_variable(@_); - return $self->make_ternary( - $self->call('(is_code)', $var->clone), - $self->call( - '(run_code)', - $var->clone, - $self->symbol('(vars)')->clone(arity => 'vars'), - ), - $var, - ); + return $self->check_lambda($var); +} + +sub led_variable { + my $self = shift; + my ($symbol, $left) = @_; + + if ($left->arity ne 'call') { + $self->_error("Unexpected variable found", $symbol); + } + + my $var = $symbol; + + # was this actually supposed to be an expression? + # for instance, {{foo bar baz.quux blorg}} + # if we get here for baz, we need to make sure we end up with all of + # baz.quux + # this basically just reimplements $self->expression, except starting + # partway through + while ($self->token->lbp > $var->lbp) { + my $token = $self->token; + $self->advance; + $var = $token->led($self, $var); + } + + push @{ $left->second }, $self->check_lambda($var); + + return $left; +} + +sub led_literal { + my $self = shift; + my ($symbol, $left) = @_; + + if ($left->arity ne 'call') { + $self->_error("Unexpected literal found", $symbol); + } + + push @{ $left->second }, $symbol; + + return $left; } sub led_dot { @@ -392,7 +432,9 @@ sub nud_mark_raw { my $self = shift; my ($symbol) = @_; - return $self->call('mark_raw', $self->expression(0)); + return $self->symbol('mark_raw')->clone( + line => $symbol->line, + )->nud($self); } sub nud_uplevel { @@ -436,7 +478,10 @@ sub define_function { $self->SUPER::define_function(@_); for my $name (@names) { - $self->symbol($name)->set_nud($self->can('nud_name')); + my $symbol = $self->symbol($name); + $symbol->set_nud($self->can('nud_name')); + $symbol->set_led($self->can('led_name')); + $symbol->lbp(10); } return; @@ -487,6 +532,21 @@ sub print_raw { return $self->print(@_)->clone(id => 'print_raw'); } +sub check_lambda { + my $self = shift; + my ($var) = @_; + + return $self->make_ternary( + $self->call('(is_code)', $var->clone), + $self->call( + '(run_code)', + $var->clone, + $self->symbol('(vars)')->clone(arity => 'vars'), + ), + $var, + ); +} + __PACKAGE__->meta->make_immutable; no Any::Moose; -- cgit v1.2.3-54-g00ecf