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

I just realized I used "transitive" in this post when I should have used
"associative"; I don't know why. I apologize; I've got a head cold, and
between the direct effects and the drugs, I seem to be not thinking
quite straight ...

Stephen Leake <stephen_leake@member.fsf.org> writes:

> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>>> 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:
>
> if A then
>    B;
>
> elsif C then
>    D;
>
> elsif 
>   E then
>    F;
>
> else
>   G;
>
> end if;
>
> Here the internal keywords "then", "elsif" are not transitive; "else" is
> transitive. 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".
>
> In the analogous situation with "select or", (smie-backward-sexp "or")
> stops at the previous "or".
>
> Why should a select statement be different? I guess you'd say "because
> it is different" :). Still, I'd like one rule that handles both, and
> it's quite easy to achieve. The fewer special cases I have, the easier
> it is to maintain in the long run.
>
>>> But this is exactly like the "elsif" case the comments are talking
>>> about, so I think the code is broken.
>>
>> The comment is imprecise, it's meant for "if ... elsif ... end" where
>> the BNF said ("if" ... "elsif" ... "end")
>
> That structure matches this comment and code (as does the Ada "if"):
>
>            ;; If the new operator is not the last in the BNF rule,
>            ;; and is not associative, it's one of the inner operators
>            ;; (like the "in" in "let .. in .. end"), so keep looking.
>            ((not (smie--associative-p toklevels))
>             (push toklevels levels))
>
> 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. 
>
> 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.
>
> "select" statements "or" statements "else" statements "end" "select"
>
> Here "or" and "else" are transitive, because they have 'statements' on
> both sides. In fact have the same levels; both are (25 25) (illustrating
> your earlier point that the operator table is not invertible in general).
>
> Note that the "elsif then" pair also has the same levels on the left and
> right - they form a "transitive pair". In this case, smie-next-sexp will
> skip as many as appear.
>
> Which suggests another way to state my core complaint; since
> smie-next-sexp will skip an arbitrary number of "transitive pairs", it
> should also skip an arbitrary number of "transitive singles". Or at
> least, provide an option to do so.
>
>> rather than ("if" ... list-of-elseif ... "end") and then
>> list-of-elseif defined as (list-of-elseif "elsif" list-of-elseif).
>
> adding the missing nonterminals (and remembering that in C-like
> languages there are no "statements", only "expressions"):
>
> ("if" expressions "elseif" expressions "elseif" expressions "end")
>
> 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.
>
>> I should fix it, thank you for pointing it out.
>>
>> I.e. this rule is to avoid stopping at "elsif" when scanning from "if" to
>> "end" or from "end" to "if".  It will still stop when scanning from an
>> "elsif" and bumping into another "elsif".
>
> Hmm. Calling (smie-forward-sexp "if") on the above "if" statement gives
> the following toklevel sequence (obtained by setting a break in
> smie-next-sexp):
>
> ((184) 3)   if
> nil         A
> (3 25)      then
> nil         B
> (37 36)     ;
> (25 3)      elsif
> nil         C
> (3 25)      then
> nil         D
> (37 36)     ;
> (25 3)      elsif
> nil         E
> (3 25)      then
> nil         F
> (37 36)     ;
> (25 25)     else
> nil         G
> (37 36)     ;
> (25 127)    end
> (127 (174)) if
>
> Now I see; the checks for associative in smie-next-sexp handle the case
> where there is _one_ associative operator (here "else") in a statement.
>
> 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.
>
> Since "else" will be transitive in most languages, and appear only once,
> that would be a better keyword to use as an example in the current
> smie-next-sexp code comments.
>
> And I would still prefer having more control over this, to unify the
> behavior of smie-next-sexp on Ada "if" and "select", and between Ada and
> C-like "elsif". Similarly for "+"; if I had kept "+" in the grammar, I
> would not want smie-next-sexp to stop at it. That choice should be up to
> the smie user, not dictated by smie.
>
> As usual, this conversation has been educational - I learned more about
> what "transitive" means in SMIE :).
>
> --
> -- Stephe

-- 
-- Stephe



  reply	other threads:[~2012-10-14 21:48 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 [this message]
2012-10-15  1:47     ` Stefan Monnier
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=85txtwvi6t.fsf@member.fsf.org \
    --to=stephen_leake@member.fsf.org \
    --cc=emacs-devel@gnu.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.