/* Abstract syntax for a small subset of GF grammars in JavaScript */ function defined_cats(g) { var dc={}; with(g.abstract) for(var i in cats) dc[cats[i]]=true; return dc; } function defined_funs(g) { var df={}; with(g.abstract) for(var i in funs) df[funs[i].name]=true; return df; } // Return the type of a named function in the abstract syntax function function_type(g,fun) { with(g.abstract) for(var i in funs) if(funs[i].name==fun) return funs[i].type return null; } // Return the lincat defined in a given concrete syntax for an abstract category function cat_lincat(conc,cat) { with(conc) for(var i in lincats) if(lincats[i].cat==cat) return lincats[i].type return null; } // Return the index of the concrete syntax with a given langcode function conc_index(g,langcode) { var c=g.concretes; for(var ix=0;ix ... -> Tn */ var state="name"; var ok=true; for(var i=0;ok && i": ok=ws[i]=="->"; state="type"; break; } } } var err=check_name(fun.name,"Function"); if(err) return {error: err}; return ok && state=="->" ? {ok:fun} : { error : "Fun : Cat1 -> ... -> Catn" } } function parse_param(s) { var ws=s.split("="); if(ws.length==2) { var name=ws[0].trim(); var err=check_name(name,"Parameter type"); return err ? { error:err } : { ok: { name:name,rhs:ws[1].trim() } } } else return { error: "P = C1 | ... | Cn" } } function parse_oper(s) { var i=s.indexOf(" "); var operr = { error: "op = expr" } if(i>0 && i0) s+=" -> "; s+=t[i]; } return s; } function show_fun(fun) { return fun.name+" : "+show_type(fun.type); } function show_grammar(g) { return show_abstract(g)+"\n"+show_concretes(g) } function show_abstract(g) { // var startcat= g.abstract.cats.length==1 ? g.abstract.cats[0] : g.abstract.startcat; var startcat= g.abstract.startcat || g.abstract.cats[0]; return "abstract "+g.basename+" = {\n\n" +"flags coding = utf8 ;\n\n" +show_startcat(startcat) +show_cats(g.abstract.cats) +show_funs(g.abstract.funs) +"}\n"; } function show_startcat(startcat) { return startcat ? "flags startcat = "+startcat+";\n\n" : ""; } function show_cats(cats) { return cats.length>0 ? "cat\n "+cats.join("; ")+";\n\n" : ""; } function show_funs(funs) { return show_list("fun",show_fun,funs); } function show_concretes(g) { return map(show_concrete(g.basename),g.concretes).join("\n\n"); } function show_concrete(basename) { return function(conc) { return "--# -path=.:present\n" + "concrete "+basename+conc.langcode+" of "+basename+" =" +show_opens(conc.opens) +" {\n\nflags coding = utf8 ;\n\n" +show_params(conc.params) +show_lincats(conc.lincats) +show_opers(conc.opers) +show_lins(conc.lins) +"}\n" } } function show_list(kw,show1,list) { return list.length>0 ? kw+"\n "+map(show1,list).join(";\n ")+";\n\n" : "" } function show_opens(opens) { return opens && opens.length>0 ? "\n\nopen "+opens.join(", ")+" in" : "" } function show_params(params) { return show_list("param",show_param,params); } function show_lincats(lincats) { return show_list("lincat",show_lincat,lincats); } function show_opers(opers) { return show_list("oper",show_oper,opers); } function show_lins(lins) { return show_list("lin",show_lin,lins); } function show_param(p) { return p.name + " = " + p.rhs; } function show_oper(p) { return p.name + " " + p.rhs; } function show_lincat(p) { return p.cat + " = " + p.type; } function show_lin(lin) { return lin.fun + " " + lin.args.join(" ")+ " = " + lin.lin; }