var editor=element("editor"); /* -------------------------------------------------------------------------- */ function div_id(id,cs) { return node("div",{id:id},cs); } function div_class(cls,cs) { return node("div",{"class":cls},cs); } function a(url,linked) { return node("a",{href:url},linked); } function ul(lis) { return node("ul",{},lis); } function li(xs) { return node("li",{},xs); } function table(rows) { return node("table",{},rows); } function td_right(cs) { return node("td",{"class":"right"},cs); } function jsurl(js) { return "javascript:"+js; } function insertAfter(el,ref) { ref.parentNode.insertBefore(el,ref.nextSibling); } /* -------------------------------------------------------------------------- */ function initial_view() { var current=local.get("current"); if(current>0) open_grammar(current-1); else draw_grammar_list(); //debug(local.get("dir","no server directory yet")); } function draw_grammar_list() { local.put("current",0); editor.innerHTML=""; editor.appendChild(node("h3",{},[text("Your grammars")])); var gs=ul([]); function del(i) { return function () { delete_grammar(i); } } for(var i=0;i0 && !local.get(local.count-1)) local.count--; initial_view(); } } function open_grammar(i) { var g=local.get(i); g.index=i; local.put("current",i+1); edit_grammar(g); } function close_grammar(g) { save_grammar(g); draw_grammar_list(); } function reload_grammar(g) { save_grammar(g); edit_grammar(g); } function save_grammar(g) { if(g.index==null) g.index=local.count++; local.put(g.index,g); } function edit_grammar(g) { editor.innerHTML=""; editor.appendChild(draw_grammar(g)); } function draw_grammar(g) { var files=div_class("files",[draw_filebar(g),draw_file(g)]); return div_class("grammar",[draw_namebar(g,files),files]) } function draw_namebar(g,files) { return div_class("namebar", [table([tr([td(draw_name(g)), td_right([draw_plainbutton(g,files), upload_button(g), draw_closebutton(g)])])])]) } function draw_name(g) { return editable("h3",text(g.basename),g,edit_name,"Rename grammar"); } function draw_closebutton(g) { var b=button("X",function(){close_grammar(g);}); b.title="Save and Close this grammar"; return b; } function draw_plainbutton(g,files) { var b2; function show_editor() { edit_grammar(g); } function show_plain() { files.innerHTML="
"+show_grammar(g)+"
" b.style.display="none"; if(b2) b2.style.display=""; else { b2=button("Show editor",show_editor); insertAfter(b2,b); } } var b=button("Show plain",show_plain); b.title="Show plain text representaiton of the grammar"; return b; } function upload_button(g) { var b=button("Upload",function(){upload(g);}); b.title="Upload the grammar to the server to check it in GF and test it in the minibar"; return b; } function lang(code,name) { return { code:code, name:name} } function lang1(name) { var ws=name.split("/"); return ws.length==1 ? lang(name.substr(0,3),name) : lang(ws[0],ws[1]); } var languages = map(lang1,"Amharic Arabic Bulgarian Catalan Danish Dutch English Finnish French German Hindi Ina/Interlingua Italian Latin Norwegian Polish Ron/Romanian Russian Spanish Swedish Thai Turkish Urdu".split(" ")); //languages.push(lang("Other","Other")); var langname={}; //for(var i=0;i=ci) g.current--; reload_grammar(g); } } function draw_filebar(g) { var cur=(g.current||0)-1; var filebar = empty_class("tr","extensible") filebar.appendChild(gap()); filebar.appendChild( tab(cur== -1,button("Abstract",function(){open_abstract(g);}))); var cs=g.concretes; function del(ci) { return function() { delete_concrete(g,ci); }} function open_conc(i) { return function() {open_concrete(g,1*i); }} // for(var i=0;i0 // && g.current<=g.concretes.length ? draw_concrete(g,g.current-1) : draw_abstract(g); } function draw_startcat(g) { var abs=g.abstract; var startcat = abs.startcat || abs.cats[0]; function opt(cat) { return option(cat,cat); } var m= node("select",{},map(opt,abs.cats)); m.value=startcat; m.onchange=function() { abs.startcat=m.value; save_grammar(g); } return indent([kw("flags startcat"),sep(" = "),m]); } function draw_abstract(g) { var kw_cat = kw("cat"); kw_cat.title = "The categories (nonterminals) of the grammar are enumerated here."; var kw_fun = kw("fun"); kw_fun.title = "The functions (productions) of the grammar are enumerated here."; var flags=g.abstract.startcat || g.abstract.cats.length>1 ? draw_startcat(g) : text(""); return div_id("file", [kw("abstract "),ident(g.basename),sep(" = "), flags, indent([extensible([kw_cat, indent(draw_cats(g))]), extensible([kw_fun, indent(draw_funs(g))])])]); } function add_cat(g,el) { function add(s) { var cats=s.split(/\s*(?:\s|[;])\s*/); // allow separating spaces or ";" if(cats.length>0 && cats[cats.length-1]=="") cats.pop(); for(var i in cats) { var err=check_name(cats[i],"Category"); if(err) return err; } for(var i in cats) g.abstract.cats.push(cats[i]); reload_grammar(g); return null; } string_editor(el,"",add); } function delete_ix(old,ix) { var a=[]; // for(var i=0;i0) el.appendChild(sep(" → ")); el.appendChild(check(t[i],ident(t[i]))); } return el; } function edit_name(g,el) { function change_name(name) { if(name!=g.basename && name!="") { var err=check_name(name,"Grammar"); if(err) return err; g.basename=name reload_grammar(g); } return null; } string_editor(el,g.basename,change_name) } /* -------------------------------------------------------------------------- */ function draw_concrete(g,i) { var conc=g.concretes[i]; return div_id("file", [kw("concrete "),ident(g.basename+conc.langcode), kw(" of "),ident(g.basename),sep(" = "), indent([extensible([kw("param"),draw_params(g,i)])]), indent([kw("lincat"),draw_lincats(g,i)]), indent([extensible([kw("oper"),draw_opers(g,i)])]), indent([kw("lin"),draw_lins(g,i)]) ]) } function draw_param(p,dp) { function check(el) { return ifError(dp[p.name],"Same parameter type defined twice",el); } return node("span",{},[check(ident(p.name)),sep(" = "),text(p.rhs)]); } function add_param(g,ci,el) { function add(s) { var p=parse_param(s); if(p.ok) { g.concretes[ci].params.push(p.ok); reload_grammar(g); return null; } else return p.error } string_editor(el,"",add); } function edit_param(ci,i) { return function (g,el) { function replace(s) { var p=parse_param(s); if(p.ok) { g.concretes[ci].params[i]=p.ok; reload_grammar(g); return null; } else return p.error; } string_editor(el,show_param(g.concretes[ci].params[i]),replace); } } function delete_param(g,ci,ix) { with(g.concretes[ci]) params=delete_ix(params,ix); reload_grammar(g); } function draw_params(g,ci) { var conc=g.concretes[ci]; conc.params || (conc.params=[]); var params=conc.params; var es=[]; var dp={}; function del(i) { return function() { delete_param(g,ci,i); }} function draw_eparam(i,dp) { return editable("span",draw_param(params[i],dp),g,edit_param(ci,i),"Edit this parameter type"); } for(var i in params) { es.push(div_class("param",[deletable(del(i),draw_eparam(i,dp),"Delete this parameter type")])); dp[params[i].name]=true; } es.push(more(g,function(g,el) { return add_param(g,ci,el)}, "Add a new parameter type")); return indent(es); } function delete_lincat(g,ci,cat) { var i; var c=g.concretes[ci]; for(i=0;i1 ? n+(++use[n]) : n; } return map(unique,names); } function draw_lins(g,i) { var conc=g.concretes[i]; function edit(f) { return function(g,el) { function ok(s) { if(f.template) conc.lins.push({fun:f.fun,args:f.args,lin:s}); else f.lin=s; reload_grammar(g); return null; } string_editor(el,f.lin,ok) } } function del(fun) { return function () { delete_lin(g,i,fun); } } function dl(f,cls) { var l=[ident(f.fun)] for(var i in f.args) { l.push(text(" ")); l.push(ident(f.args[i])); } l.push(sep(" = ")); var t=editable("span",text(f.lin),g,edit(f),"Edit lin for "+f.fun); l.push(t); return node("span",{"class":cls},l); } var df=defined_funs(g); function draw_lin(f) { var fun=f.fun; var err= !df[fun]; var l= err ? deletable(del(fun),dl(f,"lin"),"Delete this function") : dl(f,"lin") var l=ifError(err,"Function "+fun+" is not part of the abstract syntax",l); delete df[fun]; return wrap("div",l); } function largs(f) { var funs=g.abstract.funs; for(var i=0;i10) i.size=init.length+5; var e=node("form",{}, [i, node("input",{type:"submit",value:"OK"},[]), button("Cancel",restore), text(" "), m]) e.onsubmit=done start(""); } function ifError(b,msg,el) { return b ? inError(msg,el) : el; } function inError(msg,el) { return node("span",{"class":"inError",title:msg},[el]); } function kw(txt) { return wrap_class("span","kw",text(txt)); } function sep(txt) { return wrap_class("span","sep",text(txt)); } function ident(txt) { return wrap_class("span","ident",text(txt)); } function indent(cs) { return div_class("indent",cs); } function extensible(cs) { return div_class("extensible",cs); } function more(g,action,hint) { var b=node("span",{"class":"more","title":hint || "Add more"}, [text(" + ")]); b.onclick=function() { action(g,b); } return b; } function editable(tag,cs,g,f,hint) { var b=edit_button(function(){f(g,e)},hint); var e=node(tag,{"class":"editable"},[cs,b]); return e; } function edit_button(action,hint) { var b=node("span",{"class":"edit","title":hint || "Edit"},[text("%")]); b.onclick=action; return b; } function deletable(del,el,hint) { var b=node("span",{"class":"delete",title:hint || "Delete"},[text("×")]) b.onclick=del; return node("span",{"class":"deletable"},[b,el]) } function touch_edit() { var b=node("input",{type:"checkbox"},[]); function touch() { document.body.className=b.checked ? "nohover" : "hover"; } b.onchange=touch; insertAfter(b,editor); insertAfter(wrap("small",text("Enable editing on touch devices. ")),b); } /* --- Initialization ------------------------------------------------------- */ //document.body.appendChild(empty_id("div","debug")); initial_view(); touch_edit();