diff --git a/src/www/gfse/editor.css b/src/www/gfse/editor.css index dc7180c33..9ef8259a3 100644 --- a/src/www/gfse/editor.css +++ b/src/www/gfse/editor.css @@ -22,7 +22,7 @@ div.files { margin: 0 8px 8px 8px; position: relative; } div#file, table.extension td, table.extension th { border: 2px solid #009; } div#file { border-top-width: 0; } pre.plain { border: 2px solid #009; } -div#file, pre.plain { background: white; padding: 0.6ex; } +div#file, pre.plain, table.matrixview td { background: white; padding: 0.6ex; } table.extension { border-collapse: collapse; background: white; } table.extension td, table.extension th { padding: 1ex; } @@ -87,6 +87,8 @@ table.tabs td.inactive { border-top-color: #66c; border-left-color: #66c; border-right-color: #66c; } +table.matrixview th { background: #cef; color: #009; } + table.tabs td.gap { border-top-width: 0; border-left-width: 0; border-right-width: 0; } diff --git a/src/www/gfse/editor.js b/src/www/gfse/editor.js index 8f8d3354d..b724f420e 100644 --- a/src/www/gfse/editor.js +++ b/src/www/gfse/editor.js @@ -137,7 +137,6 @@ function edit_grammar(g) { replaceChildren(editor,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]) @@ -150,10 +149,11 @@ function draw_namebar(g,files) { var mb=minibar_button(g,files,err_ind,cb); var qb=quiz_button(g,err_ind); //var pb=draw_plainbutton(g,files); + var mxb=draw_matrixbutton(g,files) var xb=draw_closebutton(g); return div_class("namebar", [table([tr([td(draw_name(g)), - td_right([err_ind,cb,mb,qb/*,pb*/,xb])])])]) + td_right([err_ind,cb,mb,qb/*,pb*/,mxb,xb])])])]) } function draw_name(g) { @@ -183,6 +183,24 @@ function draw_plainbutton(g,files) { return b; } +function draw_matrixbutton(g,files) { + var b2; + function show_editor() { edit_grammar(g); } + function show_matrix() { + clear(files) + files.appendChild(draw_matrix(g)) + b.style.display="none"; + if(b2) b2.style.display=""; + else { + b2=button("Show editor",show_editor); + insertAfter(b2,b); + } + } + var b=button("Matrix view",show_matrix); + b.title="Show matrix view of the grammar"; + return b; +} + function show_compile_error(res,err_ind) { var dst=compiler_output replaceInnerHTML(err_ind,res.errorcode=="OK" @@ -1285,6 +1303,54 @@ function draw_lins(g,ci) { ls.push(dtmpl(f)); return indent_sortable(ls,sort_lins); } +/* -------------------------------------------------------------------------- */ + +function draw_matrix(g) { + var row=[th(text("Abstract"))] + var t=empty_class("table","matrixview") + for(var ci in g.concretes) + row.push(th(text(concname(g.concretes[ci].langcode)))) + t.appendChild(tr(row)) + + var dc=defined_cats(g); + var df=inherited_funs(g); + + for(var i in g.abstract.cats) { + var cat=g.abstract.cats[i] + var row=[td(ident(cat))] + for(var ci in g.concretes) { + var conc=g.concretes[ci] + row.push(td(text(cat_lincat(conc,cat)))) + } + t.appendChild(tr(row)) + } + for(var i in g.abstract.funs) { + var fun=g.abstract.funs[i] + var row=[td(draw_fun(g,fun,dc,df))] + for(var ci in g.concretes) { + var conc=g.concretes[ci] + var lin=fun_lin(conc,fun.name) + var dl=lin ? simple_draw_lin(lin) : text(" ") + row.push(td(dl)) + } + t.appendChild(tr(row)) + } + return t +} + +function simple_draw_lin(f) { + var l=[] + if(f.args.length>0) { + l.push(sep("\\")) /* λ */ + for(var i in f.args) { + l.push(text(" ")); + l.push(ident(f.args[i])); + } + l.push(sep(" → ")); + } + l.push(text_ne(f.lin)); + return wrap("span",l); +} /* -------------------------------------------------------------------------- */ diff --git a/src/www/gfse/gf_abs.js b/src/www/gfse/gf_abs.js index 30f852196..caa83fa90 100644 --- a/src/www/gfse/gf_abs.js +++ b/src/www/gfse/gf_abs.js @@ -20,9 +20,9 @@ type Concrete = { langcode: Id, params: [{name: Id, rhs: String}], lincats : [{ cat: Cat, type: Term}], opers: [{name: Lhs, rhs: Term}], - lins: [{fun: FunId, args: [Id], lin: Term}] + lins: [Lin] } - +type Lin = {fun: FunId, args: [Id], lin: Term} type Lhs = String -- name and type of oper, -- e.g "regN : Str -> { s:Str,g:Gender} =" @@ -85,6 +85,13 @@ function cat_lincat(conc,cat) { return null; } +// Return the lin defined in a given concrete syntax for an abstract function +// cat_lincat :: Concrete -> FunId -> Lin +function fun_lin(conc,fun) { + with(conc) for(var i in lins) if(lins[i].fun==fun) return lins[i] + return null; +} + // Return the index of the concrete syntax with a given langcode // conc_index :: Grammar -> Id -> Int function conc_index(g,langcode) {