Skip to content

Commit 04ce069

Browse files
committed
refactor: use Verso's runParserCategory function for string parsing
This is a step towards removing `parserInputString`. Upstream `runParserCategory` always starts at `pos := 0` Another option would be to update the upstream function to take this into account, but the idea is that the function will evolve to take a string literal so it should be able to compute the position by itself. I made the types different (the Verso one is monadic) as to help avoid confusion, and increase programming ergonomics. Note that we don't change the parts `in VersoManual.Docstring` as these are code strings that come from the `MD4Lean` and they don't have an attached location.
1 parent 1e49d3d commit 04ce069

5 files changed

Lines changed: 45 additions & 50 deletions

File tree

src/verso-blog/VersoBlog.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ def leanInline : RoleExpanderOf LeanInlineConfig
627627
Elab.Term.withLevelNames us
628628
else id
629629

630-
match Parser.runParserCategory env `term altStr (← getFileName) with
630+
match (← SyntaxUtils.runParserCategory `term altStr) with
631631
| .error e => throwErrorAt str e
632632
| .ok stx => withOptions (fun _ => opts) <| runWithOpenDecls scopes <| runWithVariables scopes fun _ => do
633633
let (newMsgs, type, tree) ← do
@@ -637,7 +637,7 @@ def leanInline : RoleExpanderOf LeanInlineConfig
637637
let (tree', t) ← do
638638

639639
let expectedType ← config.type.mapM fun (s : StrLit) => do
640-
match Parser.runParserCategory env `term s.getString (← getFileName) with
640+
match (← SyntaxUtils.runParserCategory `term s.getString) with
641641
| .error e => throwErrorAt str e
642642
| .ok stx => withEnableInfoTree false do
643643
let t ← leveller <| Elab.Term.elabType stx

src/verso-manual/VersoManual/InlineLean.lean

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ open Verso ArgParse Doc Elab Genre.Manual Html Code Highlighted.WebAssets Expect
2828
open Lean Elab
2929
open SubVerso.Highlighting
3030

31-
open Verso.SyntaxUtils (parserInputString runParserCategory' SyntaxError)
31+
open Verso.SyntaxUtils (parserInputString SyntaxError)
3232

3333
open Lean.Doc.Syntax
3434
open Lean.Elab.Tactic.GuardMsgs
@@ -356,7 +356,7 @@ def leanTerm : CodeBlockExpanderOf LeanInlineConfig
356356
Elab.Term.withLevelNames us
357357
else id
358358

359-
match Parser.runParserCategory (← getEnv) `term altStr (← getFileName) with
359+
match (← SyntaxUtils.runParserCategory `term altStr) with
360360
| .error e => throwErrorAt str e
361361
| .ok stx =>
362362
let (newMsgs, tree) ← do
@@ -366,7 +366,7 @@ def leanTerm : CodeBlockExpanderOf LeanInlineConfig
366366

367367
let tree' ← runWithOpenDecls <| runWithVariables fun _vars => do
368368
let expectedType ← config.type.mapM fun (s : StrLit) => do
369-
match Parser.runParserCategory (← getEnv) `term s.getString (← getFileName) with
369+
match (← SyntaxUtils.runParserCategory `term s.getString) with
370370
| .error e => throwErrorAt stx e
371371
| .ok stx => withEnableInfoTree false do
372372
let t ← leveller <| Elab.Term.elabType stx
@@ -433,7 +433,7 @@ def leanInline : RoleExpanderOf LeanInlineConfig
433433
Elab.Term.withLevelNames us
434434
else id
435435

436-
match Parser.runParserCategory (← getEnv) `term altStr (← getFileName) with
436+
match (← SyntaxUtils.runParserCategory `term altStr) with
437437
| .error e => throwErrorAt term e
438438
| .ok stx =>
439439

@@ -444,7 +444,7 @@ def leanInline : RoleExpanderOf LeanInlineConfig
444444
let (tree', t) ← runWithOpenDecls <| runWithVariables fun _ => do
445445

446446
let expectedType ← config.type.mapM fun (s : StrLit) => do
447-
match Parser.runParserCategory (← getEnv) `term s.getString (← getFileName) with
447+
match (← SyntaxUtils.runParserCategory `term s.getString) with
448448
| .error e => throwErrorAt term e
449449
| .ok stx => withEnableInfoTree false do
450450
let t ← leveller <| Elab.Term.elabType stx
@@ -516,7 +516,7 @@ def inst : RoleExpanderOf LeanBlockConfig
516516
| throwErrorAt arg "Expected code literal with the example name"
517517
let altStr ← parserInputString term
518518

519-
match Parser.runParserCategory (← getEnv) `term altStr (← getFileName) with
519+
match (← SyntaxUtils.runParserCategory `term altStr) with
520520
| .error e => throwErrorAt term e
521521
| .ok stx =>
522522
let (newMsgs, tree) ← do

src/verso-manual/VersoManual/InlineLean/Signature.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ open SubVerso.Highlighting
1515
open Verso Genre Manual ArgParse Doc Elab
1616
open Verso Output Html
1717
open Verso Code Highlighted WebAssets
18-
open Verso.SyntaxUtils
18+
open Verso.SyntaxUtils (parserInputString)
1919
open Lean Elab
2020

2121
namespace Verso.Genre.Manual.InlineLean
@@ -63,7 +63,7 @@ def signature : CodeBlockExpanderOf SignatureConfig
6363
let col? := (← getRef).getPos? |>.map (← getFileMap).utf8PosToLspPos |>.map (·.character)
6464

6565

66-
match Parser.runParserCategory (← getEnv) `signature_spec altStr (← getFileName) with
66+
match (← SyntaxUtils.runParserCategory `signature_spec altStr) with
6767
| .error e => throwError e
6868
| .ok stx =>
6969
let `(signature_spec|$[$kw]? $name:declId $sig:declSig) := stx

src/verso-manual/VersoManual/InlineLean/SyntaxError.lean

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ open SubVerso.Highlighting
1616
open Verso Genre Manual ArgParse Doc Elab
1717
open Verso Output Html
1818
open Verso Code Highlighted WebAssets
19-
open Verso.SyntaxUtils
19+
open Verso.SyntaxUtils (SyntaxError)
2020
open Lean Elab
2121

2222
namespace Verso.Genre.Manual.InlineLean
@@ -140,7 +140,8 @@ def syntaxError : CodeBlockExpanderOf SyntaxErrorConfig
140140
(detail? := some "Syntax error")
141141

142142
let s := str.getString
143-
match runParserCategory' (← getEnv) (← getOptions) config.category s with
143+
let errorFn := SyntaxUtils.runParserCategory.toSyntaxErrors
144+
match (← SyntaxUtils.runParserCategoryGen (errorFn := errorFn) config.category s) with
144145
| .ok stx =>
145146
throwErrorAt str m!"Expected a syntax error for category {config.category}, but got {indentD stx}"
146147
| .error es =>

src/verso/Verso/SyntaxUtils.lean

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ deriving ToJson, FromJson, BEq, Repr, Quote
169169

170170

171171
-- Based on mkErrorMessage used in Lean upstream - keep them in synch for best UX
172-
open Lean.Parser in
173172
private partial def mkSyntaxError (c : InputContext) (pos : String.Pos.Raw) (stk : SyntaxStack) (e : Parser.Error) : SyntaxError := Id.run do
174173
let mut pos := pos
175174
let mut endPos? := none
@@ -219,49 +218,44 @@ public defmethod ParserFn.parseString [Monad m] [MonadError m] [MonadEnv m] (p :
219218
else
220219
pure stk[0]
221220

221+
-- Default from upstream
222+
public def runParserCategory.toErrorMsg (ictx : InputContext) (s : ParserState) :=
223+
s.toErrorMsg ictx
222224

223-
open Lean.Parser in
224-
/--
225-
Runs a parser category, returning any errors encountered as a list of position-string pairs.
225+
-- Unused
226+
public def runParserCategory.toErrorMsgList (ictx : InputContext) (s : ParserState) : List (Position × String) := Id.run do
227+
let mut errs := []
228+
for (pos, _stk, err) in s.allErrors do
229+
let pos := ictx.fileMap.toPosition pos
230+
errs := (pos, toString err) :: errs
231+
errs.reverse
232+
233+
-- Used in Manual's syntaxError block
234+
public def runParserCategory.toSyntaxErrors (ictx : InputContext) (s : ParserState) : Array SyntaxError :=
235+
s.allErrors.map fun (pos, stk, e) => (mkSyntaxError ictx pos stk e)
236+
237+
/-- Runs a parser category, returning any errors encountered. It takes
238+
and optional `fileName` as callers in VersoManual/Docstring like to
239+
override it.
226240
-/
227-
public def runParserCategory
228-
(env : Environment) (opts : Lean.Options) (catName : Name)
229-
(input : String) (fileName : String := "<example>") :
230-
Except (List (Position × String)) Syntax :=
241+
public def runParserCategoryGen [Monad m] [MonadEnv m] [MonadLog m] [MonadOptions m]
242+
(errorFn : InputContext → ParserState → ε)
243+
(catName : Name) (input : String) (fileName : Option String := none) : m (Except ε Syntax) := do
244+
let fileName ← fileName.getDM getFileName
245+
let env ← getEnv
246+
let options ← getOptions
231247
let p := andthenFn whitespace (categoryParserFnImpl catName)
232248
let ictx := mkInputContext input fileName
233-
let s := p.run ictx { env, options := opts } (getTokenTable env) (mkParserState input)
234-
if !s.allErrors.isEmpty then
235-
Except.error (toErrorMsg ictx s)
249+
let s := p.run ictx { env, options } (getTokenTable env) (mkParserState input)
250+
pure $ if !s.allErrors.isEmpty then
251+
Except.error (errorFn ictx s)
236252
else if ictx.atEnd s.pos then
237253
Except.ok s.stxStack.back
238254
else
239-
Except.error (toErrorMsg ictx (s.mkError "end of input"))
240-
where
241-
toErrorMsg (ctx : InputContext) (s : ParserState) : List (Position × String) := Id.run do
242-
let mut errs := []
243-
for (pos, _stk, err) in s.allErrors do
244-
let pos := ctx.fileMap.toPosition pos
245-
errs := (pos, toString err) :: errs
246-
errs.reverse
247-
248-
open Lean.Parser in
249-
/--
250-
Runs a parser category, returning any errors encountered as `SyntaxError`s, with the source spans
251-
computed the way Lean does.
252-
-/
253-
public def runParserCategory' (env : Environment) (opts : Lean.Options) (catName : Name) (input : String) (fileName : String := "<example>") : Except (Array SyntaxError) Syntax :=
254-
let p := andthenFn whitespace (categoryParserFnImpl catName)
255-
let ictx := mkInputContext input fileName
256-
let s := p.run ictx { env, options := opts } (getTokenTable env) (mkParserState input)
257-
if !s.allErrors.isEmpty then
258-
Except.error <| toSyntaxErrors ictx s
259-
else if ictx.atEnd s.pos then
260-
Except.ok s.stxStack.back
261-
else
262-
Except.error (toSyntaxErrors ictx (s.mkError "end of input"))
263-
where
264-
toSyntaxErrors (ictx : InputContext) (s : ParserState) : Array SyntaxError :=
265-
s.allErrors.map fun (pos, stk, e) => (mkSyntaxError ictx pos stk e)
255+
Except.error (errorFn ictx (s.mkError "end of input"))
256+
257+
public def runParserCategory [Monad m] [MonadEnv m] [MonadLog m] [MonadOptions m]
258+
(catName : Name) (input : String) (fileName : Option String := none) : m (Except String Syntax) :=
259+
runParserCategoryGen runParserCategory.toErrorMsg catName input fileName
266260

267261
end Verso.SyntaxUtils

0 commit comments

Comments
 (0)