From a811b28bc150ba4a7da4d18afa9cb5132f20ad26 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sun, 29 Mar 2020 22:07:55 -0400 Subject: [PATCH] SELF MODIFYING GRAMMER WORKS! --- fungll.krak | 46 ++++++++++--------- k_prime.krak | 122 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 114 insertions(+), 54 deletions(-) diff --git a/fungll.krak b/fungll.krak index bf77e64..8240696 100644 --- a/fungll.krak +++ b/fungll.krak @@ -7,12 +7,12 @@ import str:* import regex:* // nonterminals are negative, terminals are positive -obj Grammer (Object) { +obj Grammer (Object) { var nonterminals: vec>> var nonterminal_names: vec - var nonterminal_funs: vec): T>> + var nonterminal_funs: vec): T>>> var terminals: vec - var terminal_funs: vec + var terminal_funs: vec> var start_symbol: int fun construct(): *Grammer { nonterminals.construct() @@ -42,22 +42,28 @@ obj Grammer (Object) { destruct() copy_construct(&other) } - fun add_new_nonterminal(name: *char, rule: ref vec, f: fun(ref vec): T): int { - return add_new_nonterminal(str(name), rule, f) + fun add_new_nonterminal(name: *char, rule: ref vec, d: K, f: fun(ref K,ref vec): T): int { + return add_new_nonterminal(str(name), rule, d, f) } - fun add_new_nonterminal(name: ref str, rule: ref vec, f: fun(ref vec): T): int { + fun add_new_nonterminal(name: ref str, rule: ref vec, d: K, f: fun(ref K,ref vec): T): int { nonterminals.add(vec(rule)) nonterminal_names.add(name) - nonterminal_funs.add(vec(f)) + nonterminal_funs.add(vec(make_pair(d,f))) return -1*nonterminals.size } - fun add_to_nonterminal(nonterminal: int, rule: ref vec, f: fun(ref vec): T) { - nonterminals[(-1*nonterminal)-1].add(rule) - nonterminal_funs[(-1*nonterminal)-1].add(f) + fun add_to_nonterminal(nonterminal: ref str, rule: ref vec, d: K, f: fun(ref K,ref vec): T) { + add_to_nonterminal(-1*(nonterminal_names.find(nonterminal)+1), rule, d, f) } - fun add_terminal(c: *char, f: fun(ref str,int,int): T): int { + fun add_to_nonterminal(nonterminal: int, rule: ref vec, d: K, f: fun(ref K,ref vec): T) { + nonterminals[(-1*nonterminal)-1].add(rule) + nonterminal_funs[(-1*nonterminal)-1].add(make_pair(d,f)) + } + fun add_terminal(c: *char, d: K, f: fun(ref K,ref str,int,int): T): int { + return add_terminal(str(c), d, f) + } + fun add_terminal(c: ref str, d: K, f: fun(ref K,ref str,int,int): T): int { terminals.add(regex(c)) - terminal_funs.add(f) + terminal_funs.add(make_pair(d,f)) return terminals.size } fun get_nonterminal_rules(nonterminal: int): ref vec> { @@ -119,7 +125,7 @@ obj Grammer (Object) { for (var i = bs.idx_into_rule-1; i >= 0; i--;) { var erminal = nonterminals[nonterminal][bs.rule_idx][i] if is_terminal(erminal) { - var right_value = terminal_funs[erminal-1](input, bs.pivot, bs.right) + var right_value = terminal_funs[erminal-1].second(terminal_funs[erminal-1].first, input, bs.pivot, bs.right) params.add(right_value) } else { /*var right = find_comp(erminal, bs.pivot, bs.right)*/ @@ -147,7 +153,7 @@ obj Grammer (Object) { bs = BSR.data[new_bs_idx] } } - var to_ret = nonterminal_funs[nonterminal][bs.rule_idx](params.reverse()) + var to_ret = nonterminal_funs[nonterminal][bs.rule_idx].second(nonterminal_funs[nonterminal][bs.rule_idx].first, params.reverse()) return to_ret } } @@ -265,7 +271,7 @@ fun bs(nonterminal: int, rule_idx: int, idx_into_rule: int, left: int, pivot: in var to_ret.construct(nonterminal, rule_idx, idx_into_rule, left, pivot, right): BS return to_ret } -fun fungll(grammer: ref Grammer, input: ref str): set { +fun fungll(grammer: ref Grammer, input: ref str): set { var R = descend(grammer, grammer.start_symbol, 0) var U = set() var G = map, set>() @@ -301,13 +307,13 @@ fun fungll(grammer: ref Grammer, input: ref str): set { } return Y } -fun descend(grammer: ref Grammer, symbol: int, l: int): set { +fun descend(grammer: ref Grammer, symbol: int, l: int): set { var to_ret = set() for (var rhs = 0; rhs < grammer.get_nonterminal_rules(symbol).size; rhs++;) to_ret.add(descriptor(symbol, rhs, 0, l, l)) return to_ret } -fun process(grammer: ref Grammer, input: ref str, descript: Descriptor, G: ref map, set>, P: ref map, set>): triple, set>, map, set>, map, set>> { +fun process(grammer: ref Grammer, input: ref str, descript: Descriptor, G: ref map, set>, P: ref map, set>): triple, set>, map, set>, map, set>> { // if at end / end is emptystr if descript.idx_into_rule == grammer.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx].size { return process_e(grammer, descript, G, P) @@ -315,7 +321,7 @@ fun process(grammer: ref Grammer, input: ref str, descript: Descriptor, G: return process_symbol(grammer, input, descript, G, P) } } -fun process_e(grammer: ref Grammer, descript: Descriptor, G: ref map, set>, P: ref map, set>): triple, set>, map, set>, map, set>> { +fun process_e(grammer: ref Grammer, descript: Descriptor, G: ref map, set>, P: ref map, set>): triple, set>, map, set>, map, set>> { var nonterminal: int var rule_idx: int var left: int @@ -332,7 +338,7 @@ fun process_e(grammer: ref Grammer, descript: Descriptor, G: ref map, set>(), map(make_pair(X,l), set(k))) } -fun process_symbol(grammer: ref Grammer, input: ref str, descript: Descriptor, G: ref map, set>, P: ref map, set>): triple, set>, map, set>, map, set>> { +fun process_symbol(grammer: ref Grammer, input: ref str, descript: Descriptor, G: ref map, set>, P: ref map, set>): triple, set>, map, set>, map, set>> { var s = grammer.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule] var k = descript.pivot var R = P.get_with_default(make_pair(s,k), set()) @@ -345,7 +351,7 @@ fun process_symbol(grammer: ref Grammer, input: ref str, descript: Descrip return make_triple(skip(k,pending(descript.nonterminal, descript.rule_idx, descript.idx_into_rule+1, descript.left), R), Gp, map, set>()) } } -fun matc(grammer: ref Grammer, input: ref str, descript: Descriptor): pair, set> { +fun matc(grammer: ref Grammer, input: ref str, descript: Descriptor): pair, set> { /*println("trying to match " + grammer.to_string(grammer.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule]))*/ var match_length = grammer.match_terminal(grammer.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule], input, descript.pivot) if match_length > 0 { diff --git a/k_prime.krak b/k_prime.krak index 22b7f0d..e71e7e6 100644 --- a/k_prime.krak +++ b/k_prime.krak @@ -39,7 +39,7 @@ fun get_map(m: MalValue): map { } error("can't get_map not a map") } -fun read_str(grammer: ref Grammer, s: str): MalResult { +fun read_str(grammer: ref Grammer, s: str): MalResult { var BSR = fungll(grammer, s) var success = false for (var i = 0; i < BSR.data.size; i++;) { @@ -654,7 +654,7 @@ fun pr_str(v: MalValue, print_readably: bool): str { error("can't print") } -fun READ(grammer: ref Grammer, s: str): MalResult { +fun READ(grammer: ref Grammer, s: str): MalResult { return read_str(grammer, s) } @@ -901,7 +901,7 @@ fun PRINT(v: MalValue): str { return pr_str(v, true) } -fun rep(grammer: ref Grammer, env: *Env, a: str): str { +fun rep(grammer: ref Grammer, env: *Env, a: str): str { var read = READ(grammer, a) if is_err(read) { return PRINT(get_err(read)) @@ -927,21 +927,21 @@ fun print_wrapper(params: vec, sep: *char, print_readably: bool): str fun main(argc: int, argv: **char): int { - var grammer.construct(): Grammer + var grammer.construct(): Grammer - var ret_nil_term: fun(ref str, int, int): MalResult = fun(input: ref str, l: int, r: int): MalResult { return MalResult::Ok(MalValue::Nil()); } - var ret_nil_sym: fun(ref vec): MalResult = fun(x: ref vec): MalResult { return MalResult::Ok(MalValue::Nil()); } - var ret_0_sym: fun(ref vec): MalResult = fun(x: ref vec): MalResult { return x[0]; } + var ret_nil_term: fun(ref MalValue, ref str, int, int): MalResult = fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { return MalResult::Ok(MalValue::Nil()); } + var ret_nil_sym: fun(ref MalValue, ref vec): MalResult = fun(_: ref MalValue, x: ref vec): MalResult { return MalResult::Ok(MalValue::Nil()); } + var ret_0_sym: fun(ref MalValue, ref vec): MalResult = fun(_: ref MalValue, x: ref vec): MalResult { return x[0]; } var WS = grammer.add_new_nonterminal("WS", vec(grammer.add_terminal("( |,| | |(;[ -~]* -))+", ret_nil_term)), ret_nil_sym) - var optional_WS = grammer.add_new_nonterminal("optional_WS", vec(), ret_nil_sym) - grammer.add_to_nonterminal(optional_WS, vec(WS), ret_nil_sym) +))+", MalValue::Nil(), ret_nil_term)), MalValue::Nil(), ret_nil_sym) + var optional_WS = grammer.add_new_nonterminal("optional_WS", vec(), MalValue::Nil(), ret_nil_sym) + grammer.add_to_nonterminal(optional_WS, vec(WS), MalValue::Nil(), ret_nil_sym) - var atom = grammer.add_new_nonterminal("atom", vec(grammer.add_terminal("-?[0-9]+", fun(input: ref str, l: int, r: int): MalResult { return MalResult::Ok(MalValue::Int(string_to_num(input.slice(l,r)))); })), ret_0_sym) + var atom = grammer.add_new_nonterminal("atom", vec(grammer.add_terminal("-?[0-9]+", MalValue::Nil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { return MalResult::Ok(MalValue::Int(string_to_num(input.slice(l,r)))); })), MalValue::Nil(), ret_0_sym) grammer.add_to_nonterminal(atom, vec(grammer.add_terminal("\"([#-[]| |[]-~]|(\\\\)|(\\n)|(\\t)|(\\\*)|(\\0)| -|[ -!]|(\\\\\"))*\"", fun(input: ref str, l: int, r: int): MalResult { +|[ -!]|(\\\\\"))*\"", MalValue::Nil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { var to_ret = str() for (var i = l+1; i < r-1; i++;) { if input[i] == '\\' { @@ -960,9 +960,8 @@ fun main(argc: int, argv: **char): int { } /*return MalResult::Ok(MalValue::String(input.slice(l+1,r-1)));*/ return MalResult::Ok(MalValue::String(to_ret)); - })), fun(x: ref vec): MalResult { return x[0]; }) //" - /*grammer.add_to_nonterminal(atom, vec(grammer.add_terminal("([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|'|<|>)*", fun(input: ref str, l: int, r: int): MalResult { return MalResult::Ok(MalValue::Symbol(input.slice(l,r))); })), ret_0_sym)*/ - grammer.add_to_nonterminal(atom, vec(grammer.add_terminal("([a-z]|[A-Z]|_|\\*|\\?|\\+|-|!|=|&|<|>)([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|<|>)*", fun(input: ref str, l: int, r: int): MalResult { + })), MalValue::Nil(), ret_0_sym) //" + grammer.add_to_nonterminal(atom, vec(grammer.add_terminal("-|(([a-z]|[A-Z]|_|\\*|\\?|\\+|!|=|&|<|>)([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|<|>)*)", MalValue::Nil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { var s = input.slice(l,r) if s == "true" { return MalResult::Ok(MalValue::True()); @@ -973,17 +972,17 @@ fun main(argc: int, argv: **char): int { } else { return MalResult::Ok(MalValue::Symbol(input.slice(l,r))); } - })), ret_0_sym) - grammer.add_to_nonterminal(atom, vec(grammer.add_terminal(":([a-z]|[A-Z]|_)([a-z]|[A-Z]|_|[0-9])*", fun(input: ref str, l: int, r: int): MalResult { return MalResult::Ok(MalValue::Keyword(input.slice(l,r))); })), ret_0_sym) + })), MalValue::Nil(), ret_0_sym) + grammer.add_to_nonterminal(atom, vec(grammer.add_terminal(":([a-z]|[A-Z]|_)([a-z]|[A-Z]|_|[0-9])*", MalValue::Nil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { return MalResult::Ok(MalValue::Keyword(input.slice(l,r))); })), MalValue::Nil(), ret_0_sym) - var form = grammer.add_new_nonterminal("form", vec(atom), ret_0_sym) - var space_forms = grammer.add_new_nonterminal("space_forms", vec(form), fun(x: ref vec): MalResult { + var form = grammer.add_new_nonterminal("form", vec(atom), MalValue::Nil(), ret_0_sym) + var space_forms = grammer.add_new_nonterminal("space_forms", vec(form), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[0]) { return x[0] } return MalResult::Ok(MalValue::List(vec(get_value(x[0])))) }) - grammer.add_to_nonterminal(space_forms, vec(form, WS, space_forms), fun(x: ref vec): MalResult { + grammer.add_to_nonterminal(space_forms, vec(form, WS, space_forms), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[0]) { return x[0] } @@ -993,23 +992,23 @@ fun main(argc: int, argv: **char): int { return MalResult::Ok(MalValue::List(vec(get_value(x[0])) + get_list(get_value(x[2])))) }) - grammer.add_to_nonterminal(form, vec(grammer.add_terminal("\\(", ret_nil_term), + grammer.add_to_nonterminal(form, vec(grammer.add_terminal("\\(", MalValue::Nil(), ret_nil_term), optional_WS, space_forms, optional_WS, - grammer.add_terminal("\\)", ret_nil_term)), fun(x: ref vec): MalResult { return x[2]; }) - grammer.add_to_nonterminal(form, vec(grammer.add_terminal("\\[", ret_nil_term), + grammer.add_terminal("\\)", MalValue::Nil(), ret_nil_term)), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { return x[2]; }) + grammer.add_to_nonterminal(form, vec(grammer.add_terminal("\\[", MalValue::Nil(), ret_nil_term), optional_WS, space_forms, optional_WS, - grammer.add_terminal("]", ret_nil_term)), fun(x: ref vec): MalResult { + grammer.add_terminal("]", MalValue::Nil(), ret_nil_term)), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[2]) { return x[2] } return MalResult::Ok(MalValue::Vector(get_list(get_value(x[2])))) }) - var doubled_space_forms = grammer.add_new_nonterminal("doubled_space_forms", vec(form, WS, form), fun(x: ref vec): MalResult { + var doubled_space_forms = grammer.add_new_nonterminal("doubled_space_forms", vec(form, WS, form), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[0]) { return x[0] } @@ -1018,7 +1017,7 @@ fun main(argc: int, argv: **char): int { } return MalResult::Ok(MalValue::List(vec(get_value(x[0]), get_value(x[2])))) }) - grammer.add_to_nonterminal(doubled_space_forms, vec(form, WS, form, WS, doubled_space_forms), fun(x: ref vec): MalResult { + grammer.add_to_nonterminal(doubled_space_forms, vec(form, WS, form, WS, doubled_space_forms), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[0]) { return x[0] } @@ -1030,11 +1029,11 @@ fun main(argc: int, argv: **char): int { } return MalResult::Ok(MalValue::List(vec(get_value(x[0]), get_value(x[2])) + get_list(get_value(x[4])))) }) - grammer.add_to_nonterminal(form, vec(grammer.add_terminal("{", ret_nil_term), + grammer.add_to_nonterminal(form, vec(grammer.add_terminal("{", MalValue::Nil(), ret_nil_term), optional_WS, doubled_space_forms, optional_WS, - grammer.add_terminal("}", ret_nil_term)), fun(x: ref vec): MalResult { + grammer.add_terminal("}", MalValue::Nil(), ret_nil_term)), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[2]) { return x[2] } @@ -1046,31 +1045,31 @@ fun main(argc: int, argv: **char): int { } return MalResult::Ok(MalValue::Map(to_ret)) }) - grammer.add_to_nonterminal(form, vec(grammer.add_terminal("@", ret_nil_term), form), fun(x: ref vec): MalResult { + grammer.add_to_nonterminal(form, vec(grammer.add_terminal("@", MalValue::Nil(), ret_nil_term), form), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[1]) { return x[1] } return MalResult::Ok(MalValue::List(vec(MalValue::Symbol(str("deref")), get_value(x[1])))) }) - grammer.add_to_nonterminal(form, vec(grammer.add_terminal("'", ret_nil_term), form), fun(x: ref vec): MalResult { + grammer.add_to_nonterminal(form, vec(grammer.add_terminal("'", MalValue::Nil(), ret_nil_term), form), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[1]) { return x[1] } return MalResult::Ok(MalValue::List(vec(MalValue::Symbol(str("deref")), get_value(x[1])))) }) - grammer.add_to_nonterminal(form, vec(grammer.add_terminal("`", ret_nil_term), form), fun(x: ref vec): MalResult { + grammer.add_to_nonterminal(form, vec(grammer.add_terminal("`", MalValue::Nil(), ret_nil_term), form), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[1]) { return x[1] } return MalResult::Ok(MalValue::List(vec(MalValue::Symbol(str("deref")), get_value(x[1])))) }) - grammer.add_to_nonterminal(form, vec(grammer.add_terminal("~", ret_nil_term), form), fun(x: ref vec): MalResult { + grammer.add_to_nonterminal(form, vec(grammer.add_terminal("~", MalValue::Nil(), ret_nil_term), form), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[1]) { return x[1] } return MalResult::Ok(MalValue::List(vec(MalValue::Symbol(str("deref")), get_value(x[1])))) }) - grammer.add_to_nonterminal(form, vec(grammer.add_terminal("~@", ret_nil_term),form), fun(x: ref vec): MalResult { + grammer.add_to_nonterminal(form, vec(grammer.add_terminal("~@", MalValue::Nil(), ret_nil_term),form), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { if is_err(x[1]) { return x[1] } @@ -1317,7 +1316,7 @@ fun main(argc: int, argv: **char): int { })); env->set(str("first"), make_builtin_function(fun(params: vec): MalResult { if params.size != 1 || !is_list_or_vec(params[0]) { - return MalResult::Err(MalValue::String(str("first called with wrong number or type of params"))) + return MalResult::Err(MalValue::String(str("first called with wrong number or type of params") + pr_str(params[0], true))) } else { var list = get_list_or_vec(params[0]) if list.size == 0 { @@ -1533,6 +1532,61 @@ fun main(argc: int, argv: **char): int { env->set(str("conj"), make_builtin_function(fun(params: vec): MalResult { return MalResult::Err(MalValue::String(str("not implemented"))) })); + // self-modifying grammer + env->set(str("add_terminal"), make_builtin_function(fun(params: vec): MalResult { + if params.size != 2 || !is_string(params[0]) { + return MalResult::Err(MalValue::String(str("add_terminal called with wrong number or type of params"))) + } else { + return MalResult::Ok(MalValue::Int(grammer.add_terminal(get_string(params[0]), params[1], fun(f: ref MalValue, input: ref str, l: int, r: int): MalResult { + return function_call(f, vec(MalValue::String(input.slice(l,r)))) + }))) + } + })); + var call_for_sym = fun(f: ref MalValue, x: ref vec): MalResult { + var params = vec() + for (var i = 0; i < x.size; i++;) { + if is_err(x[i]) { + return x[i] + } + params.add(get_value(x[i])) + } + return function_call(f, vec(MalValue::List(params))) + } + env->set(str("add_new_nonterminal"), make_builtin_function(fun(params: vec): MalResult { + if params.size != 3 || !is_string(params[0]) || !is_list_or_vec(params[1]) { + return MalResult::Err(MalValue::String(str("add_new_nonterminal called with wrong number or type of params"))) + } else { + var rule = get_list(params[1]) + var int_rule = vec() + for (var i = 0; i < rule.size; i++;) { + if !is_int(rule[i]) { + return MalResult::Err(MalValue::String(str("add_new_nonterminal called with bad rule"))) + } + int_rule.add(get_int(rule[i])) + } + return MalResult::Ok(MalValue::Int(grammer.add_new_nonterminal(get_string(params[0]), int_rule, params[2], call_for_sym))) + } + })); + env->set(str("add_to_nonterminal"), make_builtin_function(fun(params: vec): MalResult { + if params.size != 3 || (!is_int(params[0]) && !is_string(params[0])) || !is_list_or_vec(params[1]) { + return MalResult::Err(MalValue::String(str("add_to_nonterminal called with wrong number or type of params"))) + } else { + var rule = get_list(params[1]) + var int_rule = vec() + for (var i = 0; i < rule.size; i++;) { + if !is_int(rule[i]) { + return MalResult::Err(MalValue::String(str("add_to_nonterminal called with bad rule"))) + } + int_rule.add(get_int(rule[i])) + } + if is_int(params[0]) { + grammer.add_to_nonterminal(get_int(params[0]), int_rule, params[2], call_for_sym) + } else { + grammer.add_to_nonterminal(get_string(params[0]), int_rule, params[2], call_for_sym) + } + return MalResult::Ok(MalValue::Nil()) + } + })); rep(grammer, env, str("(def! not (fn* (a) (if a false true)))")) rep(grammer, env, str("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \" \\nnil)\")))))")) rep(grammer, env, str("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"))