[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Detecting mismatched parens better



Here is a proposal for how to solve the problem that has bothered
KMP, me and probably many other people, that mismatched parens
in files being compiled get bad error recovery.

First, suppose we establish the convention that lists that go "around"
a DEFUN (as EMACS would call it) should have a space after the open
paren.  For example,
( EVAL-WHEN (COMPILE)
(DEFUN ...))

Then it is never legitimate to have two nested lists that both start
in column 0 unless one of them has a space after the "(".

In the reader, each "(" would check its cursor position or look at a
variable holding the previous character read, to see if it was in
column 0.  Then it would peek at the next character to see if it is a
space.  If the "(" was in columnb 0 and not followed by a space,
then a special variable is bound to T; except that if it was already
T, an error is reported.

The error should specify a condition such as :MISSING-CLOSEPAREN
and if the handler continues then the reader should untyi the "("
and then pretend to read enough ")"'s to close all open levels of list
structure.  The compiler would handle the error and set a flag so a
warning would come out later.

This is a simple and clean solution that does the right thing.
BUT-- it requires two characters be untyi'd.  To avoid trying to do
that, make this change: before looking ahead for a space, if the
special variable is T, get the error right away.  If the variable is
NIL, bind it to NIL, then look ahead and set it to T if the next
character was not a space.  This avoids double-untyi'ing because the
char after the "(" is only checked if the "(" does not need to be untyi'd.
It makes the error check stricter: lists flagged with a space after the
paren are only allowed OUTSIDE ordinary defuns.

To facilitate the change-over, lists starting in column 0 with car
EVAL-WHEN and a few other common things could set a flag saying omit
this error check on that file.  A hairier scheme can recognize and
accept those symbols regardless of extra spaces.  Then no
change to source files is required.  But I think the change is
good for other things too.

A possible alternative to space is # as in
(#@EVAL-WHEN (EVAL)
(DEFUN ...))
assuming #@ is made a no-op.

As a separate error check, if the top level READ sees a list that does
not start in column 0, it should get an error, and if the error is
handled, it should skip sexps until it finds one that does start in
column 0.  This error would be :EXTRA-CLOSEPARENS.  Getting the error
sooner in this way would enable the compiler to associate the warning
with the right function.


Opinions?  I am sending this (as opposed to just implementing the
hairier scheme which required no change to source files) as an
experiment to see if a more co-operative attitude on my part will meet
with other people's willingness to co-operate.