lean4-htt/tests/lean/run/parseEnd.lean
David Thrane Christiansen c9727c2d19
feat: add a stop position field to the parser (#10043)
This PR allows Lean's parser to run with a final position prior to the
end of the string, so it can be invoked on a sub-region of the input.

This has applications in Verso proper, which parses Lean syntax in
contexts such as code blocks and docstrings, and it is a prerequisite to
parsing the contents of Lean docstrings.
2025-08-23 18:29:51 +00:00

59 lines
1.5 KiB
Text

import Lean.Elab.Command
open Lean Elab Command Parser
declare_syntax_cat balanced
syntax "!" : balanced
syntax "(" balanced* ")" : balanced
elab d:docComment "test" : command => do
let some ⟨pos, endPos⟩ := d.raw[1].getRange? (canonicalOnly := true)
| throwErrorAt d "Docstring doesn't have a canonical position"
let p := Parser.categoryParser `balanced 0
let p := andthenFn whitespace p.fn
let text ← getFileMap
let input := text.source
let endPos := input.prev <| input.prev endPos
if h : endPos ≤ input.endPos then
let ictx := mkInputContext input (← getFileName) (endPos := endPos) (endPos_valid := h)
let env ← getEnv
let s := { mkParserState input with pos }
let s := p.run ictx { env, options := {} } (getTokenTable env) s
if !s.allErrors.isEmpty then
for (pos, _, err) in s.allErrors do
logMessage {
fileName := (← getFileName )
pos := text.toPosition pos
endPos := some (text.toPosition endPos)
data := s!"{err.toString}"
}
else if ictx.atEnd s.pos then
logInfo s.stxStack.back
else
let pos := s.pos
logMessage {
fileName := (← getFileName )
pos := text.toPosition pos
endPos := some (text.toPosition endPos)
data := s!"expected end of input"
}
else
throwError "Out of bounds"
/-- info: (!!(!)) -/
#guard_msgs in
/--
( ! ! (!) )
-/
test
/-- error: unexpected end of input; expected ')' -/
#guard_msgs in
/--
(
-/
test