-;; Use '__operators__' in Octave REPL to get a full list.
-(defconst octave-operator-table
- '((assoc ";" "\n") (assoc ",") ; The doc claims they have equal precedence!?
- (right "=" "+=" "-=" "*=" "/=")
- (assoc "&&") (assoc "||") ; The doc claims they have equal precedence!?
- (assoc "&") (assoc "|") ; The doc claims they have equal precedence!?
- (nonassoc "<" "<=" "==" ">=" ">" "!=" "~=")
- (nonassoc ":") ;No idea what this is.
- (assoc "+" "-")
- (assoc "*" "/" "\\" ".\\" ".*" "./")
- (nonassoc "'" ".'")
- (nonassoc "++" "--" "!" "~") ;And unary "+" and "-".
- (right "^" "**" ".^" ".**")
- ;; It's not really an operator, but for indentation purposes it
- ;; could be convenient to treat it as one.
- (assoc "...")))
-
-(defconst octave-smie-bnf-table
- '((atom)
- ;; We can't distinguish the first element in a sequence with
- ;; precedence grammars, so we can't distinguish the condition
- ;; if the `if' from the subsequent body, for example.
- ;; This has to be done later in the indentation rules.
- (exp (exp "\n" exp)
- ;; We need to mention at least one of the operators in this part
- ;; of the grammar: if the BNF and the operator table have
- ;; no overlap, SMIE can't know how they relate.
- (exp ";" exp)
- ("try" exp "catch" exp "end_try_catch")
- ("try" exp "catch" exp "end")
- ("unwind_protect" exp
- "unwind_protect_cleanup" exp "end_unwind_protect")
- ("unwind_protect" exp "unwind_protect_cleanup" exp "end")
- ("for" exp "endfor")
- ("for" exp "end")
- ("parfor" exp "endparfor")
- ("parfor" exp "end")
- ("do" exp "until" atom)
- ("while" exp "endwhile")
- ("while" exp "end")
- ("if" exp "endif")
- ("if" exp "else" exp "endif")
- ("if" exp "elseif" exp "else" exp "endif")
- ("if" exp "elseif" exp "elseif" exp "else" exp "endif")
- ("if" exp "elseif" exp "elseif" exp "else" exp "end")
- ("switch" exp "case" exp "endswitch")
- ("switch" exp "case" exp "otherwise" exp "endswitch")
- ("switch" exp "case" exp "case" exp "otherwise" exp "endswitch")
- ("switch" exp "case" exp "case" exp "otherwise" exp "end")
- ("function" exp "endfunction")
- ("function" exp "end")
- ("enumeration" exp "endenumeration")
- ("enumeration" exp "end")
- ("events" exp "endevents")
- ("events" exp "end")
- ("methods" exp "endmethods")
- ("methods" exp "end")
- ("properties" exp "endproperties")
- ("properties" exp "end")
- ("classdef" exp "endclassdef")
- ("classdef" exp "end"))
- ;; (fundesc (atom "=" atom))
- ))
+(let-when-compile
+ ((operator-table
+ ;; Use '__operators__' in Octave REPL to get a full list?
+ '((assoc ";" "\n") (assoc ",") ;The doc says they have equal precedence!?
+ (right "=" "+=" "-=" "*=" "/=")
+ (assoc "&&") (assoc "||") ; The doc claims they have equal precedence!?
+ (assoc "&") (assoc "|") ; The doc claims they have equal precedence!?
+ (nonassoc "<" "<=" "==" ">=" ">" "!=" "~=")
+ (nonassoc ":") ;No idea what this is.
+ (assoc "+" "-")
+ (assoc "*" "/" "\\" ".\\" ".*" "./")
+ (nonassoc "'" ".'")
+ (nonassoc "++" "--" "!" "~") ;And unary "+" and "-".
+ (right "^" "**" ".^" ".**")
+ ;; It's not really an operator, but for indentation purposes it
+ ;; could be convenient to treat it as one.
+ (assoc "...")))
+
+ (matchedrules
+ ;; We can't distinguish the first element in a sequence with
+ ;; precedence grammars, so we can't distinguish the condition
+ ;; of the `if' from the subsequent body, for example.
+ ;; This has to be done later in the indentation rules.
+ '(("try" exp "catch" exp "end_try_catch")
+ ("unwind_protect" exp
+ "unwind_protect_cleanup" exp "end_unwind_protect")
+ ("for" exp "endfor")
+ ("parfor" exp "endparfor")
+ ("while" exp "endwhile")
+ ("if" exp "endif")
+ ("if" exp "else" exp "endif")
+ ("if" exp "elseif" exp "else" exp "endif")
+ ("if" exp "elseif" exp "elseif" exp "else" exp "endif")
+ ("switch" exp "case" exp "endswitch")
+ ("switch" exp "case" exp "otherwise" exp "endswitch")
+ ("switch" exp "case" exp "case" exp "otherwise" exp "endswitch")
+ ("function" exp "endfunction")
+ ("enumeration" exp "endenumeration")
+ ("events" exp "endevents")
+ ("methods" exp "endmethods")
+ ("properties" exp "endproperties")
+ ("classdef" exp "endclassdef")
+ ))
+
+ (bnf-table
+ `((atom)
+ ;; FIXME: We don't parse these declarations correctly since
+ ;; SMIE *really* likes to parse "a b = 2 c" as "(a b) = (2 c)".
+ ;; IOW to do it right, we'd need to change octave-smie-*ward-token
+ ;; so that the spaces between vars in var-decls are lexed as
+ ;; something like ",".
+ ;; Doesn't seem worth the trouble/slowdown for now.
+ ;; We could hack smie-rules so as to work around the bad parse,
+ ;; but even that doesn't seem worth the trouble.
+ (var-decls (atom "=" atom)) ;; (var-decls "," var-decls)
+ (single-exp (atom "=" atom))
+ (exp (exp "\n" exp)
+ ;; We need to mention at least one of the operators in this part
+ ;; of the grammar: if the BNF and the operator table have
+ ;; no overlap, SMIE can't know how they relate.
+ (exp ";" exp)
+ ("do" exp "until" single-exp)
+ ,@matchedrules
+ ;; For every rule that ends in "endfoo", add a corresponding
+ ;; rule which uses "end" instead.
+ ,@(mapcar (lambda (rule) (nconc (butlast rule) '("end")))
+ matchedrules)
+ ("global" var-decls) ("persistent" var-decls)
+ ;; These aren't super-important, but having them here
+ ;; makes it easier to extract all keywords.
+ ("break") ("continue") ("return")
+ ;; The following rules do not correspond to valid code AFAIK,
+ ;; but they lead to a grammar that degrades more gracefully
+ ;; on incomplete/incorrect code. It also helps us in
+ ;; computing octave--block-offset-keywords.
+ ("try" exp "end") ("unwind_protect" exp "end")
+ )
+ ;; (fundesc (atom "=" atom))
+ )))