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 jsonlikes, 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