From 5883e2cea9408245566b992caeb5f8ab45e0584a Mon Sep 17 00:00:00 2001 From: thautwarm Date: Sun, 2 Sep 2018 03:38:29 +0800 Subject: [PATCH] add simple lisp --- RBNF.Test/Tests.fs | 55 ++++++++++++++++++++++++++++++++++++--- RBNF/AutoLexer/analyse.fs | 7 +++-- RBNF/RBNF.fsproj | 4 +++ 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/RBNF.Test/Tests.fs b/RBNF.Test/Tests.fs index 7a4e022..b9a9c63 100644 --- a/RBNF.Test/Tests.fs +++ b/RBNF.Test/Tests.fs @@ -20,6 +20,9 @@ let def_token str_lst = (fun str -> {filename = ""; value = str ; name = "const" ; colno = 1; lineno = 1; offset = 1;}) +type sexpr = +| Term of string +| S of sexpr list type Expr = | Add of Expr * Expr @@ -152,7 +155,7 @@ type MyTests(output:ITestOutputHelper) = plus := Or [ - And [plus; C "+"; identifier] + And [plus.bind_to("emm"); C "+"; identifier] identifier ] => @@ -163,11 +166,57 @@ type MyTests(output:ITestOutputHelper) = let (Value r) = arr.[2] Add(l, r) |> Value | _ -> ast - let a, b = analyse analysis.crate state.lang + let a, b = analyse analysis.crate [for each in ["plus"] -> each, state.lang.[each]] - let tokens = lex None (Array.toList b) {filename=""; text="abs+abs+abs"} |> Array.ofSeq + + let tokens = lex None b {filename=""; text="abs+abs+abs"} |> Array.ofSeq parse plus tokens state |> sprintf "%A" |> output.WriteLine sprintf "%A \n %A" a b |> output.WriteLine 0 + [] + member __.``lisp``() = + let term = R "term" "[^\(\)\:\s]+" => + fun state ast -> + match ast with + | Token tk -> Value <| Term tk.value + | _ -> failwith "emmm" + + let space = R "space" "\s+" + let sexpr = Named "sexpr" + + let state = State.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] + => + 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]] + + let tokens = lex None lexer_factors {filename = ""; text = "(add 1 (mul 2 3))"} + |> Seq.filter (fun it -> it.name <> "space") + |> Array.ofSeq + + let ast = parse sexpr tokens state + output.WriteLine <| sprintf "%A" ast + 0 diff --git a/RBNF/AutoLexer/analyse.fs b/RBNF/AutoLexer/analyse.fs index f17b392..2676abf 100644 --- a/RBNF/AutoLexer/analyse.fs +++ b/RBNF/AutoLexer/analyse.fs @@ -44,8 +44,7 @@ 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) hashmap) = - let lang = seq{ for a in lang -> (a.Key, a.Value)} |> Map.ofSeq +let rec analyse (analysis: analysis) (lang: (string * 't parser) list) = let rec proc analysis parser = match parser with | Literal {lexer = Some lexer} -> @@ -82,7 +81,7 @@ let rec analyse (analysis: analysis) (lang: (string, 't parser) hashmap) = let bounds, lexer_tbs = [ - for (name, parser) in Map.toList lang do + for (name, parser) in lang do let analysis = proc analysis parser yield (name, analysis.bounds), analysis.lexer_tb ] @@ -93,4 +92,4 @@ let rec analyse (analysis: analysis) (lang: (string, 't parser) hashmap) = | {factor = StringFactor lst;} -> {lexer with factor = StringFactor <| List.sortDescending lst} | _ -> lexer - in List.reduce merge_lexer_tbs lexer_tbs |> Array.map fn + in List.reduce merge_lexer_tbs lexer_tbs |> Array.map fn |> Array.toList diff --git a/RBNF/RBNF.fsproj b/RBNF/RBNF.fsproj index 5d3e428..2e490a8 100644 --- a/RBNF/RBNF.fsproj +++ b/RBNF/RBNF.fsproj @@ -16,6 +16,7 @@ + @@ -27,6 +28,9 @@ + + +