Files
lean4/tests/playground/filemap.lean
2019-04-02 17:23:13 -07:00

75 lines
2.4 KiB
Lean4
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
structure Position :=
(line : Nat := 1)
(column : Nat := 0)
instance : Inhabited Position :=
{}
structure FileMap :=
(source : String)
(positions : Array String.Pos)
(lines : Array Nat)
namespace FileMap
instance : Inhabited FileMap :=
{ source := "", positions := Array.empty, lines := Array.empty }
private partial def ofStringAux (s : String) : String.Pos Nat Array String.Pos Array Nat FileMap
| i line ps lines :=
if s.atEnd i then { source := s, positions := ps.push i, lines := lines.push line }
else
let c := s.get i in
let i := s.next i in
if c == '\n' then ofStringAux i (line+1) (ps.push i) (lines.push (line+1))
else ofStringAux i line ps lines
def ofString (s : String) : FileMap :=
ofStringAux s 0 1 (Array.empty.push 0) (Array.empty.push 1)
private partial def toColumnAux (str : String) (lineBeginPos : String.Pos) (pos : String.Pos) : String.Pos Nat Nat
| i c :=
if i == pos || str.atEnd i then c
else toColumnAux (str.next i) (c+1)
/- Remark: `pos` is in `[ps.get b, ps.get e]` and `b < e` -/
private partial def toPositionAux (str : String) (ps : Array Nat) (lines : Array Nat) (pos : String.Pos) : Nat Nat Position
| b e :=
let posB := ps.get b in
if e == b + 1 then { line := lines.get b, column := toColumnAux str posB pos posB 0 }
else
let m := (b + e) / 2 in
let posM := ps.get m in
if pos == posM then { line := lines.get m, column := 0 }
else if pos > posM then toPositionAux m e
else toPositionAux b m
def toPosition : FileMap String.Pos Position
| { source := str, positions := ps, lines := lines } pos := toPositionAux str ps lines pos 0 (ps.size-1)
end FileMap
def String.toFileMap (s : String) : FileMap :=
FileMap.ofString s
partial def showLineColsAux (fmap : FileMap) : String.Pos IO Unit
| i :=
if fmap.source.atEnd i then pure ()
else do
let p := fmap.toPosition i,
IO.println ("[" ++ toString i ++ "] := (" ++ toString p.line ++ ", " ++ toString p.column ++ ")"),
showLineColsAux (fmap.source.next i)
def showLineCols (str : String) : IO Unit :=
let fmap := FileMap.ofString str in
IO.println ("string: " ++ repr str) *>
showLineColsAux fmap 0
def main (xs : List String) : IO Unit :=
do
showLineCols ("hello\nwoαld\ntβst"),
showLineCols "",
showLineCols "\n\n\n",
showLineCols "\n\n\nabc\n",
showLineCols "\n\n\nabc"