e173910baf3ff86139e30c9e1c1d03cc2bca1a86
2 use feature
qw(switch);
4 use warnings FATAL
=> qw(all);
6 our @EXPORT_OK = qw( read_str );
8 use types
qw($nil $true $false);
16 bless { position => 0, tokens => shift } => $class
18 sub next { my $self = shift; return $self->{tokens}[$self->{position}++] }
19 sub peek { my $self = shift; return $self->{tokens}[$self->{position}] }
24 my @tokens = $str =~ /[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)/g;
25 return grep {! /^;|^$/} @tokens;
30 my $token = $rdr->next();
32 when(/^-?[0-9]+$/) { return Integer->new($token) }
34 my $str = substr $token, 1, -1;
37 return String->new($str)
39 when(/^nil$/) { return $nil }
40 when(/^true$/) { return $true }
41 when(/^false$/) { return $false }
42 default { return Symbol->new($token) }
47 my($rdr,$class,$start,$end) = @_;
48 $start = $start || '(';
51 my $token = $rdr->next();
53 if ($token ne $start) {
54 die "expected '$start'";
56 while (($token = $rdr->peek()) ne $end) {
57 if (! defined $token) {
58 die "expected '$end', got EOF";
60 push(@lst, read_form($rdr));
63 if ($class eq 'List') {
64 return List->new(\@lst);
65 } elsif ($class eq 'Vector') {
66 return Vector->new(\@lst);
69 for(my $i=0; $i<$#lst; $i+=2) {
71 $hsh->{$$str} = $lst[$i+1];
73 return HashMap->new($hsh);
79 my $token = $rdr->peek();
81 when("'") { $rdr->next(); List->new([Symbol->new('quote'),
83 when('`') { $rdr->next(); List->new([Symbol->new('quasiquote'),
85 when('~') { $rdr->next(); List->new([Symbol->new('unquote'),
87 when('~@') { $rdr->next(); List->new([Symbol->new('splice-unquote'),
89 when(')') { die "unexpected ')'" }
90 when('(') { return read_list($rdr, 'List') }
91 when(']') { die "unexpected ']'" }
92 when('[') { return read_list($rdr, 'Vector', '[', ']') }
93 when('}') { die "unexpected '}'" }
94 when('{') { return read_list($rdr, 'HashMap', '{', '}') }
95 default { return read_atom($rdr) }
101 my @tokens = tokenize($str);
102 #print join(" / ", @tokens) . "\n";
103 return read_form(Reader->new(\@tokens));
106 #print Dumper(read_str("123"));
107 #print Dumper(read_str("+"));
108 #print Dumper(read_str("\"abc\""));
109 #print Dumper(read_str("nil"));
110 #print Dumper(read_str("true"));
111 #print Dumper(read_str("false"));
112 #print Dumper(read_str("(+ 2 3)"));
113 #print Dumper(read_str("(foo 2 (3 4))"));