import Lean open Lean open Lean.Elab def runCore (input : String) (failIff : Bool := true) : CoreM Unit := do let env ← getEnv; let opts ← getOptions; let (env, messages) ← process input env opts; messages.toList.forM fun msg => do IO.println (← msg.toString) if failIff && messages.hasErrors then throwError "errors have been found"; if !failIff && !messages.hasErrors then throwError "there are no errors"; pure () open Lean.Parser @[term_parser] def tst := leading_parser "(|" >> termParser >> Parser.optional (symbol ", " >> termParser) >> "|)" def tst2 : Parser := symbol "(||" >> termParser >> symbol "||)" @[term_parser] def boo : ParserDescr := ParserDescr.node `boo 10 (ParserDescr.binary `andthen (ParserDescr.symbol "[|") (ParserDescr.binary `andthen (ParserDescr.cat `term 0) (ParserDescr.symbol "|]"))) @[term_parser] def boo2 : ParserDescr := ParserDescr.node `boo2 10 (ParserDescr.parser `tst2) open Lean.Elab.Term @[term_elab tst] def elabTst : TermElab := adaptExpander $ fun stx => match stx with | `((| $e |)) => pure e | _ => throwUnsupportedSyntax @[term_elab boo] def elabBoo : TermElab := fun stx expected? => elabTerm (stx.getArg 1) expected? @[term_elab boo2] def elabBool2 : TermElab := adaptExpander $ fun stx => match stx with | `((|| $e ||)) => `($e + 1) | _ => throwUnsupportedSyntax /-- info: id : Nat → Nat -/ #guard_msgs in #eval runCore "#check [| @id.{1} Nat |]" /-- info: id 1 : Nat -/ #guard_msgs in #eval runCore "#check (| id 1 |)" /-- info: id 1 + 1 : Nat -/ #guard_msgs in #eval runCore "#check (|| id 1 ||)" -- #eval run "#check (| id 1, id 1 |)" -- it will fail @[term_elab tst] def elabTst2 : TermElab := adaptExpander $ fun stx => match stx with | `((| $e1, $e2 |)) => `(($e1, $e2)) | _ => throwUnsupportedSyntax -- Now both work /-- info: id 1 : Nat -/ #guard_msgs in #eval runCore "#check (| id 1 |)" /-- info: (id 1, id 2) : Nat × Nat -/ #guard_msgs in #eval runCore "#check (| id 1, id 2 |)" declare_syntax_cat foo syntax "⟨|" term "|⟩" : foo syntax term : foo syntax term ">>>" term : foo syntax (name := tst3) "FOO " foo : term macro_rules | `(FOO ⟨| $t |⟩) => `($t+1) | `(FOO $t:term) => `($t) /-- info: id 1 + 1 : Nat -/ #guard_msgs in #check FOO ⟨| id 1 |⟩ /-- info: 1 : Nat -/ #guard_msgs in #check FOO 1 /-- info: 1 >>> 2 : Nat -/ #guard_msgs in #check FOO 1 >>> 2