Commit 02ea4b5f authored by Juergen Nickelsen's avatar Juergen Nickelsen

handle read errors better

parent 8a46ffb3
......@@ -61,8 +61,16 @@ sub repl {
if ($interactive) {
print("> ");
}
my $expr = Read($fh);
last unless defined($expr);
my $expr = eval {
my $expr = Read($fh);
return $expr;
};
if ($@) {
say("Error: $@");
next;
} elsif (!defined($expr)) {
last;
}
if ($interactive) {
$value = iEval($expr);
......
......@@ -25,13 +25,21 @@ my $default_input = \*STDIN;
my $sepchars = quotemeta("();\n");
# after a read error, consume to end of line
sub read_error {
my ($in, @rest) = @_;
<$in>;
error(@rest);
}
sub Read {
my ($in) = @_;
$in //= $default_input;
if (stringp($in)) {
my $string = $in;
open(my $str_in, "<", \$string) or
error("read: cannot open string as filehandle: $!\n");
read_error($in,
"read: cannot open string as filehandle: $!\n");
$in = $str_in;
}
......@@ -42,25 +50,28 @@ sub Read {
my $list = read_list_elems($in);
return undef unless defined($list);
my $closer = next_token($in);
return error("syntax: list closed by $closer: ", $in)
return read_error($in, "syntax: list closed by $closer: ", $in)
unless $closer eq ')';
return $list;
} elsif ($t eq '\'') {
$t = Read($in);
return error("EOF in quote: %s", $in) unless defined($t);
return read_error($in, "EOF in quote: %s", $in)
unless defined($t);
return list(intern($Quote), $t);
} elsif ($t eq '#\'') {
$t = Read($in);
return error("EOF in quote %s", $in) unless defined($t);
return read_error($in, "EOF in quote %s", $in)
unless defined($t);
return list(intern($n_function), $t);
} elsif ($t eq '.') {
return error("found . where sexpr was expected: %s", $in);
return read_error($in,
"found . where sexpr was expected: %s", $in);
} elsif (symbolp($t)) {
return $t;
} elsif ($t =~ m{^\"}) {
return substr($t, 1);
} elsif ($t eq ')') {
return error("close paren unexpected");
return read_error($in, "close paren unexpected");
} else {
return $t;
}
......@@ -77,14 +88,16 @@ sub read_list_elems {
push_back_token($t);
return $list;
} elsif ($t eq '.') {
return error("syntax: . at start of list: %s",
return read_error($in, "syntax: . at start of list: %s",
$in)
unless $end;
my $sexpr = Read($in);
return undef unless defined($t);
$t = next_token($in);
return error("syntax: no ) after improper list: %s",
$in)
return
read_error($in,
"syntax: no ) after improper list: %s",
$in)
unless $t eq ')';
rplacd($end, $sexpr);
push_back_token($t);
......@@ -101,7 +114,7 @@ sub read_list_elems {
}
}
}
return error("EOF while reading list elements: %s", $in);
return read_error($in, "EOF while reading list elements: %s", $in);
}
......@@ -181,23 +194,24 @@ sub symbol_or_number_or_dot {
sub error_or_eof {
my ($in) = @_;
if (defined($!)) {
return error("read failure line $.: $!: %s", $in);
return read_error($in, "read failure line $.: $!: %s", $in);
}
return error("unexpected EOF line $.: %s", $in);
return read_error($in, "unexpected EOF line $.: %s", $in);
}
sub read_macro {
my ($in) = @_;
#debug("read macro");
my $c = next_nonwhite($in);
return error("unexpected EOF line $.: %s", $in) unless defined($c);
return read_error($in, "unexpected EOF line $.: %s", $in)
unless defined($c);
if ($c eq '\'') {
my $result = '#\'';
#debug("read macro returns %s", $result);
return $result;
# and possibly more
} else {
return error("unknown reader macro \"#$c\": %s", $in);
return read_error($in, "unknown reader macro \"#$c\": %s", $in);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment