diff --git a/src/Driver.ml b/src/Driver.ml index bf041b4ab..fc9eb5225 100644 --- a/src/Driver.ml +++ b/src/Driver.ml @@ -3,7 +3,7 @@ open Ostap let parse cmd = let s = Util.read cmd#get_infile in let kws = [ - "skip"; + "skip"; "if"; "then"; "else"; "elif"; "fi"; "while"; "do"; "od"; "repeat"; "until"; @@ -14,7 +14,7 @@ let parse cmd = "case"; "of"; "esac"; "when"; "boxed"; "unboxed"; "string"; "sexp"; "array"; "infix"; "infixl"; "infixr"; "at"; "before"; "after"; - "true"; "false"; "lazy"; "eta"] + "true"; "false"; "lazy"; "eta"; "syntax"] in Util.parse (object diff --git a/src/Language.ml b/src/Language.ml index 64a8b6907..07564b6f4 100644 --- a/src/Language.ml +++ b/src/Language.ml @@ -775,9 +775,65 @@ module Expr = } | %"return" e:basic[infix][Val]? => {isVoid atr} => {Return e} | %"case" l:$ e:parse[infix][Val] %"of" bs:!(Util.listBy)[ostap ("|")][ostap (!(Pattern.parse) -"->" scope[infix][atr])] %"esac"{Case (e, bs, l#coord, atr)} - | l:$ %"lazy" e:basic[infix][Val] => {notRef atr} :: (not_a_reference l) => {env#add_lazy; ignore atr (Call (Var "makeLazy", [Lambda ([], e)]))} - | l:$ %"eta" e:basic[infix][Val] => {notRef atr} :: (not_a_reference l) => {let name = env#get_tmp in ignore atr (Lambda ([name], Call (e, [Var name])))} - | -"(" parse[infix][atr] -")" + | l:$ %"lazy" e:basic[infix][Val] => {notRef atr} :: (not_a_reference l) => {env#add_import "Lazy"; ignore atr (Call (Var "makeLazy", [Lambda ([], e)]))} + | l:$ %"eta" e:basic[infix][Val] => {notRef atr} :: (not_a_reference l) => {let name = env#get_tmp in ignore atr (Lambda ([name], Call (e, [Var name])))} + | l:$ %"syntax" "(" e:syntax[infix] ")" => {notRef atr} :: (not_a_reference l) => {env#add_import "Ostap"; ignore atr e} + | -"(" parse[infix][atr] -")"; + syntax[infix]: ss:!(Util.listBy)[ostap ("|")][syntaxSeq infix] { + List.fold_right (fun s -> function + | Var "" -> s + | acc -> Call (Var "alt", [s; acc]) + ) ss (Var "") + }; + syntaxSeq[infix]: ss:syntaxBinding[infix]+ sema:(-"{" parse[infix][Val] -"}")? { + let sema, ss = + match sema with + | Some s -> s, ss + | None -> + let arr, ss = + List.fold_left (fun (arr, ss) ((loc, omit, p, s) as elem) -> + match omit with + | None -> (match p with + | None -> let tmp = env#get_tmp in + ((Var tmp) :: arr, (loc, omit, Some (Pattern.Named (tmp, Pattern.Wildcard)), s) :: ss) + | Some (Pattern.Named (name, _)) -> ((Var name) :: arr, elem :: ss) + | Some p -> let tmp = env#get_tmp in + ((Var tmp) :: arr, (loc, omit, Some (Pattern.Named (tmp, p)), s) :: ss) + ) + | Some _ -> (arr, elem :: ss) + ) ([], []) ss + in + (match arr with [a] -> a | _ -> Array (List.rev arr)), List.rev ss + in + List.fold_right (fun (loc, _, p, s) -> + let make_right = + match p with + | None -> (fun body -> Lambda ([env#get_tmp], body)) + | Some (Pattern.Named (name, Pattern.Wildcard)) -> (fun body -> Lambda ([name], body)) + | Some p -> (fun body -> + let arg = env#get_tmp in + Lambda ([arg], Case (Var arg, [p, body], loc#coord, Val)) + ) + in + function + | Var "" -> Call (Var (infix_name "@"), [s; make_right sema]) + | acc -> Call (Var "seq", [s; make_right acc]) + ) ss (Var "") + }; + syntaxBinding[infix]: l:$ omit:"-"? p:(!(Pattern.parse) -"=")? s:syntaxPostfix[infix]; + syntaxPostfix[infix]: s:syntaxPrimary[infix] p:("*" {`Rep0} | "+" {`Rep} | "?" {`Opt})? { + match p with + | None -> s + | Some `Opt -> Call (Var "opt" , [s]) + | Some `Rep -> Call (Var "rep" , [s]) + | Some `Rep0 -> Call (Var "rep0", [s]) + }; + syntaxPrimary[infix]: l:$ p:LIDENT args:(-"(" !(Util.list0)[parse infix Val] -")")* { + Loc.attach p l#coord; + List.fold_left (fun acc args -> Call (acc, args)) (Var p) args + } + | -"(" syntax[infix] -")" + | -"$(" parse[infix][Val] -")" ) in (fun def -> defCell := Obj.magic !def; parse), (fun def -> defCell := Obj.magic !def; basic), (fun def -> defCell := Obj.magic !def; scope) @@ -1147,12 +1203,12 @@ ostap ( let parse cmd = let env = object - val lazy_used = Pervasives.ref false + val imports = Pervasives.ref ([] : string list) val tmp_index = Pervasives.ref 0 - method add_lazy = lazy_used := true - method get_tmp = let index = !tmp_index in incr tmp_index; Printf.sprintf "__tmp%d" index - method is_lazy = !lazy_used + method add_import imp = imports := imp :: !imports + method get_tmp = let index = !tmp_index in incr tmp_index; Printf.sprintf "__tmp%d" index + method get_imports = !imports end in @@ -1186,7 +1242,7 @@ let parse cmd = <(is, infix)> : imports[cmd] <(d, infix')> : definitions[infix] expr:expr[infix'][Expr.Weak]? { - ((if env#is_lazy then "Lazy" :: is else is), Infix.extract_exports infix'), Expr.Scope (d, match expr with None -> Expr.materialize Expr.Weak Expr.Skip | Some e -> e) + (env#get_imports @ is, Infix.extract_exports infix'), Expr.Scope (d, match expr with None -> Expr.materialize Expr.Weak Expr.Skip | Some e -> e) } ) in diff --git a/src/version.ml b/src/version.ml index 155880415..cc1eacf50 100644 --- a/src/version.ml +++ b/src/version.ml @@ -1 +1 @@ -let version = "Version 1.00, b7ec1c2e6, Mon Mar 23 00:51:00 2020 +0300" +let version = "Version 1.00, 7748144a8, Fri Apr 10 03:15:18 2020 +0300" diff --git a/stdlib/Ostap.lama b/stdlib/Ostap.lama index 90c891742..e7f74b9ae 100644 --- a/stdlib/Ostap.lama +++ b/stdlib/Ostap.lama @@ -74,6 +74,12 @@ public fun token (x) { esac } +public fun loc (k) { + fun (s) { + k $ Succ ([s.getLine, s.getCol], s) + } +} + public fun eof (k) { fun (s) { k (endOfMatcher (s)) @@ -235,18 +241,18 @@ public fun parseString (p, s) { acc.result } -public fun left (f) { +public fun left (op, f) { fun (c, x) { fun (y) { - f (c (x), y) + f (c (x), op, y) } } } -public fun right (f) { +public fun right (op, f) { fun (c, x) { fun (y) { - c (f (x, y)) + c (f (x, op, y)) } } } @@ -258,7 +264,7 @@ fun altl (level) { local assfun = case assoc of Left -> left | Right -> right | Nona -> left esac; case map (fun (p) { case p of - [op, sema] -> op @ lift(assfun (sema)) + [op, sema] -> op @ fun (op) {assfun (op, sema)} esac }, ps) of p : ps -> foldl (infix |, p, ps) diff --git a/stdlib/regression/orig/test28.log b/stdlib/regression/orig/test28.log new file mode 100644 index 000000000..7c3587ea9 --- /dev/null +++ b/stdlib/regression/orig/test28.log @@ -0,0 +1,4 @@ +Succ (Seq ("a", "b")) +Succ (Alt ("a")) +Succ (Alt ("b")) +Succ (Rep ({"a", "a", "a"})) diff --git a/stdlib/regression/orig/test29.log b/stdlib/regression/orig/test29.log new file mode 100644 index 000000000..7c3587ea9 --- /dev/null +++ b/stdlib/regression/orig/test29.log @@ -0,0 +1,4 @@ +Succ (Seq ("a", "b")) +Succ (Alt ("a")) +Succ (Alt ("b")) +Succ (Rep ({"a", "a", "a"})) diff --git a/stdlib/regression/test11.lama b/stdlib/regression/test11.lama index 62bf27501..7cc97d7ab 100644 --- a/stdlib/regression/test11.lama +++ b/stdlib/regression/test11.lama @@ -2,10 +2,10 @@ import Ostap; import Fun; local a = token ("a"), - add = [token ("+"), fun (l, r) {Add (l, r)}], - sub = [token ("-"), fun (l, r) {Sub (l, r)}], - mul = [token ("*"), fun (l, r) {Mul (l, r)}], - div = [token ("/"), fun (l, r) {Div (l, r)}], + add = [token ("+"), fun (l, _, r) {Add (l, r)}], + sub = [token ("-"), fun (l, _, r) {Sub (l, r)}], + mul = [token ("*"), fun (l, _, r) {Mul (l, r)}], + div = [token ("/"), fun (l, _, r) {Div (l, r)}], exp = expr ({[Left, {add, sub}], [Left, {mul, div}]}, a) (id); printf ("%s\n", parseString (exp |> bypass (eof), "a").string); diff --git a/stdlib/regression/test12.lama b/stdlib/regression/test12.lama index e739ed76b..74c474561 100644 --- a/stdlib/regression/test12.lama +++ b/stdlib/regression/test12.lama @@ -9,10 +9,10 @@ fun gen (depth) { } local a = token ("a"), - add = [token ("+"), fun (l, r) {Add (l, r)}], - sub = [token ("-"), fun (l, r) {Sub (l, r)}], - mul = [token ("*"), fun (l, r) {Mul (l, r)}], - div = [token ("/"), fun (l, r) {Div (l, r)}], + add = [token ("+"), fun (l, _, r) {Add (l, r)}], + sub = [token ("-"), fun (l, _, r) {Sub (l, r)}], + mul = [token ("*"), fun (l, _, r) {Mul (l, r)}], + div = [token ("/"), fun (l, _, r) {Div (l, r)}], exp = expr ({[Left, {add, sub}], [Left, {mul, div}]}, a) (id), i; diff --git a/stdlib/regression/test13.lama b/stdlib/regression/test13.lama index b6277bef9..57c6b9008 100644 --- a/stdlib/regression/test13.lama +++ b/stdlib/regression/test13.lama @@ -2,10 +2,10 @@ import Ostap; import Fun; local a = token ("a"), - add = [token ("+"), fun (l, r) {Add (l, r)}], - sub = [token ("-"), fun (l, r) {Sub (l, r)}], - mul = [token ("*"), fun (l, r) {Mul (l, r)}], - div = [token ("/"), fun (l, r) {Div (l, r)}], + add = [token ("+"), fun (l, _, r) {Add (l, r)}], + sub = [token ("-"), fun (l, _, r) {Sub (l, r)}], + mul = [token ("*"), fun (l, _, r) {Mul (l, r)}], + div = [token ("/"), fun (l, _, r) {Div (l, r)}], exp = expr ({[Right, {add, sub}], [Left, {mul, div}]}, a) (id); printf ("%s\n", parseString (exp |> bypass (eof), "a+a-a").string); diff --git a/stdlib/regression/test14.lama b/stdlib/regression/test14.lama index 4eb50b462..6cf1f7b12 100644 --- a/stdlib/regression/test14.lama +++ b/stdlib/regression/test14.lama @@ -3,11 +3,11 @@ import Fun; import List; local a = token ("a"), - eq = [token ("="), fun (l, r) {Eq (l, r)}], - add = [token ("+"), fun (l, r) {Add (l, r)}], - sub = [token ("-"), fun (l, r) {Sub (l, r)}], - mul = [token ("*"), fun (l, r) {Mul (l, r)}], - div = [token ("/"), fun (l, r) {Div (l, r)}], + eq = [token ("="), fun (l, _, r) {Eq (l, r)}], + add = [token ("+"), fun (l, _, r) {Add (l, r)}], + sub = [token ("-"), fun (l, _, r) {Sub (l, r)}], + mul = [token ("*"), fun (l, _, r) {Mul (l, r)}], + div = [token ("/"), fun (l, _, r) {Div (l, r)}], exp = expr ({[Nona, singleton (eq)], [Right, {add, sub}], [Left, {mul, div}]}, a) (id); printf ("%s\n", parseString (exp |> bypass (eof), "a+a-a").string); diff --git a/stdlib/regression/test15.lama b/stdlib/regression/test15.lama index 63395235d..5f3224624 100644 --- a/stdlib/regression/test15.lama +++ b/stdlib/regression/test15.lama @@ -3,11 +3,11 @@ import Fun; import List; local a = token ("a"), - eq = [token ("="), fun (l, r) {Eq (l, r)}], - add = [token ("+"), fun (l, r) {Add (l, r)}], - sub = [token ("-"), fun (l, r) {Sub (l, r)}], - mul = [token ("*"), fun (l, r) {Mul (l, r)}], - div = [token ("/"), fun (l, r) {Div (l, r)}], + eq = [token ("="), fun (l, _, r) {Eq (l, r)}], + add = [token ("+"), fun (l, _, r) {Add (l, r)}], + sub = [token ("-"), fun (l, _, r) {Sub (l, r)}], + mul = [token ("*"), fun (l, _, r) {Mul (l, r)}], + div = [token ("/"), fun (l, _, r) {Div (l, r)}], exp = expr ({[Nona, singleton (eq)], [Right, {add, sub}], [Left, {mul, div}]}, a) (id); printf ("%s\n", parseString (exp |> bypass (eof), "a=a").string); diff --git a/stdlib/regression/test16.lama b/stdlib/regression/test16.lama index 7cbd09ec9..4443c61d2 100644 --- a/stdlib/regression/test16.lama +++ b/stdlib/regression/test16.lama @@ -3,11 +3,11 @@ import Fun; import List; local a = token ("a") @ lift(fun (a) {if a then "a" else "b" fi}), - eq = [token ("="), fun (l, r) {fun (a) {Eq (l (a), r (a))}}], - add = [token ("+"), fun (l, r) {fun (a) {Add (l (a), r (a))}}], - sub = [token ("-"), fun (l, r) {fun (a) {Sub (l (a), r (a))}}], - mul = [token ("*"), fun (l, r) {fun (a) {Mul (l (a), r (a))}}], - div = [token ("/"), fun (l, r) {fun (a) {Div (l (a), r (a))}}], + eq = [token ("="), fun (l, _, r) {fun (a) {Eq (l (a), r (a))}}], + add = [token ("+"), fun (l, _, r) {fun (a) {Add (l (a), r (a))}}], + sub = [token ("-"), fun (l, _, r) {fun (a) {Sub (l (a), r (a))}}], + mul = [token ("*"), fun (l, _, r) {fun (a) {Mul (l (a), r (a))}}], + div = [token ("/"), fun (l, _, r) {fun (a) {Div (l (a), r (a))}}], exp = expr ({[Nona, singleton (eq)], [Right, {add, sub}], [Left, {mul, div}]}, a) (id); fun unpack (x, y) { diff --git a/stdlib/regression/test28.lama b/stdlib/regression/test28.lama new file mode 100644 index 000000000..08c95cab2 --- /dev/null +++ b/stdlib/regression/test28.lama @@ -0,0 +1,8 @@ +local sq = syntax (e1=token ("a") e2=token ("b") {Seq (e1, e2)}), + al = syntax (e=(token ("a") | token ("b")) {Alt (e)}), + rp = syntax (e=token ("a")* {Rep (e)}); + +printf ("%s\n", parseString (syntax (p=sq eof {p}), "ab").string); +printf ("%s\n", parseString (syntax (p=al eof {p}), "a").string); +printf ("%s\n", parseString (syntax (p=al eof {p}), "b").string); +printf ("%s\n", parseString (syntax (p=rp eof {p}), "aaa").string) \ No newline at end of file diff --git a/stdlib/regression/test29.lama b/stdlib/regression/test29.lama new file mode 100644 index 000000000..06de4fa6f --- /dev/null +++ b/stdlib/regression/test29.lama @@ -0,0 +1,8 @@ +local sq = syntax (e1=token ("a") e2=token ("b") {Seq (e1, e2)}), + al = syntax (e=(token ("a") | token ("b")) {Alt (e)}), + rp = syntax (e=token ("a")* {Rep (e)}); + +printf ("%s\n", parseString (syntax (sq -eof), "ab").string); +printf ("%s\n", parseString (syntax (al -eof), "a").string); +printf ("%s\n", parseString (syntax (al -eof), "b").string); +printf ("%s\n", parseString (syntax (rp -eof), "aaa").string) \ No newline at end of file