emacs-devel
[Top][All Lists]
Advanced

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

Re: SMIE help


From: Stefan Monnier
Subject: Re: SMIE help
Date: Fri, 29 Nov 2013 16:28:28 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux)

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

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).
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))))))
    
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 :=".


        Stefan



reply via email to

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