@builtin "whitespace.ne"
@builtin "string.ne"
@builtin "number.ne"

@{%
function de_array(d) {
    if (d.length > 1) {
        throw Error("You can't de_array list with more than one elem!")
    }
    return d[0];
}

function remove_null(d) {
    return d.filter(elem => elem !== null);
}

function json_obj_processor(d) {
    let pairs = [d[2]];
    for (let more of d[3]) {
        pairs.push(more[1]);
    }
    
    let ret = {};
    for(let p of pairs) {
        ret[p.pk] = p.pv;
    }
    
    return ret;
}

function json_arr_parser(d) {
    let obj_list = [d[2]];
    for(let more of d[3]) {
        obj_list.push(more[1]);
    }
    
    return obj_list;
}
%}


json -> json_obj {% de_array %} | json_list {% de_array %} | json_bool {% de_array %} | json_number {% de_array %} | json_str {% de_array %}


# json obj

json_obj -> 
    _ "{" _ "}" _ {% d => { return {}; }%}
    | _ "{" pair ("," pair):* "}" _ {% json_obj_processor %}

pair -> _ key _ ":" _ value _ {% d => {return {"pk": d[1], "pv": d[5]};} %}

key -> dqstring {% de_array %}
value -> json {% de_array %}


# json list

json_list -> 
    _ "[" _ "]" _ {% d => {return [];} %} | 
    _ "[" json ("," json):* "]" _ {% json_arr_parser %}


# basic elements

json_bool -> "true" | "false" {% de_array %}
json_str -> dqstring {% de_array %}
json_number -> decimal {% de_array %}