feat: hygieneInfo parser (aka this 2.0)
This commit is contained in:
parent
e826f5f42a
commit
c20a7bf305
9 changed files with 50 additions and 5 deletions
|
|
@ -271,10 +271,11 @@ abbrev CharLit := TSyntax charLitKind
|
|||
abbrev NameLit := TSyntax nameLitKind
|
||||
abbrev ScientificLit := TSyntax scientificLitKind
|
||||
abbrev NumLit := TSyntax numLitKind
|
||||
abbrev HygieneInfo := TSyntax hygieneInfoKind
|
||||
|
||||
end Syntax
|
||||
|
||||
export Syntax (Term Command Prec Prio Ident StrLit CharLit NameLit ScientificLit NumLit)
|
||||
export Syntax (Term Command Prec Prio Ident StrLit CharLit NameLit ScientificLit NumLit HygieneInfo)
|
||||
|
||||
namespace TSyntax
|
||||
|
||||
|
|
@ -921,6 +922,9 @@ def getChar (s : CharLit) : Char :=
|
|||
def getName (s : NameLit) : Name :=
|
||||
s.raw.isNameLit?.getD .anonymous
|
||||
|
||||
def getHygieneInfo (s : HygieneInfo) : Name :=
|
||||
s.raw[0].getId
|
||||
|
||||
namespace Compat
|
||||
|
||||
scoped instance : CoeTail (Array Syntax) (Syntax.TSepArray k sep) where
|
||||
|
|
@ -930,6 +934,11 @@ end Compat
|
|||
|
||||
end TSyntax
|
||||
|
||||
def HygieneInfo.mkIdent (s : HygieneInfo) (val : Name) (canonical := false) : Ident :=
|
||||
let src := s.raw[0]
|
||||
let id := { extractMacroScopes src.getId with name := val.eraseMacroScopes }.review
|
||||
⟨Syntax.ident (SourceInfo.fromRef src canonical) (toString val).toSubstring id []⟩
|
||||
|
||||
/-- Reflect a runtime datum back to surface syntax (best-effort). -/
|
||||
class Quote (α : Type) (k : SyntaxNodeKind := `term) where
|
||||
quote : α → TSyntax k
|
||||
|
|
|
|||
|
|
@ -3721,6 +3721,16 @@ abbrev nameLitKind : SyntaxNodeKind := `name
|
|||
/-- `fieldIdx` is the node kind of projection indices like the `2` in `x.2`. -/
|
||||
abbrev fieldIdxKind : SyntaxNodeKind := `fieldIdx
|
||||
|
||||
/--
|
||||
`hygieneInfo` is the node kind of the `hygieneInfo` parser, which is an
|
||||
"invisible token" which captures the hygiene information at the current point
|
||||
without parsing anything.
|
||||
|
||||
They can be used to generate identifiers (with `Lean.HygieneInfo.mkIdent`)
|
||||
as if they were introduced by the calling context, not the called macro.
|
||||
-/
|
||||
abbrev hygieneInfoKind : SyntaxNodeKind := `hygieneInfo
|
||||
|
||||
/--
|
||||
`interpolatedStrLitKind` is the node kind of interpolated string literal
|
||||
fragments like `"value = {` and `}"` in `s!"value = {x}"`.
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ open Lean.Parser.Command
|
|||
|
||||
private def declareSyntaxCatQuotParser (catName : Name) : CommandElabM Unit := do
|
||||
if let .str _ suffix := catName then
|
||||
let quotSymbol := "`(" ++ suffix ++ "|"
|
||||
let quotSymbol := "`(" ++ suffix ++ "| "
|
||||
let name := catName ++ `quot
|
||||
let cmd ← `(
|
||||
@[term_parser] def $(mkIdent name) : Lean.ParserDescr :=
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ builtin_initialize
|
|||
register_parser_alias (kind := charLitKind) "char" charLit
|
||||
register_parser_alias (kind := nameLitKind) "name" nameLit
|
||||
register_parser_alias (kind := scientificLitKind) "scientific" scientificLit
|
||||
register_parser_alias (kind := identKind) "ident" ident
|
||||
register_parser_alias (kind := identKind) ident
|
||||
register_parser_alias (kind := hygieneInfoKind) hygieneInfo
|
||||
register_parser_alias "colGt" checkColGt { stackSz? := some 0 }
|
||||
register_parser_alias "colGe" checkColGe { stackSz? := some 0 }
|
||||
register_parser_alias "colEq" checkColEq { stackSz? := some 0 }
|
||||
|
|
|
|||
|
|
@ -1072,6 +1072,20 @@ def identEq (id : Name) : Parser := {
|
|||
info := mkAtomicInfo "ident"
|
||||
}
|
||||
|
||||
def hygieneInfoFn : ParserFn := fun c s =>
|
||||
let input := c.input
|
||||
let pos := s.pos
|
||||
let str := mkEmptySubstringAt input pos
|
||||
let info := SourceInfo.original str pos str pos
|
||||
let ident := mkIdent info str .anonymous
|
||||
let stx := mkNode hygieneInfoKind #[ident]
|
||||
s.pushSyntax stx
|
||||
|
||||
def hygieneInfoNoAntiquot : Parser := {
|
||||
fn := hygieneInfoFn
|
||||
info := nodeInfo hygieneInfoKind epsilonInfo
|
||||
}
|
||||
|
||||
namespace ParserState
|
||||
|
||||
def keepTop (s : SyntaxStack) (startStackSize : Nat) : SyntaxStack :=
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ attribute [run_builtin_parser_attribute_hooks]
|
|||
@[run_builtin_parser_attribute_hooks] def rawIdent : Parser :=
|
||||
withAntiquot (mkAntiquot "ident" identKind) rawIdentNoAntiquot
|
||||
|
||||
@[run_builtin_parser_attribute_hooks] def hygieneInfo : Parser :=
|
||||
withAntiquot (mkAntiquot "hygieneInfo" hygieneInfoKind (anonymous := false)) hygieneInfoNoAntiquot
|
||||
|
||||
@[run_builtin_parser_attribute_hooks] def numLit : Parser :=
|
||||
withAntiquot (mkAntiquot "num" numLitKind) numLitNoAntiquot
|
||||
|
||||
|
|
|
|||
|
|
@ -489,6 +489,7 @@ def sepByNoAntiquot.formatter (p pSep : Formatter) : Formatter := do
|
|||
@[combinator_formatter skip] def skip.formatter : Formatter := pure ()
|
||||
|
||||
@[combinator_formatter pushNone] def pushNone.formatter : Formatter := goLeft
|
||||
@[combinator_formatter hygieneInfoNoAntiquot] def hygieneInfoNoAntiquot.formatter : Formatter := goLeft
|
||||
|
||||
@[combinator_formatter interpolatedStr]
|
||||
def interpolatedStr.formatter (p : Formatter) : Formatter := do
|
||||
|
|
|
|||
|
|
@ -492,6 +492,7 @@ def sepByNoAntiquot.parenthesizer (p pSep : Parenthesizer) : Parenthesizer := do
|
|||
@[combinator_parenthesizer skip] def skip.parenthesizer : Parenthesizer := pure ()
|
||||
|
||||
@[combinator_parenthesizer pushNone] def pushNone.parenthesizer : Parenthesizer := goLeft
|
||||
@[combinator_parenthesizer hygieneInfoNoAntiquot] def hygieneInfoNoAntiquot.parenthesizer : Parenthesizer := goLeft
|
||||
|
||||
@[combinator_parenthesizer interpolatedStr]
|
||||
def interpolatedStr.parenthesizer (p : Parenthesizer) : Parenthesizer := do
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
{"textDocument": {"uri": "file://1265.lean"},
|
||||
"position": {"line": 0, "character": 51}}
|
||||
{"items":
|
||||
[{"label": "getId", "kind": 3, "detail": "Lean.Ident → Lean.Name"},
|
||||
[{"label": "getHygieneInfo",
|
||||
"kind": 3,
|
||||
"detail": "Lean.HygieneInfo → Lean.Name"},
|
||||
{"label": "getId", "kind": 3, "detail": "Lean.Ident → Lean.Name"},
|
||||
{"label": "getName", "kind": 3, "detail": "Lean.NameLit → Lean.Name"},
|
||||
{"label": "expandInterpolatedStr",
|
||||
"kind": 3,
|
||||
|
|
@ -22,7 +25,10 @@
|
|||
{"textDocument": {"uri": "file://1265.lean"},
|
||||
"position": {"line": 2, "character": 53}}
|
||||
{"items":
|
||||
[{"label": "getId", "kind": 3, "detail": "Lean.Ident → Lean.Name"},
|
||||
[{"label": "getHygieneInfo",
|
||||
"kind": 3,
|
||||
"detail": "Lean.HygieneInfo → Lean.Name"},
|
||||
{"label": "getId", "kind": 3, "detail": "Lean.Ident → Lean.Name"},
|
||||
{"label": "getName", "kind": 3, "detail": "Lean.NameLit → Lean.Name"},
|
||||
{"label": "expandInterpolatedStr",
|
||||
"kind": 3,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue