# $Id: Driver.pm 21027 2007-09-03 10:18:53Z paultcochrane $
# Copyright (C) 2004-2006, The Perl Foundation.
package Regex::Driver;
use strict;
use warnings;
sub new {
my ( $class, $language, %options ) = @_;
if ( $language eq 'perl5' ) {
$class = 'Regex::Driver::Perl5';
}
elsif ( $language eq 'pir' ) {
$class = 'Regex::Driver::PIR';
}
my $self = bless \%options, $class;
$self->init();
return $self;
}
sub init {
}
sub output_header {
}
sub output_rule {
my ( $self, $fh, $subname, $rule, $ctx, %options ) = @_;
my $code = Regex::tree_to_list( $rule, $ctx, 'regex_done', 'regex_done', %options );
my @asm = Regex::list_to_pasm( $code, $ctx, %options );
$self->output_rule_body( $fh, $subname, $rule, $ctx, \@asm );
}
sub output_footer {
}
package Regex::Driver::Perl5;
our @ISA = qw(Regex::Driver);
sub output_header {
my ( $self, $fh ) = @_;
print $fh "use strict;\n";
}
sub output_rule_body {
my ( $self, $fh, $subname, $rule, $ctx, $instructions ) = @_;
if ($subname) {
print $fh <<"END";
sub $subname {
my (\$rx_input) = \@_;
END
}
print $fh "$_\n" foreach (@$instructions);
}
sub output_footer {
my ( $self, $fh ) = @_;
return 1 unless $self->{emit_main};
print $fh <<'END';
sub reduce {
my ($m, $input) = @_;
return if ! $m->{'!RESULT'};
my %r;
while (my ($k, $v) = each %$m) {
next if $k =~ /^!/;
if (UNIVERSAL::isa($v, 'ARRAY')) {
if (@$v == 2 && $v->[1] != -2) {
$r{$k} = substr($input, $v->[0], $v->[1] - $v->[0] + 1);
}
} else {
$r{$k} = reduce($v, $input);
}
}
return \%r;
}
sub match {
my ($input) = @_;
my $m = _rule_default(1, $input, 0, []);
use Data::Dumper;
print Data::Dumper->Dump([$m],["*DEFAULT_RULE_MATCH"]);
return reduce($m, $input);
}
sub minimatch {
my ($m, $name) = @_;
$name ||= 'ALL';
my $res = [ "$name=$m->{0}" ];
while (my ($name, $match) = each %$m) {
push @$res, minimatch($match, $name) if $name !~ /^\d+$/;
}
return $res;
}
my $m = match($ARGV[0]);
$Data::Dumper::Sortkeys = 1;
use Data::Dumper;
print Data::Dumper->Dump([$m],["*MATCH_OBJECT"]);
my $mini = minimatch($m);
print Data::Dumper->Dump([$mini],["*CAPTURES"]);
END
}
package Regex::Driver::PIR;
our @ISA = qw(Regex::Driver);
sub output_header {
my ( $self, $fh ) = @_;
$self->SUPER::output_header($fh);
return 1 unless $self->{emit_main};
print $fh <<'END';
.sub main :main
.param pmc args
.local string input_string
input_string = args[1]
$P0 = loadlib "match_group"
.local pmc regex_sub
.local pmc result
.local int matched
.local pmc stack
stack = new .ResizablePMCArray
result = _default(1, input_string, 0, stack)
matched = result["!RESULT"]
if matched goto printResults
printMatchFailed:
print "Match failed\n"
goto done
printResults:
print "Match found\n"
.local int num_groups
.local int match_num
.local int ii
.local int valid_flag
set num_groups, result["!GROUPS"]
set match_num, 0
printLoop:
ge match_num, num_groups, done
bsr printGroup
inc match_num
goto printLoop
done:
.return ()
printGroup:
.local int match_start
.local int match_end
set match_start, result[match_num;0]
set match_end, result[match_num;1]
eq match_start, -2, skipPrint
eq match_end, -2, skipPrint
print match_num
print ": "
print match_start
print ".."
print match_end
print "\n"
skipPrint:
set valid_flag, 1
ret
.end
END
}
sub output_rule_body {
my ( $self, $fh, $subname, $rule, $ctx, $instructions ) = @_;
print $fh join( "\n", @$instructions ), "\n";
}
sub output_footer {
my ( $self, $fh ) = @_;
my $subname = $self->{subname} || '_regex';
print $fh <<"END";
.sub $subname
.param string rx_input
.local pmc rx_match
.local pmc rx_stack
rx_stack = new IntList
rx_match = _default(1, rx_input, 0, rx_stack)
.return (rx_match)
end
.end
END
}
1;
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4:
syntax highlighted by Code2HTML, v. 0.9.1