Zulip Chat Archive
Stream: lean4
Topic: Matchin on syntax with group
Joachim Breitner (Aug 03 2023 at 16:04):
I have
syntax (name := find_theorems)
withPosition("#find_theorems" (colGt (strLit <|> ident <|> term:max))+) : command
and it works, and I want to extend it to
syntax (name := find_theorems)
withPosition("#find_theorems" (colGt (strLit <|> ident <|> ("⊢ " term:max) <|> term:max))+) : command
This is accepted, but if I then use
#find_theorems ⊢ (tsum _ = _) (_ * _ ^ _)
I get
elaboration function for 'group' has not been implemented
[Error pretty printing syntax: unknown constant 'group'. Falling back to raw printer.]
(group "⊢" (Term.paren "(" («term_=_» (Term.app `tsum [(Term.hole "_")]) "=" (Term.hole "_")) ")"))
I am parsing the argument list like this so far:
for s in stx[1].getArgs do
match s with
| `($ss:str) => do
let str := Lean.TSyntax.getString ss
name_pats := name_pats.push str
| `($i:ident) => do
let n := Lean.TSyntax.getId i
unless (← getEnv).contains n do
throwErrorAt i "Name {n} not in scope"
idents := idents.push n
| `(group "⊢" $st:term) => do
let t ← Lean.Elab.Term.elabTerm st none
terms := terms.push (true, t)
| _ => do
let t ← Lean.Elab.Term.elabTerm s none
terms := terms.push (false, t)
where the second-to-last clause is new. I found in the docs of <|> that it adds a group node if necessary, but I am unsure how to match it, or if I am approaching this the wrong way.
Joachim Breitner (Aug 03 2023 at 17:04):
I think I figured it out.
Chris Bailey (Jun 14 2025 at 10:04):
I'm running into this "match on group" thing now, was there a good solution? I would have thought an extra set of parens in the match would do the trick, but no cigar.
Eric Wieser (Jun 15 2025 at 10:57):
Do you have a mwe? I think Joachim's is too old to reflect the current state of Lean.
Chris Bailey (Jun 15 2025 at 18:42):
Sure, in this example I want to process a list of tuples/products. The repeated part is grouped in the syntax part as tuples:(..),*. When I go to try and match on the elements of the TSepArray, they present with this additional group wrapper that I can't seem to figure out how to match on, as evidenced by neither of the match arms hitting.
import Lean
open Lean Elab Command
elab "#goMany" "[" tuples:("(" num "," str ")"),* "]" : command => do
for tuple in tuples.getElems do
match tuple with
| `(($a, $b)) => logInfo s!"OK 0"; return
| `((($a, $b))) => logInfo s!"OK 1"; return
| stx => throwError s!"failed to match: {stx}"
-- failed to match: (group "(" (num "0") "," (str "\"x\"") ")")
#goMany [
(0, "x"),
(1, "y")
]
Aaron Liu (Jun 15 2025 at 18:52):
You can also always just access the children directly
import Lean
open Lean Elab Command
elab "#goMany" "[" tuples:("(" num "," str ")"),* "]" : command => do
for tuple in tuples.getElems do
logInfo tuple.raw[1]
logInfo tuple.raw[3]
#goMany [
(0, "x"),
(1, "y")
]
Sebastian Ullrich (Jun 16 2025 at 07:59):
Note that the default category of quotations is term, which is definitely incorrect here. So you need to specify the quotation parser, at which point you need to name it.
syntax pair := "(" num "," str ")"
elab "#goMany" "[" tuples:pair,* "]" : command => do
for tuple in tuples.getElems do
match tuple with
| `(pair| ($a, $b)) => logInfo s!"OK 0"; return
| stx => throwError s!"failed to match: {stx}"
Chris Bailey (Jun 17 2025 at 05:17):
Thanks, I didn't know you could now shortcut the declare_syntax_cat foo with just syntax foo either.
Last updated: Dec 20 2025 at 21:32 UTC