Perl6-Pugs/misc/Parser-Mini/pil1_json_parser.pl
# PIL2 simple tokenizer & parser
# ../../pugs -CPIL2-JSON -e ' say "hello" ' | ../../pugs pil2_tokenizer.pl
use v6-alpha;
# tokenizer
my $tokens =
m:g:perl5 {(\"(?:\\\\|\\"|.)*?\"|[\:\,\=\{\(\[\}\)\]]|\w+)};
# JSON parser
# outputs a p6 tree = Hash of Array|Hash|Scalar ...
sub parse (@start, $token, @end, @_ is rw) {
state %tok = (
token => sub (@_ is rw) {
~ @_.shift; # '~' stringifies "Match" object
},
hash => sub (@_ is rw) {
my Hash $h;
my Pair $p;
loop {
return $h if @_[0] eq '}';
$p = parse( <<>>, 'pair', <<>>, @_ );
$h{$p.key} = $p.value;
return $h if @_[0] ne ',';
@_.shift;
}
},
list => sub (@_ is rw) {
my Array $a;
loop {
return $a if @_[0] eq ']';
push $a, parse( <<>>, 'item', <<>>, @_ );
return $a if @_[0] ne ',';
@_.shift;
}
},
pair => sub (@_ is rw) {
my $key = parse( <<>>, 'token', << : >>, @_ );
# say " Key $key";
my $value = parse( <<>>, 'item', <<>>, @_ );
( $key => $value );
},
item => sub (@_ is rw) {
if @_[0] eq '{' {
return parse( << { >>, 'hash', << } >>, @_ )
};
if @_[0] eq '[' {
return parse( << [ >>, 'list', << ] >>, @_ )
};
parse( <<>>, 'token', <<>>, @_ );
},
);
# say " parse: @start[] <$token> @end[]";
for @start { @_.shift eq $_ or die "Expected $_" };
# say " Tail @_[]";
my $ret = %tok{$token}( @_ );
for @end { @_.shift eq $_ or die "Expected $_" };
$ret;
}
my @pil2 = =<>;
my $pil2 = @pil2.join('');
# my $pil2 = =<>.slurp; ???
my @b = $pil2 ~~ $tokens;
# say "Tokens: ", @b.join('><');
my $ast = parse( << { >>, 'hash', << } >>, @b );
say $ast.perl;