Zulip Chat Archive
Stream: general
Topic: Reserved characters in macro rules?
Cayden Codel (Jul 03 2024 at 20:57):
I'm trying to write syntax/macro rules for a data format similar to JSON. In this format, unordered lists of data (i.e., multisets) are enclosed in double angle brackets (<< ... >>
) in the same way that lists are enclosed in square brackets ([ ... ]
). Writing a syntax for this is simple enough:
import Lean.Syntax
inductive JsonLike
| bool (b : Bool)
| multiset (elems : Array JsonLike)
-- | ... -- Other cases here
declare_syntax_cat jsonlike (behavior := symbol)
syntax "true" : jsonlike
syntax "false" : jsonlike
-- Other rules for lists, objects, identifiers
syntax "<<" jsonlike,*,? ">>" : jsonlike
syntax "jsonlike% " jsonlike : term
However, I'm having trouble writing a macro_rules
for the double angle brackets syntax:
macro_rules
| `(jsonlike% true) => `(JsonLike.bool Bool.true)
| `(jsonlike% false) => `(JsonLike.bool Bool.false)
| `(jsonlike% <<$[$xs],*>>) => `(JsonLike.multiset #[$[jsonlike% $xs],*])
Lean gives the error unexpected token '<'; expected jsonlike
. It seems like '<'
is a reserved character for macro rules. Is there any way to include them?
(These syntax/macro rules are largely copied from Lean.Data.Json.Elab
.)
Thomas Murrills (Jul 03 2024 at 21:03):
I think the issue is simply the (behavior := symbol)
on declare_syntax_cat
! :)
Cayden Codel (Jul 03 2024 at 21:05):
So it is - removing it fixed the issue.
What does (behavior := symbol)
do? I copied this over from Lean.Data.Json.Elab
without knowing what it does :sweat_smile:
Thomas Murrills (Jul 03 2024 at 21:16):
Hmm, the docstrings on Parser.LeadingIdentBehavior
constructors aren’t much help to me, since they don’t tell me when we’d want one or the other (besides something about avoiding creating a reserved symbol for each tactic). It is possible that you do want behavior := symbol
, and that this should actually be fixed another way! Someone who is more familiar with how this particular knob works will probably have a more reliable answer… :)
Cayden Codel (Jul 03 2024 at 21:20):
Well it looks like I have a patch for now. Thanks!
Notification Bot (Jul 03 2024 at 21:20):
Cayden Codel has marked this topic as resolved.
Thomas Murrills (Jul 03 2024 at 21:27):
This might be worth investigating further, though, because e.g. that true
’s might leak into generic parsing of true
; it should probably be a non reserved symbol (&"true"
) but that breaks the macro rules too. (Maybe behavior := symbol
helps do this without &
somehow?)
Thomas Murrills (Jul 03 2024 at 21:38):
Another option is to leave behavior := symbol
as is and write
syntax atomic("<<") jsonlike,* ">>" : jsonlike
I did this on a hunch that this would try to parse <<
“at the same level” as <
(i.e. sort of as though it was a single token) as parsing <
instead of <<
seemed to be the issue.
Thomas Murrills (Jul 03 2024 at 21:41):
This is probably safer, as it seems it won’t expose true
and false
to the world as jsonlike
s, but I’m still surprised at the behavior and interaction with behavior := symbol
—mainly because <
cannot be part of an ident, so I don’t understand why LeadingIdentBehavior
is even relevant.
Notification Bot (Jul 04 2024 at 09:30):
Kunil Lee has marked this topic as unresolved.
Last updated: May 02 2025 at 03:31 UTC