all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Stefan Monnier <monnier@iro.umontreal.ca>
To: Stephen Leake <stephen_leake@member.fsf.org>
Cc: emacs-devel@gnu.org
Subject: Re: smie-next-sexp vs associative operators
Date: Sun, 14 Oct 2012 21:47:14 -0400	[thread overview]
Message-ID: <jwvwqyszhcg.fsf-monnier+emacs@gnu.org> (raw)
In-Reply-To: <851uh0x59u.fsf@stephe-leake.org> (Stephen Leake's message of "Sun, 14 Oct 2012 14:44:29 -0400")

>>> 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



  parent reply	other threads:[~2012-10-15  1:47 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-14  9:16 smie-next-sexp vs associative operators Stephen Leake
2012-10-14 15:54 ` Stefan Monnier
2012-10-14 18:44   ` Stephen Leake
2012-10-14 21:48     ` Stephen Leake
2012-10-15  1:47     ` Stefan Monnier [this message]
2012-10-15 12:09       ` Stephen Leake
2012-10-20  9:15       ` Stephen Leake
2012-10-21 14:58         ` Stephen Leake
2012-10-23 17:37           ` Stefan Monnier
2012-10-23 22:43             ` Stephen Leake
2012-10-24 14:24               ` Stefan Monnier
2012-10-24 23:45                 ` Stephen Leake
2012-10-25  3:01                   ` Stefan Monnier
2012-10-25 19:17                     ` Stephen Leake
2012-10-25 21:01                       ` Stefan Monnier
2012-10-23 18:07         ` Stefan Monnier
2012-10-23 23:14           ` Stephen Leake
2012-10-24 14:44             ` Stefan Monnier
2012-10-25  0:22               ` Stephen Leake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=jwvwqyszhcg.fsf-monnier+emacs@gnu.org \
    --to=monnier@iro.umontreal.ca \
    --cc=emacs-devel@gnu.org \
    --cc=stephen_leake@member.fsf.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.