emacs-devel
[Top][All Lists]
Advanced

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

Re: SMIE help


From: Ivan Andrus
Subject: Re: SMIE help
Date: Fri, 29 Nov 2013 22:05:41 -0700

On Nov 29, 2013, at 2:28 PM, Stefan Monnier <address@hidden> wrote:

>> What I have works in many ways (though it could no doubt be
>> simplified).  My indentation is wildly off however in at least one
>> case, and I have no idea how to fix it.  The case of interest is the
>> first line inside of a function (in the example the line starting with
>> local).  Interestingly other lines in a function are fine.
> 
>> # example of well indented GAP code
>> FittingHeight := function (G)
>>    local  fittingLength, F;
>> 
>>    fittingLength := 0;
> 
> Here's the problem: with the grammar you have, the above is parsed as
> something like the following structure:
> 
>  (:= FittingHeight
>      (function
>       ((G) (local (, fittingLength F)))
>       (:= fittingLength 0)))
> 
> So the "local ..." is aligned with "(G)".
> 
> You can see that it's a parsing problem by hitting C-M-b from right
> after the first semi-colon of your example: it should jump to just
> before "local" but instead it jumps to just before "(G)", as if "(G)"
> was part of the first instruction.

I see.  That makes sense.

> SMIE is not very good with "positional rules", as is the case here where
> there is no clear keyword between "(G)" and the function's body.
> By "positional" I mean that "the *first* sexp-like thingy after
> `function' is special".
> 
> You can solve this problem at 2 levels:
> - the grammar level: you can't really fix it in gap-smie-grammar itself
>  because SMIE's class of grammars is too limited to understand this,
>  but you can change the lexer such that it treats the close-paren after
>  "(G" specially and returns another token.
> - the indent-rules level: you give up parsing the code correctly and
>  instead patch things up in gap-smie-rules by adding a rule for
>  (:after . ")") which checks if this is the closing parent of
>  a "function (...)".
> 
> Doing it in indent-rules will lead to more efficient code, usually, but
> may also force you to add more and more special cases (tho in this
> particular case, it might work OK).

I presume solving it in the lexer will also cause the C-M-b to work as expected 
in your example above.  I use sexp-based motion all the time, so I should 
probably take that route (at least eventually).  For the moment I think I'll 
try the indent-rules route since it does seem easier.

> In this particular case, you might like to try and patch things up in
> gap-smie-rules, along the lines of:
> 
>    (`(:after . ")")
>     (save-excursion
>       (up-list -1)
>       (when (equal "function" (car (smie-indent-backward-token)))
>        `(column . ,(+ gap-indent-step (smie-indent-virtual))))))

That works great!

> After that, you'll also want to change the smie-rules for (:before
> . "function"), probably, so as to treat "function (..)\n" as "hanging":
> 
>    (`(:before . "function")
>     (when (save-excursion
>            (forward-word 1)
>            (forward-sexp 1)
>            (smie-rule-hanging-p))
>       (smie-rule-parent)))
> 
> so that the body of "function" is not indented relative to "function"
> but relative to "FittingHeight :=".


Thank you very much for SMIE and for answering my questions.

-Ivan


reply via email to

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