test(tests/playground/parser): add leanWhitespace parser
This commit is contained in:
parent
c9bd22c265
commit
7e08130c8f
2 changed files with 131 additions and 14 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import init.lean.message init.lean.parser.syntax init.lean.parser.trie init.lean.parser.basic init.lean.parser.stringliteral
|
||||
import init.lean.parser.token
|
||||
|
||||
namespace Lean
|
||||
namespace flatParser
|
||||
|
|
@ -294,10 +295,6 @@ parsingTables → parserM α
|
|||
end flatParser
|
||||
end Lean
|
||||
|
||||
def mkBigString : Nat → String → String
|
||||
| 0 s := s
|
||||
| (n+1) s := mkBigString n (s ++ "-- new comment\n")
|
||||
|
||||
section
|
||||
open Lean.flatParser
|
||||
|
||||
|
|
@ -331,27 +328,67 @@ many1' ((parseStringLiteral *> whitespace *> pure ()) <|> (str "--" *> takeUntil
|
|||
|
||||
end
|
||||
|
||||
|
||||
namespace BasicParser
|
||||
open Lean.Parser
|
||||
open Lean.Parser.MonadParsec
|
||||
|
||||
def testBasicParser (p : BasicParserM Unit) (input : String) : String :=
|
||||
let cfg : Lean.Parser.ParserConfig := {
|
||||
filename := "test", input := input, fileMap := { lines := {} }, tokens := Lean.Parser.Trie.empty } in
|
||||
let r := p cfg input.mkOldIterator {} in
|
||||
match r with
|
||||
| (Parsec.Result.ok _ it _, _) := "OK at " ++ toString it.offset
|
||||
| (Parsec.Result.error msg _, _) := "Error " ++ msg.toString
|
||||
|
||||
@[inline] def str' (s : String) : BasicParserM Unit :=
|
||||
str s *> pure ()
|
||||
|
||||
def parserP : BasicParserM Unit :=
|
||||
many1' (str' "++" <|> str' "**" <|> (str "--" *> takeUntil (λ c, c = '\n') *> any *> pure ()))
|
||||
|
||||
def parser2 : BasicParserM Unit :=
|
||||
many1' ((parseStringLiteral *> Lean.Parser.MonadParsec.whitespace *> pure ()) <|> (str "--" *> takeUntil (λ c, c = '\n') *> any *> pure ()))
|
||||
|
||||
def parser3 : BasicParserM Unit :=
|
||||
Lean.Parser.whitespace
|
||||
|
||||
end BasicParser
|
||||
|
||||
def mkBigString : Nat → String → String
|
||||
| 0 s := s
|
||||
| (n+1) s := mkBigString n (s ++ "-- new comment\n")
|
||||
|
||||
def mkBigString2 : Nat → String → String
|
||||
| 0 s := s
|
||||
| (n+1) s := mkBigString2 n (s ++ "\"hello\\nworld\"\n-- comment\n")
|
||||
|
||||
def mkBigString3 : Nat → String → String
|
||||
| 0 s := s
|
||||
| (n+1) s := mkBigString3 n (s ++ "/- /- comment 1 -/ -/ \n -- comment 2 \n \t \n ")
|
||||
|
||||
@[noinline] def testFlatP (s : String) : IO Unit :=
|
||||
IO.println (Lean.flatParser.testParser flatP s)
|
||||
|
||||
@[noinline] def testParsecP (p : Parser Unit) (s : String) : IO Unit :=
|
||||
IO.println (testParsec p s)
|
||||
|
||||
@[noinline] def testBasicParser (p : Lean.Parser.BasicParserM Unit) (s : String) : IO Unit :=
|
||||
IO.println (BasicParser.testBasicParser p s)
|
||||
|
||||
@[noinline] def prof {α : Type} (msg : String) (p : IO α) : IO α :=
|
||||
let msg₁ := "Time for '" ++ msg ++ "':" in
|
||||
let msg₂ := "Memory usage for '" ++ msg ++ "':" in
|
||||
allocprof msg₂ (timeit msg₁ p)
|
||||
|
||||
def main (xs : List String) : IO Unit :=
|
||||
let s₁ := mkBigString xs.head.toNat "" in
|
||||
let s₂ := s₁ ++ "bad" ++ mkBigString 20 "" in
|
||||
let s₃ := mkBigString2 xs.head.toNat "" in
|
||||
prof "flat Parser 1" (testFlatP s₁) *>
|
||||
prof "flat Parser 2" (testFlatP s₂) *>
|
||||
prof "Parsec 1" (testParsecP parsecP s₁) *>
|
||||
prof "Parsec 2" (testParsecP parsecP s₂) *>
|
||||
prof "Parsec 3" (testParsecP parsecP2 s₃)
|
||||
-- let s₁ := mkBigString xs.head.toNat "" in
|
||||
-- let s₂ := s₁ ++ "bad" ++ mkBigString 20 "" in
|
||||
-- let s₃ := mkBigString2 xs.head.toNat "" in
|
||||
let s₄ := mkBigString3 xs.head.toNat "" in
|
||||
-- prof "flat Parser 1" (testFlatP s₁) *>
|
||||
-- prof "flat Parser 2" (testFlatP s₂) *>
|
||||
-- prof "Parsec 1" (testParsecP parsecP s₁) *>
|
||||
-- prof "Parsec 2" (testParsecP parsecP s₂) *>
|
||||
-- prof "Parsec 3" (testParsecP parsecP2 s₃) *>
|
||||
prof "Basic parser 1" (testBasicParser BasicParser.parser3 s₄)
|
||||
|
|
|
|||
|
|
@ -225,6 +225,74 @@ partial def strLitAux : String → ParserM σ δ μ String
|
|||
def strLit : ParserM σ δ μ String :=
|
||||
ch '\"' *> strLitAux ""
|
||||
|
||||
/- Execute `p` and then `q` but does not combine epsilon flag.
|
||||
This combinator is useful for preserving tail recursion. -/
|
||||
@[inline] def seqCore (p : ParserM σ δ μ α) (q : ParserM σ δ μ β) : ParserM σ δ μ β :=
|
||||
λ str inp,
|
||||
match p str inp with
|
||||
| Result.ok _ i st bst _ := q str (mkInput i st bst)
|
||||
| Result.error msg i st etx e := Result.error msg i st etx e
|
||||
|
||||
@[inline] def fixEpsilon (p : ParserM σ δ μ α) : ParserM σ δ μ α :=
|
||||
λ str inp,
|
||||
let i := currPos inp in
|
||||
match p str inp with
|
||||
| Result.ok a i₁ st bst _ := Result.ok a i₁ st bst (i₁ > i)
|
||||
| other := other
|
||||
|
||||
partial def finishCommentBlock : Nat → ParserM σ δ μ Unit
|
||||
| nesting str inp :=
|
||||
match inp with
|
||||
| ⟨Result.ok _ i st bst _, _⟩ :=
|
||||
if str.atEnd i then mkError inp "end of input"
|
||||
else
|
||||
let c := str.get i in
|
||||
let i := str.next i in
|
||||
if c == '-' then
|
||||
if str.atEnd i then mkError inp "end of input"
|
||||
else
|
||||
let c := str.get i in
|
||||
if c == '/' then -- "-/" end of comment
|
||||
if nesting == 1 then Result.ok () (str.next i) st bst false
|
||||
else finishCommentBlock (nesting-1) str (mkInput (str.next i) st bst)
|
||||
else
|
||||
finishCommentBlock nesting str (mkInput i st bst)
|
||||
else if c == '/' then
|
||||
if str.atEnd i then mkError inp "end of input"
|
||||
else
|
||||
let c := str.get i in
|
||||
if c == '-' then finishCommentBlock (nesting+1) str (mkInput (str.next i) st bst)
|
||||
else finishCommentBlock nesting str (mkInput i st bst)
|
||||
else finishCommentBlock nesting str (mkInput i st bst)
|
||||
| ⟨Result.error _ _ _ _ _, h⟩ := unreachableError h
|
||||
|
||||
partial def leanWhitespaceAux : ParserM σ δ μ Unit
|
||||
| str inp :=
|
||||
match inp with
|
||||
| ⟨Result.ok _ i st bst _, _⟩ :=
|
||||
if str.atEnd i then inp.val
|
||||
else let c := str.get i in
|
||||
if c.isWhitespace then leanWhitespaceAux str (mkInput (str.next i) st bst)
|
||||
else if c == '-' then
|
||||
let i := str.next i in
|
||||
let c := str.get i in
|
||||
if c == '-' then seqCore (takeUntil (= '\n')) leanWhitespaceAux str (mkInput i st bst)
|
||||
else inp.val
|
||||
else if c == '/' then
|
||||
let i := str.next i in
|
||||
let c := str.get i in
|
||||
if c == '-' then
|
||||
let i := str.next i in
|
||||
let c := str.get i in
|
||||
if c == '-' then inp.val -- "/--" doc comment is an actual token
|
||||
else seqCore (finishCommentBlock 1) leanWhitespaceAux str (mkInput i st bst)
|
||||
else inp.val
|
||||
else inp.val
|
||||
| ⟨Result.error _ _ _ _ _, h⟩ := unreachableError h
|
||||
|
||||
def leanWhitespace : ParserM σ δ μ Unit :=
|
||||
fixEpsilon leanWhitespaceAux
|
||||
|
||||
end ParserM
|
||||
|
||||
class monadParser (σ : outParam Type) (δ : outParam Type) (μ : outParam Type) (m : Type → Type) :=
|
||||
|
|
@ -271,6 +339,8 @@ monadParser.map (λ β p, ParserM.lookahead p) p
|
|||
@[inline] def whitespace : m Unit := takeWhile Char.isWhitespace
|
||||
|
||||
@[inline] def strLit : m String := monadParser.lift (ParserM.strLit)
|
||||
|
||||
@[inline] def leanWhitespace : m Unit := monadParser.lift ParserM.leanWhitespace
|
||||
end
|
||||
|
||||
section
|
||||
|
|
@ -297,6 +367,9 @@ many1 (str "++" <|> str "**" <|> (str "--" *> takeUntil (= '\n') *> any *> pure
|
|||
def testP2 : Parser Unit :=
|
||||
many1 ((strLit *> whitespace *> pure ()) <|> (str "--" *> takeUntil (= '\n') *> any *> pure ()))
|
||||
|
||||
def testP3 : Parser Unit :=
|
||||
leanWhitespace
|
||||
|
||||
def testParser (x : Parser Unit) (input : String) : String :=
|
||||
match (x 0).run () () input with
|
||||
| Lean.Parser.Result.ok _ i _ _ _ := "Ok at " ++ toString i
|
||||
|
|
@ -318,6 +391,10 @@ def mkBigString2 : Nat → String → String
|
|||
| 0 s := s
|
||||
| (n+1) s := mkBigString2 n (s ++ "\"hello\\nworld\"\n-- comment\n")
|
||||
|
||||
def mkBigString3 : Nat → String → String
|
||||
| 0 s := s
|
||||
| (n+1) s := mkBigString3 n (s ++ "/- /- comment 1 -/ -/ \n -- comment 2 \n \t \n ")
|
||||
|
||||
def prof {α : Type} (msg : String) (p : IO α) : IO α :=
|
||||
let msg₁ := "Time for '" ++ msg ++ "':" in
|
||||
let msg₂ := "Memory usage for '" ++ msg ++ "':" in
|
||||
|
|
@ -331,7 +408,10 @@ do
|
|||
-- tst1,
|
||||
-- let s₁ := mkBigString xs.head.toNat "",
|
||||
-- let s₂ := s₁ ++ "bad" ++ mkBigString 20 "",
|
||||
let s₃ := mkBigString2 xs.head.toNat "",
|
||||
-- let s₃ := mkBigString2 xs.head.toNat "",
|
||||
let s₄ := mkBigString3 xs.head.toNat "",
|
||||
IO.println s₄.length,
|
||||
-- prof "Parser 1" (test testP s₁),
|
||||
-- prof "Parser 2" (test testP s₂),
|
||||
prof "Parser 3" (test testP2 s₃)
|
||||
-- prof "Parser 3" (test testP2 s₃),
|
||||
prof "Parser 4" (test testP3 s₄)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue