Zulip Chat Archive
Stream: lean4
Topic: Stuck defining custom syntax
Yuri de Wit (Mar 10 2022 at 11:39):
I am trying to implement a custom syntax in Lean for the first time.
I am stuck on one problem: I would like to reuse rule_ctr
in two different contexts so I extracted out its definition from the rule_term
into its own syntax cat. However, when implementing rule_term
with macro_rules
, how do I delegate to the rule_ctr macro_rules?
Right now I get: expected 'numLit', 'rule_term' or numeral
Here is a #MWE (see HERE!
for where the error occurs):
-- Syntax
-- ------
-- rule ::=
-- | rule_ctr = rule_term
declare_syntax_cat rule
-- rule_ctr ::=
-- | (ctr term term ...) # a constructor
declare_syntax_cat rule_ctr
-- rule_term ::=
-- | λvar. term # a lambda
-- | (term term) # an application
-- | rule_ctr
-- | num # a machine int
-- | let var = term; term # a local definition
declare_syntax_cat rule_term
-- rule_ctr
--
syntax (name := rule_ctr) "(" ident rule_term* ")" : rule_ctr
macro_rules
| `(rule_ctr| ( $name $arg* )) => sorry
-- rule_term
--
syntax (name := rule_term_lam) "λ" ident "." rule_term : rule_term
syntax (name := rule_term_app) "(" rule_term rule_term ")" : rule_term
syntax (name := rule_term_ctr) rule_ctr : rule_term
syntax (name := rule_term_num) num : rule_term
syntax (name := rule_term_let) "let" ident "=" rule_term rule_term : rule_term
macro_rules
| `(rule_term| λ $var . $term:rule_term) => sorry
| `(rule_term| ( $name:rule_term $arg:rule_term )) => sorry
| `(rule_term| $ctr:rule_ctr ) => sorry -- <==== HERE!
| `(rule_term| $lit:num) => sorry
| `(rule_term| let $name:ident = $expr:rule_term $body:$rule_term ) => sorry
-- rule
--
syntax rule_ctr "=" rule_term : rule
macro_rules
| `(rule| ( $name $arg * ) = $term:rule_term) => sorry
-- translation from rules to terms
--
syntax "[rules|" rule* "]" : term
macro_rules
| `([rules| $rs:rule* ]) => sorry
Yuri de Wit (Mar 10 2022 at 11:45):
Humm, or maybe I dont need to explicitly do this in rule_term?
Sebastian Ullrich (Mar 10 2022 at 11:49):
There is some confusion between the syntax category rule_ctr
and the syntax
declaration of the same name. You should not use syntax categories if you don't plan to extend them with more than one syntax declaration, use a syntax abbreviation instead:
syntax rule_ctr := "(" ident rule_term* ")"
Sebastian Ullrich (Mar 10 2022 at 11:51):
You also do not usually need to name syntax
declarations
Yuri de Wit (Mar 10 2022 at 12:33):
Thanks for the feedback.
(1) "There is some confusion between the syntax category rule_ctr and the syntax declaration of the same name" - I see! Sorry, I missed that.
(2) I see that there is one difference betweensyntax rule_ctr := "(" ident rule_term* ")"
and syntax "(" ident rule_term* ")" : rule_ctr
in the elaborated term: the first uses Lean.ParserDescr.nodeWithAntiquot
and the second Lean.ParserDescr.node
. Did I just gained the ability to antiquote rule_ctr by using your suggestion?
(3) This seems to be a good rule of thumb: "should not use syntax categories if you don't plan to extend them with more than one syntax declaration".
(4) One consequence of this change to syntax rule_ctr := "(" ident rule_term* ")"
is that the compiler rejects:
macro_rules
| `(rule_ctr| ( $name:ident $args:rule_term* )) => sorry
with expected rule_ctr
.
Sebastian Ullrich (Mar 10 2022 at 14:00):
2) Syntax categories are also valid antiquotation kinds, so there's not really any change compared to a single-rule category
4) This is true, but is it even the case that you want the same expansion of rule_ctr
in both places in the grammar?
Yuri de Wit (Mar 10 2022 at 17:12):
Sebastian Ullrich said:
4) This is true, but is it even the case that you want the same expansion of
rule_ctr
in both places in the grammar?
I will have to think about this probably as I go through with this. But initially, I thought that the rule_ctr would always construct the same term and so I could avoid duplicating the macro_rules item. But it is not that important except understanding/learning.
Sebastian Ullrich (Mar 10 2022 at 17:21):
Since you already have a `[rules| ]
interpretation construct, I assume your syntax will expand as part of such macros, not by itself, in which case it shouldn't matter whether rule_ctr
is a category or not.
Yuri de Wit (Mar 10 2022 at 20:23):
Ok, making progress.
How do I create a quoted $name
? I.e. for a constructor (Add 1 2)
I would like to create a syntax transformer that generates Term.Ctr "Add" ...
:
| `(rule_ctr| ( $name:ident $args:rule_term* )) => `(Term.Ctr $name #[$args,*])
Yuri de Wit (Mar 10 2022 at 21:18):
This did it:
| `(rule_ctr| ( $name:ident $args:rule_term* )) => `(Term.Ctr $(Lean.quote name.getId.toString) #[$args,*])
Last updated: Dec 20 2023 at 11:08 UTC