emacs-devel
[Top][All Lists]
Advanced

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

Re: smie-next-sexp vs associative operators


From: Stefan Monnier
Subject: Re: smie-next-sexp vs associative operators
Date: Sun, 14 Oct 2012 21:47:14 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2.50 (gnu/linux)

>>> I'm indenting "accept LILLY".  It should be indented relative to
>>> "select".
>> That's odd.  I'd expect it to be indented relative to "or".
> The reason is that's how "if/then/else" works:

That's not a good reason: the indentation of an expression that follows
a keyword should almost always be relative to that keyword.

> if A then
>    B;
> elsif C then
>    D;
> elsif 
>   E then
>    F;
> else
>   G;
> end if;

I'm not completely sure how to interpret the above.
Is it an example of good indentation, or does it present a problem case?
In which way is it related to the select...do case?

> Here the internal keywords "then", "elsif" are not transitive; "else" is
> transitive.

That doesn't sound right.  "then" should not be associative,
but "elseif" should be.
More specifically, with point right after an "elsif", I'd expect C-M-b
to stop right after the previous "elsif".

> Here we are assuming "E" is a complex multi-line expression,
> so we can't use it as an indentation reference; we have to get back to
> "if" or "elsif". We call (smie-backward-sexp "then") to do that; it
> stops at "if".

I'm not sure of which "then" you're talking, but when point is just
before F, C-M-b should stop with point in front of E (and returning
the previous "elsif"'s data, relative to which it should be indented).
If it doesn't, your grammar is wrong.

> In the analogous situation with "select or", (smie-backward-sexp "or")
> stops at the previous "or".

The "or" in select should largely behave like the "elsif" above.

> However, what determines whether an operator is "transitive" in this
> SMIE sense is more subtle; it depends on what the surrounding
> non-terminals are. When the two non-terminals are the same, the operator
> is transitive. When they are different, it is not. 

No, an operator is associative simply if it has the same left and
right precedence.  What is more subtle is the choice of when to stop,
which depends on where we come from.

> For Ada, we have:
> "if" expression "then" statements "elsif" expression "then" statements
> "end" "if"

> "declare" declarations "begin" statements "end"

> These keywords are all non-transitive, because they have different
> non-terminals to the right and left; declarations, expressions, and
> statements are all distinct. "else" above is transitive because it has
> 'statements' on both sides.

No: the precedence depends on the preceding/next terminal.  I.e. the
left precedence of "then" will be equal to the right precedence of
"elsif" because of the above rule.

You might like to use rules like:

   (exp ("if" expthenexp "end")
        ("if" expthenexp "else" exp "end")
        ("if" expthenexp "elsif" expthenexp "end")
        ("if" expthenexp "elsif" expthenexp "end")
   (expthenexp (exp "then" exp))

So as to make it clear, that when jumping backward from an "elsif" (or
"else") you want to skip the "then" and stop at the previous "if" or
"elsif".
   
> Which suggests another way to state my core complaint; since
> smie-next-sexp will skip an arbitrary number of "transitive pairs",

That's annoying.

> it should also skip an arbitrary number of "transitive singles".  Or at
> least, provide an option to do so.

No, you got it backwards: you want indentation to walk back as little
as possible.  E.g. you don't want to walk all the way back to "if" if
you can indent relative to the closest "elsif".

> These "elseif" are transitive. But again, it is the surrounding
> non-terminals that determine this. In a language that distinguishes
> between expressions and statements, "elsif" will never be transitive,
> but "elsif expression then" will be.

What was the reason for separating expressions from instructions in
your grammar?  Maybe removing this distinction will help (tho it might
introduce other problems, of course).

Of course the grammar below will still "distinguish" expressions and
instructions while giving you an associative "elsif":

   (exp ("if" exptheninst "end")
        ("if" exptheninst "else" inst "end")
        ("if" exptheninst "elsif" exptheninst "end")
        ("if" exptheninst "elsif" exptheninst "end")
   (exptheninst (exp "then" inst))

> And with the equivalent sequence in a C-like language that doesn't
> have "then", it would stop at the second elsif. I don't see why Ada and
> C-like should be different in this.

Hence the "expthenexp" non-terminal.

> As usual, this conversation has been educational - I learned more about
> what "transitive" means in SMIE :).

Including the difference between transitive and associative?


        Stefan



reply via email to

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