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

handle read errors better

parent 8a46ffb3
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -61,8 +61,16 @@ sub repl {
                if ($interactive) {
                        print("> ");
                }
                my $expr = eval  {
                        my $expr = Read($fh);
                last unless defined($expr);
                        return $expr;
                };
                if ($@) {
                        say("Error: $@");
                        next;
                } elsif (!defined($expr)) {
                        last;
                }

                if ($interactive) {
                        $value = iEval($expr);
+28 −14
Original line number Diff line number Diff line
@@ -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,13 +88,15 @@ 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",
                        return
                            read_error($in,
                                       "syntax: no ) after improper list: %s",
                                       $in)
                            unless $t eq ')';
                        rplacd($end, $sexpr);
@@ -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);
        }
}