1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00

Source: Restore broken commit

This commit is contained in:
gnosygnu
2017-02-06 22:14:55 -05:00
parent 938beac9f9
commit 3bfeb94b43
4380 changed files with 328018 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.gfml; import gplx.*;
import gplx.core.texts.*; /*CharStream*/
public interface GfmlLxr extends Gfo_evt_itm {
String Key();
String[] Hooks();
GfmlTkn CmdTkn();
void CmdTkn_set(GfmlTkn val); // needed for lxr pragma
GfmlTkn MakeTkn(CharStream stream, int hookLength);
GfmlLxr SubLxr();
void SubLxr_Add(GfmlLxr... lexer);
}
class GfmlLxrRegy {
public int Count() {return hash.Count();}
public void Add(GfmlLxr lxr) {hash.Add(lxr.Key(), lxr);}
public GfmlLxr Get_by(String key) {return (GfmlLxr)hash.Get_by(key);}
Hash_adp hash = Hash_adp_.New();
}

View File

@@ -0,0 +1,217 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.gfml; import gplx.*;
import gplx.core.strings.*;
import gplx.core.texts.*; /*CharStream*/
public class GfmlLxr_ {
public static GfmlLxr general_(String key, GfmlTkn protoTkn) {return GfmlLxr_general.new_(key, protoTkn);}
public static GfmlLxr solo_(String key, GfmlTkn singletonTkn) {return GfmlLxr_singleton.new_(key, singletonTkn.Raw(), singletonTkn);}
public static GfmlLxr range_(String key, String[] ary, GfmlTkn protoTkn, boolean ignoreOutput) {return GfmlLxr_group.new_(key, ary, protoTkn, ignoreOutput);}
@gplx.Internal protected static GfmlLxr symbol_(String key, String raw, String val, GfmlBldrCmd cmd) {
GfmlTkn tkn = GfmlTkn_.singleton_(key, raw, val, cmd);
return GfmlLxr_.solo_(key, tkn);
}
@gplx.Internal protected static GfmlLxr frame_(String key, GfmlFrame frame, String bgn, String end) {return GfmlLxr_frame.new_(key, frame, bgn, end, GfmlBldrCmd_pendingTkns_add.Instance, GfmlBldrCmd_frameEnd.data_());}
public static final GfmlLxr Null = new GfmlLxr_null();
public static final String CmdTknChanged_evt = "Changed";
public static GfmlLxr as_(Object obj) {return obj instanceof GfmlLxr ? (GfmlLxr)obj : null;}
public static GfmlLxr cast(Object obj) {try {return (GfmlLxr)obj;} catch(Exception exc) {throw Err_.new_type_mismatch_w_exc(exc, GfmlLxr.class, obj);}}
}
class GfmlLxr_null implements GfmlLxr {
public String Key() {return "gfml.nullLxr";}
public Gfo_evt_mgr Evt_mgr() {if (evt_mgr == null) evt_mgr = new Gfo_evt_mgr(this); return evt_mgr;} Gfo_evt_mgr evt_mgr;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return Gfo_invk_.Rv_unhandled;}
public GfmlTkn CmdTkn() {return GfmlTkn_.Null;} public void CmdTkn_set(GfmlTkn val) {}
public String[] Hooks() {return String_.Ary_empty;}
public GfmlTkn MakeTkn(CharStream stream, int hookLength) {return GfmlTkn_.Null;}
public void SubLxr_Add(GfmlLxr... lexer) {}
public GfmlLxr SubLxr() {return this;}
}
class GfmlLxr_singleton implements GfmlLxr, Gfo_evt_itm {
public Gfo_evt_mgr Evt_mgr() {if (evt_mgr == null) evt_mgr = new Gfo_evt_mgr(this); return evt_mgr;} Gfo_evt_mgr evt_mgr;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return Gfo_invk_.Rv_unhandled;}
public String Key() {return key;} private String key;
public GfmlTkn CmdTkn() {return singletonTkn;} GfmlTkn singletonTkn;
public void CmdTkn_set(GfmlTkn val) {
String oldRaw = singletonTkn.Raw();
singletonTkn = val;
hooks = String_.Ary(val.Raw());
Gfo_evt_mgr_.Pub_vals(this, GfmlLxr_.CmdTknChanged_evt, Keyval_.new_("old", oldRaw), Keyval_.new_("new", val.Raw()), Keyval_.new_("lxr", this));
}
public String[] Hooks() {return hooks;} private String[] hooks;
public GfmlTkn MakeTkn(CharStream stream, int hookLength) {
stream.MoveNextBy(hookLength);
return singletonTkn;
}
public GfmlLxr SubLxr() {return subLxr;} GfmlLxr subLxr;
public void SubLxr_Add(GfmlLxr... lexer) {subLxr.SubLxr_Add(lexer);}
public static GfmlLxr_singleton new_(String key, String hook, GfmlTkn singletonTkn) {
GfmlLxr_singleton rv = new GfmlLxr_singleton();
rv.ctor_(key, hook, singletonTkn, GfmlLxr_.Null);
return rv;
} protected GfmlLxr_singleton() {}
@gplx.Internal protected void ctor_(String key, String hook, GfmlTkn singletonTkn, GfmlLxr subLxr) {
this.key = key;
this.hooks = String_.Ary(hook);
this.subLxr = subLxr;
this.singletonTkn = singletonTkn;
}
}
class GfmlLxr_group implements GfmlLxr {
public String Key() {return key;} private String key;
public Gfo_evt_mgr Evt_mgr() {if (evt_mgr == null) evt_mgr = new Gfo_evt_mgr(this); return evt_mgr;} Gfo_evt_mgr evt_mgr;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return Gfo_invk_.Rv_unhandled;}
public GfmlTkn CmdTkn() {return outputTkn;} public void CmdTkn_set(GfmlTkn val) {} GfmlTkn outputTkn;
public String[] Hooks() {return trie.Symbols();}
public GfmlTkn MakeTkn(CharStream stream, int hookLength) {
while (stream.AtMid()) {
if (!ignoreOutput)
sb.Add_mid(stream.Ary(), stream.Pos(), hookLength);
stream.MoveNextBy(hookLength);
String found = String_.cast(trie.FindMatch(stream));
if (found == null) break;
hookLength = trie.LastMatchCount;
}
if (ignoreOutput) return GfmlTkn_.IgnoreOutput;
String raw = sb.To_str_and_clear();
return outputTkn.MakeNew(raw, raw);
}
public GfmlLxr SubLxr() {throw Err_sublxr();}
public void SubLxr_Add(GfmlLxr... lexer) {throw Err_sublxr();}
Err Err_sublxr() {return Err_.new_unimplemented_w_msg("group lxr does not have subLxrs", "key", key, "output_tkn", outputTkn.Raw()).Trace_ignore_add_1_();}
GfmlTrie trie = GfmlTrie.new_(); String_bldr sb = String_bldr_.new_(); boolean ignoreOutput;
public static GfmlLxr_group new_(String key, String[] hooks, GfmlTkn outputTkn, boolean ignoreOutput) {
GfmlLxr_group rv = new GfmlLxr_group();
rv.key = key;
for (String hook : hooks)
rv.trie.Add(hook, hook);
rv.outputTkn = outputTkn; rv.ignoreOutput = ignoreOutput;
return rv;
} GfmlLxr_group() {}
}
class GfmlLxr_general implements GfmlLxr, Gfo_invk {
public Gfo_evt_mgr Evt_mgr() {if (evt_mgr == null) evt_mgr = new Gfo_evt_mgr(this); return evt_mgr;} Gfo_evt_mgr evt_mgr;
public String Key() {return key;} private String key;
public GfmlTkn CmdTkn() {return txtTkn;} public void CmdTkn_set(GfmlTkn val) {} GfmlTkn txtTkn;
public String[] Hooks() {return symTrie.Symbols();}
public GfmlTkn MakeTkn(CharStream stream, int firstTknLength) {
GfmlTkn rv = null;
if (symLxr != null) { // symLxr has something; produce
rv = MakeTkn_symLxr(stream);
if (rv != GfmlTkn_.IgnoreOutput) return rv;
}
while (stream.AtMid()) { // keep moving til (a) symChar or (b) endOfStream
Object result = symTrie.FindMatch(stream);
symTknLen = symTrie.LastMatchCount;
if (result == null) { // no match; must be txtChar;
txtBfr.Add(stream);
stream.MoveNext();
}
else { // symChar
symLxr = (GfmlLxr)result; // set symLxr for next pass
if (txtBfr.Has()) // txtBfr has something: gen txtTkn
rv = txtBfr.MakeTkn(stream, txtTkn);
else { // txtBfr empty: gen symbol
rv = MakeTkn_symLxr(stream);
if (rv == GfmlTkn_.IgnoreOutput) continue;
}
return rv;
}
}
if (txtBfr.Has()) // endOfStream, but txtBfr has chars
return txtBfr.MakeTkn(stream, txtTkn);
return GfmlTkn_.EndOfStream;
}
public void SubLxr_Add(GfmlLxr... lxrs) {
for (GfmlLxr lxr : lxrs) {
for (String hook : lxr.Hooks())
symTrie.Add(hook, lxr);
Gfo_evt_mgr_.Sub_same(lxr, GfmlLxr_.CmdTknChanged_evt, this);
}
}
public GfmlLxr SubLxr() {return this;}
GfmlTkn MakeTkn_symLxr(CharStream stream) {
GfmlLxr lexer = symLxr; symLxr = null;
int length = symTknLen; symTknLen = 0;
return lexer.MakeTkn(stream, length);
}
GfmlLxr_general_txtBfr txtBfr = new GfmlLxr_general_txtBfr(); GfmlTrie symTrie = GfmlTrie.new_(); GfmlLxr symLxr; int symTknLen;
@gplx.Internal protected static GfmlLxr_general new_(String key, GfmlTkn txtTkn) {
GfmlLxr_general rv = new GfmlLxr_general();
rv.key = key; rv.txtTkn = txtTkn;
return rv;
} protected GfmlLxr_general() {}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, GfmlLxr_.CmdTknChanged_evt)) {
symTrie.Del(m.ReadStr("old"));
symTrie.Add(m.ReadStr("new"), m.CastObj("lxr"));
}
else return Gfo_invk_.Rv_unhandled;
return this;
}
}
class GfmlLxr_general_txtBfr {
public int Bgn = NullPos;
public int Len;
public boolean Has() {return Bgn != NullPos;}
public void Add(CharStream stream) {
if (Bgn == NullPos) Bgn = stream.Pos();
Len++;
} static final int NullPos = -1;
public GfmlTkn MakeTkn(CharStream stream, GfmlTkn textTkn) {
String raw = String_.new_charAry_(stream.Ary(), Bgn, Len);
Bgn = -1; Len = 0;
return textTkn.MakeNew(raw, raw);
}
}
class GfmlLxr_frame extends GfmlLxr_singleton { GfmlFrame frame; GfmlLxr endLxr, txtLxr;
public void BgnRaw_set(String val) {// needed for lxr pragma
GfmlBldrCmd_frameBgn bgnCmd = GfmlBldrCmd_frameBgn.new_(frame, txtLxr);
GfmlTkn bgnTkn = GfmlTkn_.singleton_(this.Key() + "_bgn", val, GfmlTkn_.NullVal, bgnCmd);
this.CmdTkn_set(bgnTkn);
}
public void EndRaw_set(String val) {// needed for lxr pragma
GfmlBldrCmd_frameEnd endCmd = GfmlBldrCmd_frameEnd.data_();
GfmlTkn endTkn = GfmlTkn_.singleton_(this.Key() + "_end", val, GfmlTkn_.NullVal, endCmd);
endLxr.CmdTkn_set(endTkn);
}
public static GfmlLxr new_(String key, GfmlFrame frame, String bgn, String end, GfmlBldrCmd txtCmd, GfmlBldrCmd endCmd) {
GfmlLxr_frame rv = new GfmlLxr_frame();
GfmlTkn txtTkn = frame.FrameType() == GfmlFrame_.Type_comment
? GfmlTkn_.valConst_(key + "_txt", GfmlTkn_.NullVal, txtCmd)
: GfmlTkn_.cmd_(key + "_txt", txtCmd)
;
GfmlLxr txtLxr = GfmlLxr_.general_(key + "_txt", txtTkn);
GfmlTkn bgnTkn = GfmlTkn_.singleton_(key + "_bgn", bgn, GfmlTkn_.NullVal, GfmlBldrCmd_frameBgn.new_(frame, txtLxr));
rv.ctor_(key, bgn, bgnTkn, txtLxr);
GfmlTkn endTkn = GfmlTkn_.singleton_(key + "_end", end, GfmlTkn_.NullVal, endCmd);
GfmlLxr endLxr = GfmlLxr_.solo_(key + "_end", endTkn);
rv.SubLxr_Add(endLxr);
rv.frame = frame;
rv.endLxr = endLxr;
rv.txtLxr = txtLxr;
return rv;
} GfmlLxr_frame() {}
public static GfmlLxr_frame as_(Object obj) {return obj instanceof GfmlLxr_frame ? (GfmlLxr_frame)obj : null;}
public static GfmlLxr_frame cast(Object obj) {try {return (GfmlLxr_frame)obj;} catch(Exception exc) {throw Err_.new_type_mismatch_w_exc(exc, GfmlLxr_frame.class, obj);}}
}

View File

@@ -0,0 +1,29 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.gfml; import gplx.*;
public interface GfmlObj {
int ObjType();
}
class GfmlObj_ {
public static final int
Type_tkn = 1
, Type_atr = 2
, Type_nde = 3
, Type_prg = 4
;
}

View File

@@ -0,0 +1,25 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.gfml; import gplx.*;
public class GfmlObjList extends List_adp_base {
@gplx.New public GfmlObj Get_at(int idx) {return (GfmlObj)Get_at_base(idx);}
public void Add(GfmlObj tkn) {Add_base(tkn);}
public void Add_at(GfmlObj tkn, int idx) {super.AddAt_base(idx, tkn);}
public void Del(GfmlObj tkn) {Del_base(tkn);}
public static GfmlObjList new_() {return new GfmlObjList();} GfmlObjList() {}
}

View File

@@ -0,0 +1,46 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.gfml; import gplx.*;
import gplx.core.strings.*;
public interface GfmlTkn extends GfmlObj {
String TknType();
String Raw();
String Val();
GfmlTkn[] SubTkns();
GfmlBldrCmd Cmd_of_Tkn();
GfmlTkn MakeNew(String raw, String val);
}
class GfmlTknAry_ {
public static final GfmlTkn[] Empty = new GfmlTkn[0];
public static GfmlTkn[] ary_(GfmlTkn... ary) {return ary;}
@gplx.Internal protected static String XtoRaw(GfmlTkn[] ary) {
String_bldr sb = String_bldr_.new_();
for (GfmlTkn tkn : ary)
sb.Add(tkn.Raw());
return sb.To_str();
}
@gplx.Internal protected static String XtoVal(GfmlTkn[] ary) {return XtoVal(ary, 0, ary.length);}
static String XtoVal(GfmlTkn[] ary, int bgn, int end) {
String_bldr sb = String_bldr_.new_();
for (int i = bgn; i < end; i++) {
GfmlTkn tkn = ary[i];
sb.Add(tkn.Val());
}
return sb.To_str();
}
}

View File

@@ -0,0 +1,65 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.gfml; import gplx.*;
public class GfmlTkn_ {
@gplx.Internal protected static final String NullRaw = "", NullVal = ""; static final String Type_base = "gfml.baseTkn";
@gplx.Internal protected static final GfmlTkn
Null = new GfmlTkn_base().ctor_GfmlTkn_base("gfml.nullTkn", NullRaw, NullVal, GfmlBldrCmd_.Null)
, EndOfStream = GfmlTkn_.raw_("<<End Of Stream>>")
, IgnoreOutput = GfmlTkn_.raw_("<<Ignore Output>>");
public static GfmlTkn as_(Object obj) {return obj instanceof GfmlTkn ? (GfmlTkn)obj : null;}
@gplx.Internal protected static GfmlTkn new_(String raw, String val) {return new GfmlTkn_base().ctor_GfmlTkn_base(Type_base, raw, val, GfmlBldrCmd_.Null);}
public static GfmlTkn raw_(String raw) {return new GfmlTkn_base().ctor_GfmlTkn_base(Type_base, raw, raw, GfmlBldrCmd_.Null);}
@gplx.Internal protected static GfmlTkn val_(String val) {return new GfmlTkn_base().ctor_GfmlTkn_base(Type_base, NullRaw, val, GfmlBldrCmd_.Null);}
@gplx.Internal protected static GfmlTkn cmd_(String tknType, GfmlBldrCmd cmd) {return new GfmlTkn_base().ctor_GfmlTkn_base(tknType, NullRaw, NullVal, cmd);}
@gplx.Internal protected static GfmlTkn valConst_(String tknType, String val, GfmlBldrCmd cmd) {return new GfmlTkn_valConst().ctor_GfmlTkn_base(tknType, GfmlTkn_.NullRaw, val, cmd);}
@gplx.Internal protected static GfmlTkn singleton_(String tknType, String raw, String val, GfmlBldrCmd cmd) {return new GfmlTkn_singleton().ctor_GfmlTkn_base(tknType, raw, val, cmd);}
@gplx.Internal protected static GfmlTkn composite_(String tknType, GfmlTkn[] ary) {return new GfmlTkn_composite(tknType, ary);}
@gplx.Internal protected static GfmlTkn composite_list_(String tknType, GfmlObjList list) {
GfmlTkn[] ary = new GfmlTkn[list.Count()];
for (int i = 0; i < list.Count(); i++)
ary[i] = (GfmlTkn)list.Get_at(i);
return GfmlTkn_.composite_(tknType, ary);
}
}
class GfmlTkn_base implements GfmlTkn {
public int ObjType() {return GfmlObj_.Type_tkn;}
public String TknType() {return tknType;} private String tknType;
public String Raw() {return raw;} private String raw;
public String Val() {return val;} private String val;
public GfmlBldrCmd Cmd_of_Tkn() {return cmd;} GfmlBldrCmd cmd;
public GfmlTkn[] SubTkns() {return GfmlTknAry_.Empty;}
@gplx.Virtual public GfmlTkn MakeNew(String rawNew, String valNew) {return new GfmlTkn_base().ctor_GfmlTkn_base(tknType, rawNew, valNew, cmd);}
@gplx.Internal protected GfmlTkn_base ctor_GfmlTkn_base(String tknType, String raw, String val, GfmlBldrCmd cmd) {this.tknType = tknType; this.raw = raw; this.val = val; this.cmd = cmd; return this;}
}
class GfmlTkn_valConst extends GfmlTkn_base {
@Override public GfmlTkn MakeNew(String rawNew, String valNew) {return new GfmlTkn_base().ctor_GfmlTkn_base(this.TknType(), rawNew, this.Val(), this.Cmd_of_Tkn());}
}
class GfmlTkn_singleton extends GfmlTkn_base {
@Override public GfmlTkn MakeNew(String rawNew, String valNew) {return this;}
}
class GfmlTkn_composite implements GfmlTkn {
public int ObjType() {return GfmlObj_.Type_tkn;}
public String TknType() {return tknType;} private String tknType;
public String Raw() {return GfmlTknAry_.XtoRaw(ary);}
public String Val() {return GfmlTknAry_.XtoVal(ary);}
public GfmlBldrCmd Cmd_of_Tkn() {return GfmlBldrCmd_.Null;}
public GfmlTkn[] SubTkns() {return ary;} GfmlTkn[] ary;
public GfmlTkn MakeNew(String rawNew, String valNew) {throw Err_.new_unimplemented_w_msg(".MakeNew cannot be invoked on GfmlTkn_composite (raw is available, but not val)", "tknType", tknType, "rawNew", rawNew, "valNew", valNew);}
@gplx.Internal protected GfmlTkn_composite(String tknType, GfmlTkn[] ary) {this.tknType = tknType; this.ary = ary;}
}

View File

@@ -0,0 +1,114 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.gfml; import gplx.*;
import gplx.core.texts.*; /*CharStream*/
public class GfmlTrie {
public String[] Symbols() {
String[] rv = new String[symbols.Count()];
for (int i = 0; i < rv.length; i++)
rv[i] = String_.cast(symbols.Get_at(i));
return rv;
} Ordered_hash symbols = Ordered_hash_.New();
public int LastMatchCount; // PERF: prop is faster than method
public Object FindMatch(CharStream stream) {
Object result = null; int moveCount = 0; LastMatchCount = 0;
IntObjHash_base link = rootLink;
while (stream.AtMid()) {
Object found = link.Get_by(stream.Cur());
if (found == null) break; // found is null; can happen for false matches; ex: <!-- reg, and <!-* is cur; goes to <!- before exit
LastMatchCount++;
IntObjHash_base foundAsLink = IntObjHash_base_.as_(found);
if (foundAsLink != null) { // if (found is link) (ie: another link exists)
result = foundAsLink.Bay(); // set .Bay as possible result; needed for short-long pairs; ex: < and <!-- exist; < found, but need to check next symbol for !
link = foundAsLink; // make foundAsLink the current one
moveCount++;
stream.MoveNext();
}
else { // not a link; must be last
result = found;
break;
}
}
if (moveCount > 0) stream.MoveBackBy(moveCount); // restore stream to original position; imitate idempotency
return result;
}
public void Add(String symbol, Object data) {
if (data == null) throw Err_.new_wo_type("null objects cannot be registered", "symbol", symbol);
char[] ary = String_.XtoCharAry(symbol); int lastIndex = ary.length - 1;
IntObjHash_base curLink = rootLink;
for (int i = 0; i < ary.length; i++) {
char c = ary[i];
Object found = curLink.Get_by(c);
IntObjHash_base foundAsLink = IntObjHash_base_.as_(found);
if (i == lastIndex) { // lastChar
if (found != null) { // slot is occupied
if (foundAsLink != null) // found is link; occurs when symbol is shorter than existing: ex: adding '<' when '<!--' exists)
foundAsLink.Bay_set(data); // place found in link's bay
else // found is makr; occurs when symbol is the same as existing; ex: adding '<!' when '<!' exists
curLink.Set(c, data); // place found in slot (replaces slot)
}
else // slot is unoccupied
curLink.Add(c, data); // place found in slot
}
else { // not lastChar
if (foundAsLink == null) { // next link does not exist (NOTE: next link is necessary, since char is not lastChar)
foundAsLink = IntObjHash_base_.new_(); // create next link
if (found != null) { // slot is occupied; occurs when symbol is longer than existing: ex: adding '<!--' when '<' exists
foundAsLink.Bay_set(found); // transplant occupied found to link's Bay
curLink.Set(c, foundAsLink); // place new link in slot
}
else // slot is unoccupied
curLink.Add(c, foundAsLink); // place found in slot
}
curLink = foundAsLink;
}
}
symbols.Add_if_dupe_use_nth(symbol, symbol);
}
public void Del(String symbol) {
char[] ary = String_.XtoCharAry(symbol); int lastIndex = ary.length - 1;
IntObjHash_base[] linkAry = new IntObjHash_base[ary.length]; // first, get linkAry -- one link for each symbol
IntObjHash_base link = rootLink;
for (int i = 0; i < ary.length; i++) {
char c = ary[i];
linkAry[i] = link;
link = IntObjHash_base_.as_(link.Get_by(c));
if (link == null) break; // c does not have nextHash; break
}
IntObjHash_base nextHash = null;
for (int i = lastIndex; i >= 0; i--) { // remove each char from hashes; must move backwards
char c = ary[i];
IntObjHash_base curLink = linkAry[i];
Object found = curLink.Get_by(c);
IntObjHash_base foundAsLink = IntObjHash_base_.as_(found);
if (nextHash != null && nextHash.Bay() != null) // occurs when long is dropped; ex: '<-' and '<'; '<-' dropped; <'s .Bay in '<-' chain must be transplanted to '<' .Bay
curLink.Set(c, nextHash.Bay());
else if (foundAsLink != null && foundAsLink.Bay() != null) // occurs when short is dropped; ex: '<-' and '<'; '<' dropped; <'s .Bay must be transplanted to '<' .Bay in '<-' chain
foundAsLink.Bay_set(found);
else // no long/short overlap; simply remove
curLink.Del(c);
nextHash = curLink;
}
symbols.Del(symbol);
}
public void Clear() {rootLink.Clear();}
IntObjHash_base rootLink = IntObjHash_base_.new_();
public static GfmlTrie new_() {return new GfmlTrie();}
}

View File

@@ -0,0 +1,77 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.gfml; import gplx.*;
class IntObjHash_base {
public int Count() {return count;} int count;
public boolean Has(int key) {return Get_by(key) != null;}
public Object Get_by(int key) {
if (key < 0) throw Err_.new_wo_type("key must be >= 0", "key", key);
if (key > maxKey) return null;
Object[] subAry = FetchSubAry(key);
return subAry == null ? null : subAry[subIdx];
}
public void Add(int key, Object obj) {PutObjAtKey(key, obj, true);}
public void Set(int key, Object obj) {PutObjAtKey(key, obj, false);}
public void Del(int key) {
if (key > maxKey) return; // key does not exist; exit
Object[] subAry = FetchSubAry(key);
if (subAry == null) return;
subAry[subIdx] = null;
count--;
}
public void Clear() {
rootAry = new Object[0];
count = 0;
maxKey = -1;
}
void PutObjAtKey(int key, Object obj, boolean isAdd) {
if (key < 0) throw Err_.new_wo_type("key must be >= 0", "key", key);
if (obj == null) throw Err_.new_wo_type("Object cannot be null; call .Del on key instead", "key", key);
if (key > maxKey) ExpandRootAry(key);
Object[] subAry = FetchSubAry(key);
if (subAry == null) {
subAry = new Object[subAryLength];
rootAry[rootIdx] = subAry;
}
Object curVal = subAry[subIdx];
if ( isAdd && curVal != null) throw Err_.new_wo_type(".Add cannot be called on non-null vals; call .Set instead", "key", key, "val", curVal);
if (!isAdd && curVal == null) throw Err_.new_wo_type(".Set cannot be called on null vals; call .Add instead", "key", key);
subAry[subIdx] = obj;
if (isAdd) count++;
}
void ExpandRootAry(int key) {
int newRootAryBound = (key / subAryLength) + 1;
Object[] newRootAry = new Object[newRootAryBound];
Array_.Copy(rootAry, newRootAry);
rootAry = newRootAry;
maxKey = (rootAry.length * subAryLength) - 1;
}
Object[] FetchSubAry(int key) {
rootIdx = key / subAryLength;
subIdx = key % subAryLength;
return (Object[])rootAry[rootIdx];
}
Object[] rootAry = new Object[0]; int maxKey = -1;
int rootIdx, subIdx; // NOTE: these are temp values that are cached at class level for PERF (originally out)
public Object Bay() {return bay;} public void Bay_set(Object v) {bay = v;} Object bay = null;
static final int subAryLength = 16;
}
class IntObjHash_base_ {
public static IntObjHash_base new_() {return new IntObjHash_base();}
public static IntObjHash_base as_(Object obj) {return obj instanceof IntObjHash_base ? (IntObjHash_base)obj : null;}
}