|
NAMEJE::Parser - Framework for customising JE's parser SYNOPSIS use JE;
use JE::Parser;
$je = new JE;
$p = new JE::Parser $je; # or: $p = $je->new_parser
$p->delete_statement('for', 'while', 'do'); # disable loops
$p->add_statement(try => \&parser); # replace existing 'try' statement
DESCRIPTIONThis allows one to change the list of statement types that the parser looks for. For instance, one could disable loops for a mini-JavaScript, or add extensions to the language, such as the 'catch-if' clause of a "try" statement. As yet, "delete_statement" works, but I've not finished designing the API for "add_statement". I might provide an API for extending expressions, if I can resolve the complications caused by the 'new' operator. If anyone else wants to have a go at it, be my guest. :-) METHODS
Maybe we need support for a JavaScript function to be called to handnle the statement.
EXPORTSNone by default. You may choose to export the following: Exported Variables... blah blah blah ... Exported FunctionsThese all have "()" for their prototype, except for "expected" which has "($)". ... blah blah blah ... SYNTAX ERRORS(To be written) expected 'aaaa'; # will be changed to 'Expected aaaa but found....' die \\"You can't put a doodad after a frombiggle!"; # complete message die 'aoenstuhoeanthu'; # big no-no (the error is propagated) EXAMPLESMini JavaScriptThis is an example of a mini JavaScript that does not allow loops or the creation of functions. use JE;
$j = new JE;
$p = $j->new_parser;
$p->delete_statement('for','while','do','-function');
Since function expressions could still create functions, we need to remove the Function prototype object. Someone might then try to put it back with "Function = parseInt.constructor", so we'll overwrite Function with an undeletable read-only undefined property. $j->prop({ name => 'Function',
value => undef,
readonly => 1,
dontdel => 1 });
Then, after this, we call "$p->eval('...')" to run JS code. Perl-style for(LIST) loopWell, after writing this example, it seems to me this API is not sufficient.... This example doesn't actually work yet. use JE;
use JE::Parser qw'$s ident expr statement expected';
$j = new JE;
$p = $j->new_parser;
$p->add_statement('for-list',
sub {
/\Gfor$s/cog or return;
my $loopvar = ident or return;
/\G$s\($s/cog or return;
my @expressions;
do {
# This line doesn't actually work properly because
# 'expr' will gobble up all the commas
@expressions == push @expressions, expr
and return; # If nothing gets pushed on to the
# list, we need to give the default
# 'for' handler a chance, instead of
# throwing an error.
} while /\G$s,$s/cog;
my $statement = statement or expected 'statement';
return bless {
var => $loopvar,
expressions => \@expressions,
statement => $statement
}, 'Local::JEx::ForList';
}
);
package Local::JEx::ForList;
sub eval {
my $self = shift;
local $JE::Code::scope =
bless [@$JE::Code::scope], 'JE::Scope';
# I've got to come up with a better interface than this.
my $obj = $JE::Code::global->eval('new Object');
push @$JE::Code::scope, $obj;
for (@{$self->{expressions}}) {
$obj->{ $self->{loopvar} } = $_->eval;
$self->{statement}->execute;
}
}
SEE ALSOJE and JE::Code.
|