[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
SMIE help
From: |
Ivan Andrus |
Subject: |
SMIE help |
Date: |
Thu, 28 Nov 2013 00:00:44 -0700 |
I'm trying to write a SMIE grammar for the GAP language [1], since it will be
much better than what I have at the moment. GAP is a fairly simple language,
similar to ruby (and maybe Pascal). Because of that I foolishly thought I
would be able to figure it out. I started with the example grammar and stole
some from ruby-mode.
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.
Feel free to point me at other documentation or discussions that may be of use.
Any other tips would be appreciated as well.
Thanks,
Ivan
[1] http://www.gap-system.org/Manuals/doc/ref/chap4.html
;; One variation of the lisp code that I have used
(defvar gap-indent-step 4)
;; This sort of works
(defconst gap-smie-grammar
(smie-prec2->grammar
(smie-bnf->prec2
'((id)
(inst (exp) ;not technically, but probably makes sense
;; (exp ":=" exp)
(id ":=" exp)
("function" insts "end")
("repeat" insts "until" exp)
("while" exp "do" insts "od")
("for" id "in" exp "do" insts "od")
("if" if-body "fi")
("return" exp)
("local" exps)
)
(insts (insts ";" insts) (inst))
(exp ("(" exps ")")
("[" exps "]")
("{" exps "}")
("not" exp)
(exp ".." exp)
(exp "and" exp)
(exp "or" exp)
(exp "<" exp)
(exp "<=" exp)
(exp "=" exp)
(exp ">=" exp)
(exp ">" exp)
(exp "<>" exp)
;; (exp "in" exp)
(exp "+" exp)
(exp "-" exp)
(exp "*" exp)
(exp "/" exp)
(exp "mod" exp)
(exp "^" exp)
)
(exps (exps "," exps) (exp))
(itheni (insts) (exp "then" insts))
(ielsei (itheni) (itheni "else" insts))
(if-body (ielsei) (if-body "elif" if-body)))
'((assoc ";"))
'((assoc ","))
'((assoc "elif"))
'((assoc "not")
(assoc "..")
(assoc "and" "or")
(assoc "<" "<=" "=" ">=" ">" "<>" ;; "in"
)
(assoc "+" "-")
(assoc "*" "/" "mod")
(assoc "^")))))
(defun gap-smie-rules (kind token)
(pcase (cons kind token)
(`(:list-intro . "function")
gap-indent-step)
(`(:after . "function")
gap-indent-step)
(`(:after . ,(or `"if" `"else" `"then" `"elif" `"do" `"repeat" `"while"))
gap-indent-step)
(`(:before . ";")
(cond
((smie-rule-parent-p "function" "repeat" "while" "for"
"if" "then" "elif" "else" "when")
(smie-rule-parent gap-indent-step))
))
(`(:after . ,(or "=" ":=" "+" "-" "*" "/" "^"
">" "<" ">=" "<=" "<>" "and" "or"))
(if (smie-rule-parent-p ";" nil) gap-indent-step))
))
(smie-setup gap-smie-grammar #'gap-smie-rules)
# example of well indented GAP code
FittingHeight := function (G)
local fittingLength, F;
fittingLength := 0;
F := FittingSubgroup( G );
while Order(F) > 1 do
G := G / F;
F := FittingSubgroup( G );
fittingLength := fittingLength+1;
od;
if Order(G) > 1 then
return fail;
fi;
return fittingLength;
end;
- SMIE help,
Ivan Andrus <=