Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- open FParsec
- open FParsec.CharParsers
- open System.Text.RegularExpressions
- // now () returns current time in milliseconds since start
- let now : unit -> int64 =
- let sw = System.Diagnostics.Stopwatch ()
- sw.Start ()
- fun () -> sw.ElapsedMilliseconds
- // time estimates the time 'action' repeated a number of times
- let time repeat action =
- let inline cc i = System.GC.CollectionCount i
- let v = action ()
- System.GC.Collect (2, System.GCCollectionMode.Forced, true)
- let bcc0, bcc1, bcc2 = cc 0, cc 1, cc 2
- let b = now ()
- for i in 1..repeat do
- action () |> ignore
- let e = now ()
- let ecc0, ecc1, ecc2 = cc 0, cc 1, cc 2
- v, (e - b), ecc0 - bcc0, ecc1 - bcc1, ecc2 - bcc2
- let regex = Regex ( @"^\s*(?<id>\w+)\s*=\s*(?<val>\d+)\s*$"
- , RegexOptions.Compiled ||| RegexOptions.ExplicitCapture ||| RegexOptions.Singleline ||| RegexOptions.CultureInvariant
- )
- let rparse s =
- let m = regex.Match s
- if m.Success then
- let i = m.Groups.["id"].Value
- let v = m.Groups.["val"].Value |> int
- Some (i, v)
- else
- None
- let fparser : Parser<_, unit> =
- spaces
- >>. manyChars CharParsers.letter
- .>> spaces
- .>> skipChar '='
- .>> spaces
- .>>. pint32
- .>> spaces
- .>> eof
- let fparse s =
- match runParserOnString fparser () "Input" s with
- | Success (v, _, _) -> Some v
- | Failure (s, _, _) -> None
- let inline isChar ch = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')
- let inline isDigit ch = ch >= '0' && ch <= '9'
- let z = 0
- type Parser(input : string) =
- let mutable pos = 0
- let mutable id = Array.zeroCreate 32
- let mutable idpos = 0
- let mutable value = 0
- member x.spaces () =
- let rec loop () =
- if pos < input.Length && input.[pos] = ' ' then
- pos <- pos + 1
- loop ()
- loop ()
- true
- member x.skipChar ch =
- if pos < input.Length && input.[pos] = ch then
- pos <- pos + 1
- true
- else
- false
- member x.identifier () =
- let rec loop () =
- if pos < input.Length then
- let ch = input.[pos]
- if isChar ch then
- id.[idpos] <- ch
- idpos <- idpos + 1
- pos <- pos + 1
- loop ()
- let prev = pos
- loop ()
- prev < pos
- member x.integer () =
- let rec loop () =
- if pos < input.Length then
- let ch = input.[pos]
- if isDigit ch then
- value <- value*10 + int ch - int '0'
- pos <- pos + 1
- loop ()
- let prev = pos
- loop ()
- prev < pos
- member x.eof () =
- pos >= input.Length
- member x.parse () =
- let result =
- x.spaces ()
- && x.identifier ()
- && x.spaces ()
- && x.skipChar '='
- && x.spaces ()
- && x.integer ()
- && x.spaces ()
- && x.eof ()
- if result then
- Some (System.String (id, 0, idpos), value)
- else
- None
- let cparse s =
- let p = Parser s
- p.parse ()
- let testCases =
- [|
- 100000 , "x=3"
- 100000 , " abcdef = 2930932 "
- 100000 , " abcdefghijklmnopqrst = 2930932 "
- 100000 , "x="
- 100000 , " abcdef = 2930932 aa"
- |]
- [<EntryPoint>]
- let main argv =
- for repeat, expr in testCases do
- printfn "Running test case %A (iterations: %d)" expr repeat
- let rresult, rtime, rcc0, rcc1, rcc2 = time repeat (fun () -> rparse expr)
- let fresult, ftime, fcc0, fcc1, fcc2 = time repeat (fun () -> fparse expr)
- let cresult, ctime, ccc0, ccc1, ccc2 = time repeat (fun () -> cparse expr)
- printfn "Regex result : %A (time: %d, cc0: %d, cc1: %d, cc2: %d)" rresult rtime rcc0 rcc1 rcc2
- printfn "FParsec result : %A (time: %d, cc0: %d, cc1: %d, cc2: %d)" fresult ftime fcc0 fcc1 fcc2
- printfn "Custom result : %A (time: %d, cc0: %d, cc1: %d, cc2: %d)" cresult ctime ccc0 ccc1 ccc2
- printfn "Results are %s" (if rresult = fresult && rresult = cresult then "EQUAL" else "NOT EQUAL")
- 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement