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,
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 {

View file

@ -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 '())))