emacs-devel
[Top][All Lists]
Advanced

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

smie-next-sexp vs associative operators


From: Stephen Leake
Subject: smie-next-sexp vs associative operators
Date: Sun, 14 Oct 2012 05:16:31 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (windows-nt)

I'm having a problem with the way smie-next-sexp handles associative
operators.

The problem comes when I'm trying to indent a line in this statement;

         select
            accept BILLY;
            null;
         or
            accept SILLY;
            null;
         or
            accept LILLY do
               null;
            end LILLY;
         end select;

I'm indenting "accept LILLY". It should be indented relative to
"select". 

(I could put in a special case rule for "or", but I want to use the
general purpose rule, that uses smie-backward-sexp to find the statement
start, and indents relative to that.)

In this case, smie-backward-sexp is called with "or"; 

(smie-backward-sexp "or") 

However, this stops with point on "accept SILLY", not accept.

The reason is this code:

                   ((not (smie--associative-p toklevels))
                    (push toklevels levels))
                   ;; The new operator is associative.  Two cases:
                   ;; - it's really just an associative operator (like + or ;)
                   ;;   in which case we should have stopped right before.
                   ((and lastlevels
                         (smie--associative-p (car lastlevels)))
                    (throw 'return
                           (prog1 (list (or (car toklevels) t) (point) token)
                             (goto-char pos))))
                   ;; - it's an associative operator within a larger construct
                   ;;   (e.g. an "elsif"), so we should just ignore it and keep
                   ;;   looking for the closing element.
                   (t (setq levels lastlevels))))))))

Here `lastlevels' is "or" (the one we started with), and `toklevels' is
the next "or". "or" is associative; the right and left levels are the
same. So (smie--associative-p toklevels) and (smie--associative-p (car
lastlevels)) are both true.

That means the code decides it's like +, and stops, and the higher level
indents relative to "accept", which is wrong.

But this is exactly like the "elsif" case the comments are talking
about, so I think the code is broken. In general, there is no way for
SMIE to distinguish an "associative operator" from an "associative
keyword", because at this level everything is an operator.

So I'd like to add an option `smie-next-sexp-stop-on-associative', that
controls whether this stops or keeps going. That way, the user can
let-bind this appropriately, depending on the circumstances. For Ada,
I'll probably set it to nil always, but maybe not.

Somewhat apropos of this topic; I ended up leaving all of the math
operators out of my Ada SMIE grammar; I don't make indentation decisions
based on them, so they don't need to be in the grammar. So this "or" is
the only associative operator I have.

-- 
-- Stephe



reply via email to

[Prev in Thread] Current Thread [Next in Thread]