[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