SELF MODIFYING GRAMMER WORKS!

This commit is contained in:
Nathan Braswell
2020-03-29 22:07:55 -04:00
parent 40f0125ed1
commit a811b28bc1
2 changed files with 114 additions and 54 deletions

View File

@@ -7,12 +7,12 @@ import str:*
import regex:*
// nonterminals are negative, terminals are positive
obj Grammer<T> (Object) {
obj Grammer<T,K> (Object) {
var nonterminals: vec<vec<vec<int>>>
var nonterminal_names: vec<str>
var nonterminal_funs: vec<vec<fun(ref vec<T>): T>>
var nonterminal_funs: vec<vec<pair<K,fun(ref K, ref vec<T>): T>>>
var terminals: vec<regex>
var terminal_funs: vec<fun(ref str,int,int): T>
var terminal_funs: vec<pair<K,fun(ref K,ref str,int,int): T>>
var start_symbol: int
fun construct(): *Grammer {
nonterminals.construct()
@@ -42,22 +42,28 @@ obj Grammer<T> (Object) {
destruct()
copy_construct(&other)
}
fun add_new_nonterminal(name: *char, rule: ref vec<int>, f: fun(ref vec<T>): T): int {
return add_new_nonterminal(str(name), rule, f)
fun add_new_nonterminal(name: *char, rule: ref vec<int>, d: K, f: fun(ref K,ref vec<T>): T): int {
return add_new_nonterminal(str(name), rule, d, f)
}
fun add_new_nonterminal(name: ref str, rule: ref vec<int>, f: fun(ref vec<T>): T): int {
fun add_new_nonterminal(name: ref str, rule: ref vec<int>, d: K, f: fun(ref K,ref vec<T>): 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<int>, f: fun(ref vec<T>): T) {
nonterminals[(-1*nonterminal)-1].add(rule)
nonterminal_funs[(-1*nonterminal)-1].add(f)
fun add_to_nonterminal(nonterminal: ref str, rule: ref vec<int>, d: K, f: fun(ref K,ref vec<T>): 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<int>, d: K, f: fun(ref K,ref vec<T>): 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<vec<int>> {
@@ -119,7 +125,7 @@ obj Grammer<T> (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<T> (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<T>(grammer: ref Grammer<T>, input: ref str): set<BS> {
fun fungll<T,K>(grammer: ref Grammer<T,K>, input: ref str): set<BS> {
var R = descend(grammer, grammer.start_symbol, 0)
var U = set<Descriptor>()
var G = map<pair<int, int>, set<Pending>>()
@@ -301,13 +307,13 @@ fun fungll<T>(grammer: ref Grammer<T>, input: ref str): set<BS> {
}
return Y
}
fun descend<T>(grammer: ref Grammer<T>, symbol: int, l: int): set<Descriptor> {
fun descend<T,K>(grammer: ref Grammer<T,K>, symbol: int, l: int): set<Descriptor> {
var to_ret = set<Descriptor>()
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<T>(grammer: ref Grammer<T>, input: ref str, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
fun process<T,K>(grammer: ref Grammer<T,K>, input: ref str, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
// 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<T>(grammer: ref Grammer<T>, input: ref str, descript: Descriptor, G:
return process_symbol(grammer, input, descript, G, P)
}
}
fun process_e<T>(grammer: ref Grammer<T>, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
fun process_e<T,K>(grammer: ref Grammer<T,K>, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
var nonterminal: int
var rule_idx: int
var left: int
@@ -332,7 +338,7 @@ fun process_e<T>(grammer: ref Grammer<T>, descript: Descriptor, G: ref map<pair<
}
return make_triple(make_pair(R,Y), map<pair<int, int>, set<Pending>>(), map(make_pair(X,l), set(k)))
}
fun process_symbol<T>(grammer: ref Grammer<T>, input: ref str, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
fun process_symbol<T,K>(grammer: ref Grammer<T,K>, input: ref str, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
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<int>())
@@ -345,7 +351,7 @@ fun process_symbol<T>(grammer: ref Grammer<T>, 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<pair<int,int>, set<int>>())
}
}
fun matc<T>(grammer: ref Grammer<T>, input: ref str, descript: Descriptor): pair<set<Descriptor>, set<BS>> {
fun matc<T,K>(grammer: ref Grammer<T,K>, input: ref str, descript: Descriptor): pair<set<Descriptor>, set<BS>> {
/*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 {

View File

@@ -39,7 +39,7 @@ fun get_map(m: MalValue): map<MalValue, MalValue> {
}
error("can't get_map not a map")
}
fun read_str(grammer: ref Grammer<MalResult>, s: str): MalResult {
fun read_str(grammer: ref Grammer<MalResult,MalValue>, 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<MalResult>, s: str): MalResult {
fun READ(grammer: ref Grammer<MalResult, MalValue>, 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<MalResult>, env: *Env, a: str): str {
fun rep(grammer: ref Grammer<MalResult, MalValue>, 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<MalValue>, sep: *char, print_readably: bool): str
fun main(argc: int, argv: **char): int {
var grammer.construct(): Grammer<MalResult>
var grammer.construct(): Grammer<MalResult, MalValue>
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>): MalResult = fun(x: ref vec<MalResult>): MalResult { return MalResult::Ok(MalValue::Nil()); }
var ret_0_sym: fun(ref vec<MalResult>): MalResult = fun(x: ref vec<MalResult>): 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>): MalResult = fun(_: ref MalValue, x: ref vec<MalResult>): MalResult { return MalResult::Ok(MalValue::Nil()); }
var ret_0_sym: fun(ref MalValue, ref vec<MalResult>): MalResult = fun(_: ref MalValue, x: ref vec<MalResult>): 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<int>(), 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<int>(), 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<int>(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<int>(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>): 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>): 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>): 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>): MalResult {
grammer.add_to_nonterminal(space_forms, vec(form, WS, space_forms), MalValue::Nil(), fun(_: ref MalValue, x: ref vec<MalResult>): 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>): 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>): 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>): MalResult {
grammer.add_terminal("]", MalValue::Nil(), ret_nil_term)), MalValue::Nil(), fun(_: ref MalValue, x: ref vec<MalResult>): 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>): 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>): 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>): 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>): 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>): MalResult {
grammer.add_terminal("}", MalValue::Nil(), ret_nil_term)), MalValue::Nil(), fun(_: ref MalValue, x: ref vec<MalResult>): 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>): 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>): 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>): 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>): 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>): 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>): 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>): 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>): 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>): 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>): 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<MalValue>): 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<MalValue>): MalResult {
return MalResult::Err(MalValue::String(str("not implemented")))
}));
// self-modifying grammer
env->set(str("add_terminal"), make_builtin_function(fun(params: vec<MalValue>): 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>): MalResult {
var params = vec<MalValue>()
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<MalValue>): 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<int>()
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<MalValue>): 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<int>()
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)))))))"))