Skip to content

Commit

Permalink
remove hashmap and bounds analysis for issue #2
Browse files Browse the repository at this point in the history
  • Loading branch information
thautwarm committed Sep 2, 2018
1 parent 5883e2c commit 2b6b7d9
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 357 deletions.
98 changes: 55 additions & 43 deletions RBNF.Test/Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,16 @@ let def_token str_lst =
type sexpr =
| Term of string
| S of sexpr list
with static member copy this = this

type Expr =
| Add of Expr * Expr
and Expr =
| Add of left: Expr * right: Expr
| Sym of string
| Empty


type default_value = Default
with static member copy this = this
type MyTests(output:ITestOutputHelper) =

[<Fact>]
Expand All @@ -36,10 +41,10 @@ type MyTests(output:ITestOutputHelper) =
let v1 = V "123"
let v2 = V "234"
let node_name = "node"
let node = Named node_name
let node = Named(node_name, fun () -> Default)
let node_impl = Or [And [node; v1]; v2]
let tokens = def_token ["234"; "123"; "123"]
let state = State<string>.inst()
let state = State<default_value>.inst(Default)
let (:=) = state.implement
node := node_impl
parse node tokens state |> sprintf "%A" |> output.WriteLine
Expand All @@ -51,14 +56,14 @@ type MyTests(output:ITestOutputHelper) =
let v1 = V("a")
let v2 = V("b")
let v3 = V("c")
let node = Named("node")
let mid = Named("mid")
let node = Named("node", fun () -> Default)
let mid = Named("mid", fun () -> Default)

let node_impl = Or [And [mid; v2]; v1]
let mid_impl = And [node; v3]
let tokens = def_token ["a"; "c"; "b"; "c"; "b"]

let state: State<string> = State<string>.inst()
let state = State<default_value>.inst(Default)
let (:=) = state.implement
node := node_impl
mid := mid_impl
Expand Down Expand Up @@ -86,7 +91,7 @@ type MyTests(output:ITestOutputHelper) =
let identifier = V "abs"
let plus_operator = V "+"
let plus_name = "plus"
let plus = Named plus_name
let plus = Named(plus_name, fun () -> Default)
let plus_impl = Or [And [plus; plus_operator; identifier]; identifier]

let tokens =
Expand All @@ -104,7 +109,7 @@ type MyTests(output:ITestOutputHelper) =
"+"
"abs"
]
let state = State<string>.inst()
let state = State<default_value>.inst(Default)
let (:=) = state.implement
plus := plus_impl
parse plus tokens state |> sprintf "%A" |> output.WriteLine
Expand Down Expand Up @@ -143,7 +148,7 @@ type MyTests(output:ITestOutputHelper) =
[<Fact>]
member __.``rewrite add``() =
let state = State<Expr>.inst()
let plus = Named "plus"
let plus = Named("plus", fun () -> Add(Empty, Empty))

let (:=) = state.implement
let identifier =
Expand All @@ -155,25 +160,30 @@ type MyTests(output:ITestOutputHelper) =

plus := Or
[
And [plus.bind_to("emm"); C "+"; identifier]
identifier
And[
Lens(
(fun (Add(_, b)) (Value it) -> Add(it, b)),
plus)

C "+"
Lens(
(fun (Add(a, _)) (Value it) -> Add(a, it)),
identifier)
]
Lens((fun _ (Value it) -> it), identifier)
]
=>
fun state ast ->
match ast with
| Nested arr ->
let (Value l) = arr.[0]
let (Value r) = arr.[2]
Add(l, r) |> Value
| _ -> ast
let a, b = analyse analysis.crate [for each in ["plus"] -> each, state.lang.[each]]
state.ctx |> Value

let lexer_tb = analyse [for each in ["plus"] -> state.lang.[each]]


let tokens = lex None b {filename=""; text="abs+abs+abs"} |> Array.ofSeq
let tokens = lex None lexer_tb {filename=""; text="abs+abs+abs"} |> Array.ofSeq

parse plus tokens state |> sprintf "%A" |> output.WriteLine

sprintf "%A \n %A" a b |> output.WriteLine
sprintf "%A" lexer_tb |> output.WriteLine
0
[<Fact>]
member __.``lisp``() =
Expand All @@ -184,34 +194,36 @@ type MyTests(output:ITestOutputHelper) =
| _ -> failwith "emmm"

let space = R "space" "\s+"
let sexpr = Named "sexpr"
let sexpr = Named("sexpr", fun () -> S [])

let state = State<sexpr>.inst()
let (:=) = state.implement

Named "space" := space (** only for building auto lexer which contains `space` from grammar*)

sexpr := Or [And[C"("; Rep(0, -1, sexpr).bind_to("sexpr"); C")"]; term]
Named("space", fun () -> failwith "emmm") := space (** only for building auto lexer which contains `space` from grammar*)

sexpr := Or [
And[C"(";
Lens(
(fun (S _) (Nested it) ->
Array.map
<| fun (Value it) -> it
<| it.ToArray()
|> List.ofArray
|> S
),
Rep(0, -1, sexpr))
C")"];

Lens((fun _ (Value it) -> it), term)
]
=>
fun state ast ->
match state.ctx.TryGetValue "sexpr" with
| (false, _) -> ast
| (true, it) ->
match it with
| Nested lst ->
Seq.map
<| fun (Value it) -> it
<| lst
|> List.ofSeq
|> S
|> Value
| _ -> failwith "emmm"



let bounds_map, lexer_factors =
analyse analysis.crate
[for each in ["space";"sexpr";] -> each, state.lang.[each]]
Value <| state.ctx



let lexer_factors =
analyse [for each in ["space";"sexpr";] -> state.lang.[each]]

let tokens = lex None lexer_factors {filename = ""; text = "(add 1 (mul 2 3))"}
|> Seq.filter (fun it -> it.name <> "space")
Expand Down
46 changes: 4 additions & 42 deletions RBNF/AutoLexer/analyse.fs
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
module RBNF.analyse
open RBNF.ParserC
open RBNF.Lexer
open RBNF.Infras
open System.Linq

type bound_name_descriptor = {
name : string
is_lst : bool
}

type analysis = {
bounds : bound_name_descriptor Set
lexer_tb : lexer array
}
with
static member crate = {bounds = set []; lexer_tb = [||]}


let mergeable = function
Expand Down Expand Up @@ -44,49 +31,24 @@ let merge_lexer_tb (tb: lexer array) (lexer: lexer): lexer array =
let merge_lexer_tbs (tb1: lexer array) (tb2: lexer array): lexer array =
Array.fold merge_lexer_tb tb1 tb2

let rec analyse (analysis: analysis) (lang: (string * 't parser) list) =
let rec inline analyse (parsers: 't parser list) =
let rec proc analysis parser =
match parser with
| Literal {lexer = Some lexer} ->
let lexer = lexer()
{analysis with lexer_tb = merge_lexer_tb analysis.lexer_tb lexer}
merge_lexer_tb analysis lexer

| AnyNot(parser)
| Rewrite(parser, _)
| Lens(_, parser)
| Rep(_, _, parser) -> proc analysis parser
| Bind(varname, parser) ->
let record = {name = varname; is_lst=false}
let analysis =
match Set.contains record analysis.bounds with
| false ->
{analysis with bounds = analysis.bounds.Add record}
| true ->
analysis
proc analysis parser

| Push(varname, parser) ->
let record = {name = varname; is_lst=true}
let analysis =
match Set.contains record analysis.bounds with
| false ->
{analysis with bounds = analysis.bounds.Add record}
| true ->
analysis
proc analysis parser

| Or(many)
| And(many) ->
List.fold proc analysis many
| _ -> analysis

let bounds, lexer_tbs =
[
for (name, parser) in lang do
let analysis = proc analysis parser
yield (name, analysis.bounds), analysis.lexer_tb
]
|> List.unzip
Map.ofList bounds,
let lexer_tbs = List.map (proc [||]) parsers
let fn (lexer : lexer) =
match lexer with
| {factor = StringFactor lst;} ->
Expand Down
Loading

0 comments on commit 2b6b7d9

Please sign in to comment.