Add short notation for lists: '(1 2) == (list 1 2)

This commit is contained in:
madmaurice 2021-04-03 18:09:20 +02:00
parent b316404b2b
commit c575115f92
2 changed files with 36 additions and 0 deletions

View file

@ -11,6 +11,7 @@ use constant {
STRING => 4, STRING => 4,
NUMBER => 5, NUMBER => 5,
KEYWORD => 6, KEYWORD => 6,
LIST => 7,
}; };
sub tokenize { sub tokenize {
@ -34,6 +35,10 @@ sub tokenize {
{ {
push @tokens, { type => RPAREN }; push @tokens, { type => RPAREN };
} }
elsif($str =~ s/^'\(//) # short notation for lists
{
push @tokens, { type => LIST }, { type => LPAREN };
}
elsif($str =~ s/^'([^\s()"]+)//) elsif($str =~ s/^'([^\s()"]+)//)
{ {
push @tokens, { push @tokens, {
@ -346,6 +351,10 @@ sub parser_expr {
{ {
return parser_call($ts); return parser_call($ts);
} }
elsif($tok->{type} == LIST)
{
return parser_list($ts);
}
elsif($tok->{type} == IDENT) elsif($tok->{type} == IDENT)
{ {
return sub { 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; my %macros;
sub parser_call { sub parser_call {

View file

@ -28,3 +28,9 @@
(= 5 (car lst))) (= 5 (car lst)))
(expect "cdr gives rest of list" (expect "cdr gives rest of list"
(equal (list 1 2) (cdr lst)))) (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 '())))