# Syntax propertizing an exception to Python comment rule

I want to write a mode for the Cadabra 2 computer algebra system, which has Python-like syntax, with an exception of having the hash character # as a wild card in expressions, in addition to being a comment starter like in regular Python. Consider the following code:

\dalembert{ A?? }::LaTeXForm(\Box A??).

{ \mu, \nu }::Indices(vector).
\dalembert{#}::Derivative.
\partial{#}::PartialDerivative.
{ A_{\mu} }::Depends(\partial{#}).

# QED Lagrangian
lagrangian:= (a/2) A_{\mu} \dalembert{ A_{\mu} }
+ (b/2) A_{\mu} \partial_{\nu}{\partial_{\mu}{ A_{\nu} }}
+ (1/2) m**2 A_{\mu} * A^{\mu};


Here, the QED Lagrangian line is a comment, but }::Derivative. is not. I want Emacs to interpret # as a comment delimiter only if it is not enclosed by curly or regular braces, and am struggling to implement that. The way I believe it should be done is with the syntax propertization function:

;;;###autoload
"Major mode for Cadabra 2 computer algebra system"
(setq-local syntax-propertize-function
(syntax-propertize-rules ("\$$?<!{\s*\$$#\$$?!\s*}\$$" (1 "< ")))))


I believe my regular expression is correct, it should match # if not preceded by { and not followed by } with any whitespace in between. Emacs still uses any hash as a comment starter however.

How do I implement this properly?

• Well, just trying to eval your function in my *scratch* buffer gives an (invalid-regexp) in your argument to syntax-propetize-rules.
– nega
May 14 at 18:42
• Looks like you've got a negative-lookbehind and a negative-lookahead, both of which aren't supported. Also it looks like you're trying to use \s to match whitespace. You want \s- instead. See emacswiki.org/emacs/RegularExpression for a good primer on emacs regexes.
– nega
May 14 at 19:23
• @nega I'm trying to make this work with the simplest example, I tried (rx (and "#" (not "}"))) which evaluates just fine and should catch the non-comments in the provided example, but still does not work when I load a file with the mode May 17 at 9:57

Based on your recent comment it is working, except for the fact that you're not overriding the comment character, you're adding properties to it. Effectively your (define-derived-mode ...) is saying "add this additional property to the comment character" and not "set the comment character to this property".

Additionally, you want to use 0 in your rule. The integer there is the matching sub-group of the regex in the rule, with 0 being "the whole match".

With your (slightly modified) sample text

# -*- mode: my-cadabra2 -*-

# bol comment
\dalembert{ A?? }::LaTeXForm(\Box A??). # inline comment

{ \mu, \nu }::Indices(vector).
\dalembert{#}::Derivative.
\partial{#}::PartialDerivative.
{ A_{\mu} }::Depends(\partial{#}).

# QED Lagrangian
lagrangian:= (a/2) A_{\mu} \dalembert{ A_{\mu} }
+ (b/2) A_{\mu} \partial_{\nu}{\partial_{\mu}{ A_{\nu} }}
+ (1/2) m**2 A_{\mu} * A^{\mu};


And this version of your defined of your define-derived-mode (note the modify-syntax-entry line)

;;;###autoload