summaryrefslogtreecommitdiff
path: root/src/www/gfse/gf_abs.js
diff options
context:
space:
mode:
authorhallgren <hallgren@chalmers.se>2012-02-09 18:00:36 +0000
committerhallgren <hallgren@chalmers.se>2012-02-09 18:00:36 +0000
commit9dfab3d1878b96dc138387adb5ef3df593dff29e (patch)
tree9b1ec3f424d9bfcb998933d7c5d3f82e90bf0a93 /src/www/gfse/gf_abs.js
parent7787c5d725bcd7c593d749364c5d4c9d12578571 (diff)
gfse: initial support for module extension
There is a new way to create a new grammar based on an existing grammar: by extending it. (It is also possible to clone an existing grammar, a before.)
Diffstat (limited to 'src/www/gfse/gf_abs.js')
-rw-r--r--src/www/gfse/gf_abs.js82
1 files changed, 57 insertions, 25 deletions
diff --git a/src/www/gfse/gf_abs.js b/src/www/gfse/gf_abs.js
index 953a69683..e4829548a 100644
--- a/src/www/gfse/gf_abs.js
+++ b/src/www/gfse/gf_abs.js
@@ -2,20 +2,25 @@
/*
type Id = String -- all sorts of identifiers
+type ModId = Id -- module name
type Cat = Id -- category name
+type FunId = Id -- function name
type Type = [Cat] -- [Cat_1,...,Cat_n] means Cat_1 -> ... -> Cat_n
-type Grammar = { basename: Id, abstract : Abstract, concretes : [Concrete] }
+type Grammar = { basename: ModId,
+ extends: [ModId],
+ abstract: Abstract,
+ concretes: [Concrete] }
-type Abstract = { startcat: Cat, cats : [Cat], funs : [ Fun ] }
-type Fun = { name:Id, type : Type }
+type Abstract = { startcat: Cat, cats: [Cat], funs: [Fun] }
+type Fun = { name: FunId, type: Type }
-type Concrete = { langcode:Id,
- opens:[Id],
- params: [{name:Id, rhs:String}],
- lincats : [{ cat:Cat, type:Term}],
- opers: [{name:Lhs, rhs:Term}],
- lins: [{fun:Id, args:[Id], lin:Term}]
+type Concrete = { langcode: Id,
+ opens: [ModId],
+ params: [{name: Id, rhs: String}],
+ lincats : [{ cat: Cat, type: Term}],
+ opers: [{name: Lhs, rhs: Term}],
+ lins: [{fun: FunId, args: [Id], lin: Term}]
}
@@ -24,24 +29,42 @@ type Lhs = String -- name and type of oper,
type Term = String -- arbitrary GF term (not parsed by the editor)
*/
-// defined_cats :: [Grammar] -> {Cat=>Bool}
-function defined_cats(g) {
- var dc={};
+// locally_defined_cats :: Grammar -> {Cat=>Bool} -> {Cat=>Bool} // destr upd
+function locally_defined_cats(g,dc) {
with(g.abstract)
- for(var i in cats) dc[cats[i]]=true;
+ for(var i in cats) dc[cats[i]]=g.basename;
return dc;
}
-// defined_funs :: [Grammar] -> {Id=>Bool}
-function defined_funs(g) {
- var df={};
+// all_defined_cats :: Grammar -> [Grammar] -> {Cat=>Bool}
+function all_defined_cats(g,igs) {
+ return all_inherited_cats(igs,locally_defined_cats(g,{}))
+}
+// all_inherited_cats :: [Grammar] -> {Cat=>Bool} -> {Cat=>Bool} // destr upd
+function all_inherited_cats(igs,dc) {
+ for(var i in igs) dc=locally_defined_cats(igs[i],dc)
+ return dc;
+}
+
+// locally_defined_funs :: [Grammar] -> {FunId=>ModId} -> {Id=>ModId} // destr upd
+function locally_defined_funs(g,df) {
with(g.abstract)
- for(var i in funs) df[funs[i].name]=true;
+ for(var i in funs) df[funs[i].name]=g.basename;
+ return df;
+}
+
+// all_defined_funs :: Grammar -> [Grammar] -> {FunId=>ModId}
+function all_defined_funs(g,igs) {
+ return all_inherited_funs(igs,locally_defined_funs(g,{}))
+}
+// all_inherited_funs :: [Grammar] -> {FunId=>ModId} -> {FunId=>ModId} // destr upd
+function all_inherited_funs(igs,df) {
+ for(var i in igs) df=locally_defined_funs(igs[i],df)
return df;
}
// Return the type of a named function in the abstract syntax
-// function_type :: Grammar -> Id -> Type
+// function_type :: Grammar -> FunId -> Type
function function_type(g,fun) {
with(g.abstract)
for(var i in funs) if(funs[i].name==fun) return funs[i].type
@@ -187,7 +210,7 @@ function parse_oper(s) {
}
-/* --- Print as plain text (normal GF concrete syntax) ---------------------- */
+/* --- Print as plain text (normal GF source syntax) ------------------------- */
function show_type(t) {
var s="";
@@ -209,7 +232,9 @@ function show_grammar(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"
+ return "abstract "+g.basename+" = "
+ +show_extends(g.extends)
+ +"{\n\n"
+"flags coding = utf8 ;\n\n"
+show_startcat(startcat)
+show_cats(g.abstract.cats)
@@ -217,6 +242,10 @@ function show_abstract(g) {
+"}\n";
}
+function show_extends(exts) {
+ return exts && exts.length>0 ? exts.join(", ")+" ** " : "";
+}
+
function show_startcat(startcat) {
return startcat ? "flags startcat = "+startcat+";\n\n" : "";
}
@@ -228,15 +257,18 @@ function show_cats(cats) {
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");
+ return map(show_concrete(g),g.concretes).join("\n\n");
}
-function show_concrete(basename) {
+function conc_extends(conc) { return function(m) { return m+conc.langcode; }}
+
+function show_concrete(g) {
return function(conc) {
return "--# -path=.:present\n"
- + "concrete "+basename+conc.langcode+" of "+basename+" ="
+ + "concrete "+g.basename+conc.langcode+" of "+g.basename+" = "
+ +show_extends((g.extends || []).map(conc_extends(conc)))
+show_opens(conc.opens)
- +" {\n\nflags coding = utf8 ;\n\n"
+ +"{\n\nflags coding = utf8 ;\n\n"
+show_params(conc.params)
+show_lincats(conc.lincats)
+show_opers(conc.opers)
@@ -252,7 +284,7 @@ function show_list(kw,show1,list) {
}
function show_opens(opens) {
- return opens && opens.length>0 ? "\n\nopen "+opens.join(", ")+" in" : ""
+ return opens && opens.length>0 ? "\n\nopen "+opens.join(", ")+" in " : ""
}
function show_params(params) { return show_list("param",show_param,params); }