This is closely related to a previous question I asked here: SMIE Basic Identation and Block Example
However, it is sufficiently different (and already big enough) that I might as well ask it as a separate question. Those answers may still be useful for others anyways.
Anyways, given the (corrected) SMIE grammar and rules from the previous question:
(defvar smie-sample-grammar
(smie-prec2->grammar
(smie-bnf->prec2
`((insts (insts ";" insts) (inst))
(inst ("AttributeBegin" inst "AttributeEnd")))
'((assoc ";"))))
"Sample BNF grammar for `smie'.")
(defun smie-sample-rules (kind token)
"Perform indentation of KIND on TOKEN using the `smie' engine."
(princ (list kind token))
(pcase (list kind token)
(`(:elem basic) smie-sample-indent-offset)
(`(:elem arg) 0)
(`(:after "AttributeEnd") (smie-rule-parent))))
Our toy major-mode from the previous question now works. However, if we extend it slightly, e.g., by adding arguments to each instruction that can trail multiple lines, they are indented as expected in almost all cases:
test a
b
c;
test a;
test a
b;
AttributeBegin
test c
d;
AttributeBegin
test c
d;
AttributeEnd
test c
d; # <- Not lining up as expected.
test c
d;
AttributeEnd
Only the one instruction marked above is unexpectedly indented (and others that
trail directly after an "AttributeEnd" statement). I tried to use smie-edebug
to debug the indentation of that particular line, but for some reason SMIE
doesn't even refer to the rule-set in that case.
Interestingly, adding a semi-colon after "AttributeEnd" and before the next statement causes the indentation the line up-correctly.
Is there any particular reason that statement should behave that way and is there something that can be added to the configuration for this to behave as intended?
I've updated the gist if anyone wants to take a look at the code.