diff --git a/lib/Minilisp.pm b/lib/Minilisp.pm index 9c29af1..dfce759 100644 --- a/lib/Minilisp.pm +++ b/lib/Minilisp.pm @@ -11,6 +11,7 @@ use constant { STRING => 4, NUMBER => 5, KEYWORD => 6, + LIST => 7, }; sub tokenize { @@ -34,6 +35,10 @@ sub tokenize { { push @tokens, { type => RPAREN }; } + elsif($str =~ s/^'\(//) # short notation for lists + { + push @tokens, { type => LIST }, { type => LPAREN }; + } elsif($str =~ s/^'([^\s()"]+)//) { push @tokens, { @@ -346,6 +351,10 @@ sub parser_expr { { return parser_call($ts); } + elsif($tok->{type} == LIST) + { + return parser_list($ts); + } elsif($tok->{type} == IDENT) { return sub { @@ -373,6 +382,27 @@ sub parser_expr { } } +sub parser_list { + my $ts = shift; + + my $tok = shift @$ts; + die "Missing ( after ' for list" unless $tok->{type} == LPAREN; + + my @elements; + while ($ts->[0]->{type} != RPAREN) + { + push @elements, parser_expr($ts); + } + + shift @$ts; # Drop RPAREN + + return sub { + my $ctx = shift; + + return [ map { $_->($ctx) } @elements ]; + } +} + my %macros; sub parser_call { diff --git a/t/lists.t b/t/lists.t index 806115d..fb30cf5 100644 --- a/t/lists.t +++ b/t/lists.t @@ -28,3 +28,9 @@ (= 5 (car lst))) (expect "cdr gives rest of list" (equal (list 1 2) (cdr lst)))) + +(expect "short notation equals list created with list function" + (equal '(1 2) (list 1 2))) + +(expect "short notation can create empty lists" + (zerop (length '())))