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:
214
400_xowa/src/gplx/langs/gfs/Gfs_lxr.java
Normal file
214
400_xowa/src/gplx/langs/gfs/Gfs_lxr.java
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
interface Gfs_lxr {
|
||||
int Lxr_tid();
|
||||
int Process(Gfs_parser_ctx ctx, int bgn, int end);
|
||||
}
|
||||
class Gfs_lxr_whitespace implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_whitespace;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
byte[] src = ctx.Src(); int src_len = ctx.Src_len();
|
||||
int rv = Gfs_lxr_.Rv_eos, cur_pos;
|
||||
for (cur_pos = end; cur_pos < src_len; cur_pos++) {
|
||||
byte b = src[cur_pos];
|
||||
Object o = ctx.Trie().Match_at_w_b0(ctx.Trie_rv(), b, src, cur_pos, src_len);
|
||||
if (o == null) {
|
||||
rv = Gfs_lxr_.Rv_null;
|
||||
ctx.Process_null(cur_pos);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
Gfs_lxr lxr = (Gfs_lxr)o;
|
||||
if (lxr.Lxr_tid() == Gfs_lxr_.Tid_whitespace) {}
|
||||
else {
|
||||
rv = Gfs_lxr_.Rv_lxr;
|
||||
ctx.Process_lxr(cur_pos, lxr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static final Gfs_lxr_whitespace Instance = new Gfs_lxr_whitespace(); Gfs_lxr_whitespace() {}
|
||||
}
|
||||
class Gfs_lxr_comment_flat implements Gfs_lxr {
|
||||
public Gfs_lxr_comment_flat(byte[] bgn_bry, byte[] end_bry) {
|
||||
this.bgn_bry = bgn_bry; this.bgn_bry_len = bgn_bry.length;
|
||||
this.end_bry = end_bry; this.end_bry_len = end_bry.length;
|
||||
} byte[] bgn_bry, end_bry; int bgn_bry_len, end_bry_len;
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_comment;}
|
||||
public int Process(Gfs_parser_ctx ctx, int lxr_bgn, int lxr_end) {
|
||||
byte[] src = ctx.Src(); int src_len = ctx.Src_len();
|
||||
int end_pos = Bry_find_.Find_fwd(src, end_bry, lxr_end, src_len);
|
||||
// if (end_pos == Bry_find_.Not_found) throw Err_.new_fmt_("comment is not closed: {0}", String_.new_u8(end_bry));
|
||||
return (end_pos == Bry_find_.Not_found)
|
||||
? src_len // allow eos to terminate flat comment; needed for "tidy-always-adds-nl-in-textarea" fix; NOTE: DATE:2014-06-21
|
||||
: end_pos + end_bry_len; // position after end_bry
|
||||
}
|
||||
}
|
||||
class Gfs_lxr_identifier implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_identifier;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
byte[] src = ctx.Src(); int src_len = ctx.Src_len();
|
||||
int pos, rv = Gfs_lxr_.Rv_eos;
|
||||
for (pos = end; pos < src_len; pos++) {
|
||||
byte b = src[pos];
|
||||
Object o = ctx.Trie().Match_at_w_b0(ctx.Trie_rv(), b, src, pos, src_len);
|
||||
if (o == null) { // invalid char; stop;
|
||||
rv = Gfs_lxr_.Rv_null;
|
||||
ctx.Process_null(pos);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
Gfs_lxr lxr = (Gfs_lxr)o;
|
||||
if (lxr.Lxr_tid() == Gfs_lxr_.Tid_identifier) {} // still an identifier; continue
|
||||
else { // new lxr (EX: "." in "abc."); (a) hold word of "abc"; mark "." as new lxr;
|
||||
ctx.Hold_word(bgn, pos);
|
||||
rv = Gfs_lxr_.Rv_lxr;
|
||||
ctx.Process_lxr(pos, lxr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rv == Gfs_lxr_.Rv_eos) ctx.Process_eos(); // eos
|
||||
return rv;
|
||||
}
|
||||
public static final Gfs_lxr_identifier Instance = new Gfs_lxr_identifier(); Gfs_lxr_identifier() {}
|
||||
}
|
||||
class Gfs_lxr_semic implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_semic;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
switch (ctx.Prv_lxr()) {
|
||||
case Gfs_lxr_.Tid_identifier: ctx.Make_nde(bgn, end); ctx.Cur_nde_from_stack(); break; // a;
|
||||
case Gfs_lxr_.Tid_quote:
|
||||
case Gfs_lxr_.Tid_paren_end: ctx.Cur_nde_from_stack(); break; // a();
|
||||
case Gfs_lxr_.Tid_semic: break; // a;; ignore;
|
||||
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Semic); break;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
public static final Gfs_lxr_semic Instance = new Gfs_lxr_semic(); Gfs_lxr_semic() {}
|
||||
}
|
||||
class Gfs_lxr_dot implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_dot;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
switch (ctx.Prv_lxr()) {
|
||||
case Gfs_lxr_.Tid_identifier: ctx.Make_nde(bgn, end); break; // a.
|
||||
case Gfs_lxr_.Tid_paren_end: break; // a().
|
||||
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Dot); break;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
public static final Gfs_lxr_dot Instance = new Gfs_lxr_dot(); Gfs_lxr_dot() {}
|
||||
}
|
||||
class Gfs_lxr_paren_bgn implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_paren_bgn;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
switch (ctx.Prv_lxr()) {
|
||||
case Gfs_lxr_.Tid_identifier: ctx.Make_nde(bgn, end); break; // a(;
|
||||
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Paren_bgn); break;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
public static final Gfs_lxr_paren_bgn Instance = new Gfs_lxr_paren_bgn(); Gfs_lxr_paren_bgn() {}
|
||||
}
|
||||
class Gfs_lxr_paren_end implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_paren_end;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
switch (ctx.Prv_lxr()) {
|
||||
case Gfs_lxr_.Tid_paren_bgn:
|
||||
case Gfs_lxr_.Tid_quote: break; // "))", "abc)", "'abc')"
|
||||
case Gfs_lxr_.Tid_identifier: ctx.Make_atr_by_idf(); break; // 123)
|
||||
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Paren_end); break;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
public static final Gfs_lxr_paren_end Instance = new Gfs_lxr_paren_end(); Gfs_lxr_paren_end() {}
|
||||
}
|
||||
class Gfs_lxr_quote implements Gfs_lxr {
|
||||
public Gfs_lxr_quote(byte[] bgn_bry, byte[] end_bry) {
|
||||
this.bgn_bry_len = bgn_bry.length;
|
||||
this.end_bry = end_bry; this.end_bry_len = end_bry.length;
|
||||
} private byte[] end_bry; private int bgn_bry_len, end_bry_len;
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_quote;}
|
||||
public int Process(Gfs_parser_ctx ctx, int lxr_bgn, int lxr_end) {
|
||||
byte[] src = ctx.Src(); int src_len = ctx.Src_len();
|
||||
int end_pos = Bry_find_.Find_fwd(src, end_bry, lxr_end, src_len);
|
||||
if (end_pos == Bry_find_.Not_found) throw Err_.new_wo_type("quote is not closed", "end", String_.new_u8(end_bry));
|
||||
Bry_bfr bfr = ctx.Tmp_bfr().Clear();
|
||||
int prv_pos = lxr_end;
|
||||
int nxt_pos = end_pos + end_bry_len;
|
||||
if (Bry_.Match(src, nxt_pos, nxt_pos + end_bry_len, end_bry)) { // end_bry is doubled; EX: end_bry = ' and raw = a''
|
||||
while (true) {
|
||||
bfr.Add_mid(src, prv_pos, end_pos); // add everything up to end_bry
|
||||
bfr.Add(end_bry); // add end_bry
|
||||
prv_pos = nxt_pos + end_bry_len; // set prv_pos to after doubled end_bry
|
||||
end_pos = Bry_find_.Find_fwd(src, end_bry, prv_pos, src_len);
|
||||
if (end_pos == Bry_find_.Not_found) throw Err_.new_wo_type("quote is not closed", "end", String_.new_u8(end_bry));
|
||||
nxt_pos = end_pos + end_bry_len;
|
||||
if (!Bry_.Match(src, nxt_pos, nxt_pos + end_bry_len, end_bry)) {
|
||||
bfr.Add_mid(src, prv_pos, end_pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx.Make_atr_by_bry(lxr_bgn + bgn_bry_len, end_pos, bfr.To_bry_and_clear());
|
||||
}
|
||||
else
|
||||
ctx.Make_atr(lxr_bgn + bgn_bry_len, end_pos);
|
||||
return end_pos + end_bry_len; // position after quote
|
||||
}
|
||||
}
|
||||
class Gfs_lxr_curly_bgn implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_curly_bgn;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
switch (ctx.Prv_lxr()) {
|
||||
case Gfs_lxr_.Tid_identifier: ctx.Make_nde(bgn, end); ctx.Stack_add(); break; // a{;
|
||||
case Gfs_lxr_.Tid_paren_end: ctx.Stack_add(); break; // a(){; NOTE: node exists but needs to be pushed onto stack
|
||||
default: ctx.Err_mgr().Fail_invalid_lxr(ctx, bgn, this.Lxr_tid(), Byte_ascii.Curly_bgn); break;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
public static final Gfs_lxr_curly_bgn Instance = new Gfs_lxr_curly_bgn(); Gfs_lxr_curly_bgn() {}
|
||||
}
|
||||
class Gfs_lxr_curly_end implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_curly_end;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
ctx.Stack_pop(bgn);
|
||||
return end;
|
||||
}
|
||||
public static final Gfs_lxr_curly_end Instance = new Gfs_lxr_curly_end(); Gfs_lxr_curly_end() {}
|
||||
}
|
||||
class Gfs_lxr_equal implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_eq;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
ctx.Make_nde(bgn, end).Op_tid_(Gfs_nde.Op_tid_assign);
|
||||
return end;
|
||||
}
|
||||
public static final Gfs_lxr_equal Instance = new Gfs_lxr_equal(); Gfs_lxr_equal() {}
|
||||
}
|
||||
class Gfs_lxr_comma implements Gfs_lxr {
|
||||
public int Lxr_tid() {return Gfs_lxr_.Tid_comma;}
|
||||
public int Process(Gfs_parser_ctx ctx, int bgn, int end) {
|
||||
switch (ctx.Prv_lxr()) {
|
||||
case Gfs_lxr_.Tid_identifier: ctx.Make_atr_by_idf(); break; // 123,
|
||||
}
|
||||
return end;
|
||||
}
|
||||
public static final Gfs_lxr_comma Instance = new Gfs_lxr_comma(); Gfs_lxr_comma() {}
|
||||
}
|
||||
39
400_xowa/src/gplx/langs/gfs/Gfs_lxr_.java
Normal file
39
400_xowa/src/gplx/langs/gfs/Gfs_lxr_.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
class Gfs_lxr_ {
|
||||
public static final int Rv_init = -1, Rv_null = -2, Rv_eos = -3, Rv_lxr = -4;
|
||||
public static final int Tid_identifier = 1, Tid_dot = 2, Tid_semic = 3, Tid_paren_bgn = 4, Tid_paren_end = 5, Tid_curly_bgn = 6, Tid_curly_end = 7, Tid_quote = 8, Tid_comma = 9, Tid_whitespace = 10, Tid_comment = 11, Tid_eq = 12;
|
||||
public static String Tid__name(int tid) {
|
||||
switch (tid) {
|
||||
case Tid_identifier: return "identifier";
|
||||
case Tid_dot: return "dot";
|
||||
case Tid_semic: return "semic";
|
||||
case Tid_paren_bgn: return "paren_bgn";
|
||||
case Tid_paren_end: return "paren_end";
|
||||
case Tid_curly_bgn: return "curly_bgn";
|
||||
case Tid_curly_end: return "curly_end";
|
||||
case Tid_quote: return "quote";
|
||||
case Tid_comma: return "comma";
|
||||
case Tid_whitespace: return "whitespace";
|
||||
case Tid_comment: return "comment";
|
||||
case Tid_eq: return "eq";
|
||||
default: throw Err_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
400_xowa/src/gplx/langs/gfs/Gfs_msg_bldr.java
Normal file
53
400_xowa/src/gplx/langs/gfs/Gfs_msg_bldr.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.gfo_regys.*;
|
||||
public class Gfs_msg_bldr implements GfoMsgParser {
|
||||
private final Object thread_lock = new Object();
|
||||
private final Gfs_parser parser = new Gfs_parser();
|
||||
public GfoMsg ParseToMsg(String s) {return Bld(s);}
|
||||
public GfoMsg Bld(String src) {return Bld(Bry_.new_u8(src));}
|
||||
public GfoMsg Bld(byte[] src) {
|
||||
synchronized (thread_lock) { // LOCK:Gfs_parser called when converting messages in Xow_msg_mgr; DATE:2016-10-18
|
||||
Gfs_nde nde = parser.Parse(src);
|
||||
return Bld_msg(src, nde);
|
||||
}
|
||||
}
|
||||
private GfoMsg Bld_msg(byte[] src, Gfs_nde nde) {
|
||||
boolean op_is_assign = (nde.Op_tid() == Gfs_nde.Op_tid_assign);
|
||||
String name = String_.new_u8(nde.Name_bry(src));
|
||||
if (op_is_assign) name += Tkn_mutator;
|
||||
GfoMsg rv = GfoMsg_.new_parse_(name);
|
||||
int len = nde.Atrs_len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfs_nde atr = nde.Atrs_get_at(i);
|
||||
rv.Add("", String_.new_u8(atr.Name_bry(src)));
|
||||
}
|
||||
len = nde.Subs_len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfs_nde sub = nde.Subs_get_at(i);
|
||||
if (op_is_assign) // NOTE: for now (a) assignss cannot be nested; EX: "a.b = c;" is okay but "a.b = c.d;" is not
|
||||
rv.Add("", Bld_msg(src, sub).Key());
|
||||
else
|
||||
rv.Subs_add(Bld_msg(src, sub));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static final Gfs_msg_bldr Instance = new Gfs_msg_bldr(); Gfs_msg_bldr() {} // TS.static
|
||||
public static final String Tkn_mutator = "_";
|
||||
}
|
||||
76
400_xowa/src/gplx/langs/gfs/Gfs_msg_bldr_tst.java
Normal file
76
400_xowa/src/gplx/langs/gfs/Gfs_msg_bldr_tst.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*; import gplx.core.strings.*;
|
||||
public class Gfs_msg_bldr_tst {
|
||||
@Before public void init() {fxt.Clear();} Gfs_msg_bldr_fxt fxt = new Gfs_msg_bldr_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Test_build("a;", fxt.msg_("a"));
|
||||
}
|
||||
@Test public void Dot() {
|
||||
fxt.Test_build("a.b.c;"
|
||||
, fxt.msg_("a").Subs_
|
||||
( fxt.msg_("b").Subs_
|
||||
( fxt.msg_("c")
|
||||
)));
|
||||
}
|
||||
@Test public void Args() {
|
||||
fxt.Test_build("a('b', 'c');", fxt.msg_("a", fxt.kv_("", "b"), fxt.kv_("", "c")));
|
||||
}
|
||||
@Test public void Args_num() {
|
||||
fxt.Test_build("a(1);", fxt.msg_("a", fxt.kv_("", "1")));
|
||||
}
|
||||
@Test public void Assign() {
|
||||
fxt.Test_build("a = 'b';", fxt.msg_("a_", fxt.kv_("", "b")));
|
||||
}
|
||||
@Test public void Assign_num() {
|
||||
fxt.Test_build("a = 1;", fxt.msg_("a_", fxt.kv_("", "1")));
|
||||
}
|
||||
}
|
||||
class Gfs_msg_bldr_fxt {
|
||||
public void Clear() {} String_bldr sb = String_bldr_.new_(); Gfs_msg_bldr msg_bldr = Gfs_msg_bldr.Instance;
|
||||
public Keyval kv_(String key, String val) {return Keyval_.new_(key, val);}
|
||||
public GfoMsg msg_(String key, Keyval... args) {
|
||||
GfoMsg rv = GfoMsg_.new_parse_(key);
|
||||
int len = args.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Keyval kv = args[i];
|
||||
rv.Add(kv.Key(), kv.Val());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Test_build(String raw, GfoMsg... expd) {
|
||||
GfoMsg root = msg_bldr.Bld(raw);
|
||||
Tfds.Eq_str_lines(Xto_str(expd), Xto_str(To_ary(root)));
|
||||
}
|
||||
GfoMsg[] To_ary(GfoMsg msg) {
|
||||
int len = msg.Subs_count();
|
||||
GfoMsg[] rv = new GfoMsg[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = msg.Subs_getAt(i);
|
||||
return rv;
|
||||
}
|
||||
String Xto_str(GfoMsg[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i != 0) sb.Add_char_crlf();
|
||||
sb.Add(ary[i].To_str());
|
||||
}
|
||||
return sb.To_str_and_clear();
|
||||
}
|
||||
}
|
||||
85
400_xowa/src/gplx/langs/gfs/Gfs_nde.java
Normal file
85
400_xowa/src/gplx/langs/gfs/Gfs_nde.java
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
public class Gfs_nde {
|
||||
public byte[] Name_bry(byte[] src) {return name == null ? Bry_.Mid(src, name_bgn, name_end) : name;}
|
||||
public byte[] Name() {return name;} public Gfs_nde Name_(byte[] v) {name = v; return this;} private byte[] name;
|
||||
public int Name_bgn() {return name_bgn;} private int name_bgn = -1;
|
||||
public int Name_end() {return name_end;} private int name_end = -1;
|
||||
public Gfs_nde Name_rng_(int name_bgn, int name_end) {this.name_bgn = name_bgn; this.name_end = name_end; return this;}
|
||||
public byte Op_tid() {return op_tid;} public Gfs_nde Op_tid_(byte v) {op_tid = v; return this;} private byte op_tid;
|
||||
public void Subs_clear() {
|
||||
for (int i = 0; i < subs_len; i++)
|
||||
subs[i] = null;
|
||||
subs_len = 0;
|
||||
}
|
||||
public int Subs_len() {return subs_len;} private int subs_len;
|
||||
public Gfs_nde Subs_add_many(Gfs_nde... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
Subs_add(ary[i]);
|
||||
return this;
|
||||
}
|
||||
public Gfs_nde Subs_add(Gfs_nde nde) {
|
||||
int new_len = subs_len + 1;
|
||||
if (new_len > subs_max) { // ary too small >>> expand
|
||||
subs_max = new_len * 2;
|
||||
Gfs_nde[] new_subs = new Gfs_nde[subs_max];
|
||||
Array_.Copy_to(subs, 0, new_subs, 0, subs_len);
|
||||
subs = new_subs;
|
||||
}
|
||||
subs[subs_len] = nde;
|
||||
subs_len = new_len;
|
||||
return this;
|
||||
} Gfs_nde[] subs = Gfs_nde.Ary_empty; int subs_max; int[] subs_pos_ary = Int_.Ary_empty;
|
||||
public Gfs_nde Subs_get_at(int i) {return subs[i];}
|
||||
public Gfs_nde[] Subs_to_ary() {
|
||||
Gfs_nde[] rv = new Gfs_nde[subs_len];
|
||||
for (int i = 0; i < subs_len; i++)
|
||||
rv[i] = subs[i];
|
||||
return rv;
|
||||
}
|
||||
public int Atrs_len() {return args_len;} private int args_len;
|
||||
public Gfs_nde Atrs_get_at(int i) {return args[i];}
|
||||
public Gfs_nde Atrs_add_many(Gfs_nde... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
Atrs_add(ary[i]);
|
||||
return this;
|
||||
}
|
||||
public Gfs_nde Atrs_add(Gfs_nde nde) {
|
||||
int new_len = args_len + 1;
|
||||
if (new_len > args_max) { // ary too small >>> expand
|
||||
args_max = new_len * 2;
|
||||
Gfs_nde[] new_args = new Gfs_nde[args_max];
|
||||
Array_.Copy_to(args, 0, new_args, 0, args_len);
|
||||
args = new_args;
|
||||
}
|
||||
args[args_len] = nde;
|
||||
args_len = new_len;
|
||||
return this;
|
||||
} Gfs_nde[] args = Gfs_nde.Ary_empty; int args_max; int[] args_pos_ary = Int_.Ary_empty;
|
||||
public Gfs_nde[] Atrs_to_ary() {
|
||||
Gfs_nde[] rv = new Gfs_nde[args_len];
|
||||
for (int i = 0; i < args_len; i++)
|
||||
rv[i] = args[i];
|
||||
return rv;
|
||||
}
|
||||
public static final Gfs_nde[] Ary_empty = new Gfs_nde[0];
|
||||
public static final byte Op_tid_null = 0, Op_tid_assign = 1;
|
||||
}
|
||||
105
400_xowa/src/gplx/langs/gfs/Gfs_parser.java
Normal file
105
400_xowa/src/gplx/langs/gfs/Gfs_parser.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Gfs_parser {
|
||||
private final Btrie_fast_mgr trie = Gfs_parser_.trie_();
|
||||
private final Gfs_parser_ctx ctx = new Gfs_parser_ctx();
|
||||
public Gfs_nde Parse(byte[] src) {
|
||||
ctx.Root().Subs_clear();
|
||||
int src_len = src.length; if (src_len == 0) return ctx.Root();
|
||||
ctx.Init(trie, src, src_len);
|
||||
int pos = 0;
|
||||
while (pos < src_len) {
|
||||
byte b = src[pos];
|
||||
Object o = trie.Match_at_w_b0(ctx.Trie_rv(), b, src, pos, src_len);
|
||||
if (o == null)
|
||||
ctx.Err_mgr().Fail_unknown_char(ctx, pos, b);
|
||||
else {
|
||||
Gfs_lxr lxr = (Gfs_lxr)o;
|
||||
while (lxr != null) {
|
||||
int rslt = lxr.Process(ctx, pos, ctx.Trie_rv().Pos());
|
||||
switch (lxr.Lxr_tid()) {
|
||||
case Gfs_lxr_.Tid_whitespace: break;
|
||||
case Gfs_lxr_.Tid_comment: break;
|
||||
default: ctx.Prv_lxr_(lxr.Lxr_tid()); break;
|
||||
}
|
||||
switch (rslt) {
|
||||
case Gfs_lxr_.Rv_lxr:
|
||||
pos = ctx.Nxt_pos();
|
||||
lxr = ctx.Nxt_lxr();
|
||||
break;
|
||||
case Gfs_lxr_.Rv_eos:
|
||||
pos = src_len;
|
||||
lxr = null;
|
||||
break;
|
||||
default:
|
||||
pos = rslt;
|
||||
lxr = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (ctx.Prv_lxr()) {
|
||||
case Gfs_lxr_.Tid_curly_end:
|
||||
case Gfs_lxr_.Tid_semic: break;
|
||||
default: ctx.Err_mgr().Fail_eos(ctx); break;
|
||||
}
|
||||
return ctx.Root();
|
||||
}
|
||||
}
|
||||
class Gfs_parser_ {
|
||||
public static Btrie_fast_mgr trie_() {
|
||||
Btrie_fast_mgr rv = Btrie_fast_mgr.ci_a7(); // NOTE:ci.ascii:gfs;letters/symbols only;
|
||||
Gfs_lxr_identifier word_lxr = Gfs_lxr_identifier.Instance;
|
||||
trie_add_rng(rv, word_lxr, Byte_ascii.Ltr_a, Byte_ascii.Ltr_z);
|
||||
trie_add_rng(rv, word_lxr, Byte_ascii.Ltr_A, Byte_ascii.Ltr_Z);
|
||||
trie_add_rng(rv, word_lxr, Byte_ascii.Num_0, Byte_ascii.Num_9);
|
||||
rv.Add(Byte_ascii.Underline, word_lxr);
|
||||
trie_add_many(rv, Gfs_lxr_whitespace.Instance, Byte_ascii.Space, Byte_ascii.Nl, Byte_ascii.Cr, Byte_ascii.Tab);
|
||||
trie_add_quote(rv, new byte[] {Byte_ascii.Apos});
|
||||
trie_add_quote(rv, new byte[] {Byte_ascii.Quote});
|
||||
trie_add_quote(rv, Bry_.new_a7("<:[\"\n"), Bry_.new_a7("\n\"]:>"));
|
||||
trie_add_quote(rv, Bry_.new_a7("<:['\n"), Bry_.new_a7("\n']:>"));
|
||||
trie_add_quote(rv, Bry_.new_a7("<:{'"), Bry_.new_a7("'}:>"));
|
||||
trie_add_comment(rv, new byte[] {Byte_ascii.Slash, Byte_ascii.Slash}, new byte[] {Byte_ascii.Nl});
|
||||
trie_add_comment(rv, new byte[] {Byte_ascii.Slash, Byte_ascii.Star}, new byte[] {Byte_ascii.Star, Byte_ascii.Slash});
|
||||
rv.Add(Byte_ascii.Semic, Gfs_lxr_semic.Instance);
|
||||
rv.Add(Byte_ascii.Paren_bgn, Gfs_lxr_paren_bgn.Instance);
|
||||
rv.Add(Byte_ascii.Paren_end, Gfs_lxr_paren_end.Instance);
|
||||
rv.Add(Byte_ascii.Curly_bgn, Gfs_lxr_curly_bgn.Instance);
|
||||
rv.Add(Byte_ascii.Curly_end, Gfs_lxr_curly_end.Instance);
|
||||
rv.Add(Byte_ascii.Dot, Gfs_lxr_dot.Instance);
|
||||
rv.Add(Byte_ascii.Comma, Gfs_lxr_comma.Instance);
|
||||
rv.Add(Byte_ascii.Eq, Gfs_lxr_equal.Instance);
|
||||
return rv;
|
||||
}
|
||||
private static void trie_add_rng(Btrie_fast_mgr trie, Gfs_lxr lxr, byte bgn, byte end) {
|
||||
for (byte b = bgn; b <= end; b++)
|
||||
trie.Add(b, lxr);
|
||||
}
|
||||
private static void trie_add_many(Btrie_fast_mgr trie, Gfs_lxr lxr, byte... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
trie.Add(ary[i], lxr);
|
||||
}
|
||||
private static void trie_add_quote(Btrie_fast_mgr trie, byte[] bgn) {trie_add_quote(trie, bgn, bgn);}
|
||||
private static void trie_add_quote(Btrie_fast_mgr trie, byte[] bgn, byte[] end) {trie.Add(bgn, new Gfs_lxr_quote(bgn, end));}
|
||||
private static void trie_add_comment(Btrie_fast_mgr trie, byte[] bgn, byte[] end) {trie.Add(bgn, new Gfs_lxr_comment_flat(bgn, end));}
|
||||
}
|
||||
127
400_xowa/src/gplx/langs/gfs/Gfs_parser_ctx.java
Normal file
127
400_xowa/src/gplx/langs/gfs/Gfs_parser_ctx.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import gplx.core.btries.*;
|
||||
class Gfs_parser_ctx {
|
||||
public Btrie_fast_mgr Trie() {return trie;} Btrie_fast_mgr trie;
|
||||
public Btrie_rv Trie_rv() {return trie_rv;} private final Btrie_rv trie_rv = new Btrie_rv();
|
||||
public Gfs_nde Root() {return root;} Gfs_nde root = new Gfs_nde();
|
||||
public byte[] Src() {return src;} private byte[] src;
|
||||
public int Src_len() {return src_len;} private int src_len;
|
||||
public int Prv_lxr() {return prv_lxr;} public Gfs_parser_ctx Prv_lxr_(int v) {prv_lxr = v; return this;} private int prv_lxr;
|
||||
public Gfs_nde Cur_nde() {return cur_nde;} Gfs_nde cur_nde;
|
||||
public int Nxt_pos() {return nxt_pos;} private int nxt_pos;
|
||||
public Gfs_lxr Nxt_lxr() {return nxt_lxr;} Gfs_lxr nxt_lxr;
|
||||
public Bry_bfr Tmp_bfr() {return tmp_bfr;} private Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
public void Process_eos() {}
|
||||
public void Process_lxr(int nxt_pos, Gfs_lxr nxt_lxr) {this.nxt_pos = nxt_pos; this.nxt_lxr = nxt_lxr;}
|
||||
public void Process_null(int cur_pos) {this.nxt_pos = cur_pos; this.nxt_lxr = null;}
|
||||
public void Init(Btrie_fast_mgr trie, byte[] src, int src_len) {
|
||||
this.trie = trie; this.src = src; this.src_len = src_len;
|
||||
cur_nde = root;
|
||||
Stack_add();
|
||||
}
|
||||
public void Hold_word(int bgn, int end) {
|
||||
cur_idf_bgn = bgn;
|
||||
cur_idf_end = end;
|
||||
} int cur_idf_bgn = -1, cur_idf_end = -1;
|
||||
private void Held_word_clear() {cur_idf_bgn = -1; cur_idf_end = -1;}
|
||||
public Gfs_nde Make_nde(int tkn_bgn, int tkn_end) { // "abc."; "abc("; "abc;"; "abc{"
|
||||
Gfs_nde nde = new Gfs_nde().Name_rng_(cur_idf_bgn, cur_idf_end);
|
||||
this.Held_word_clear();
|
||||
cur_nde.Subs_add(nde);
|
||||
cur_nde = nde;
|
||||
return nde;
|
||||
}
|
||||
public void Make_atr_by_idf() {Make_atr(cur_idf_bgn, cur_idf_end); Held_word_clear();}
|
||||
public void Make_atr_by_bry(int bgn, int end, byte[] bry) {Make_atr(bgn, end).Name_(bry);}
|
||||
public Gfs_nde Make_atr(int bgn, int end) {
|
||||
Gfs_nde nde = new Gfs_nde().Name_rng_(bgn, end);
|
||||
cur_nde.Atrs_add(nde);
|
||||
return nde;
|
||||
}
|
||||
public void Cur_nde_from_stack() {cur_nde = (Gfs_nde)nodes.Get_at_last();}
|
||||
public void Stack_add() {nodes.Add(cur_nde);} List_adp nodes = List_adp_.New();
|
||||
public void Stack_pop(int pos) {
|
||||
if (nodes.Count() < 2) err_mgr.Fail_nde_stack_empty(this, pos); // NOTE: need at least 2 items; 1 to pop and 1 to set as current
|
||||
List_adp_.Del_at_last(nodes);
|
||||
Cur_nde_from_stack();
|
||||
}
|
||||
public Gfs_err_mgr Err_mgr() {return err_mgr;} Gfs_err_mgr err_mgr = new Gfs_err_mgr();
|
||||
}
|
||||
class Gfs_err_mgr {
|
||||
public void Fail_eos(Gfs_parser_ctx ctx) {Fail(ctx, Fail_msg_eos, ctx.Src_len());}
|
||||
public void Fail_unknown_char(Gfs_parser_ctx ctx, int pos, byte c) {Fail(ctx, Fail_msg_unknown_char, pos, Keyval_.new_("char", Char_.To_str((char)c)));}
|
||||
public void Fail_nde_stack_empty(Gfs_parser_ctx ctx, int pos) {Fail(ctx, Fail_msg_nde_stack_empty, pos);}
|
||||
public void Fail_invalid_lxr(Gfs_parser_ctx ctx, int pos, int lxr_tid, byte c) {
|
||||
Fail(ctx, Fail_msg_invalid_lxr, pos, Keyval_.new_("char", Char_.To_str((char)c)), Keyval_.new_("cur_lxr", Gfs_lxr_.Tid__name(lxr_tid)), Keyval_.new_("prv_lxr", Gfs_lxr_.Tid__name(ctx.Prv_lxr())));
|
||||
}
|
||||
private void Fail(Gfs_parser_ctx ctx, String msg, int pos, Keyval... args) {
|
||||
byte[] src = ctx.Src(); int src_len = ctx.Src_len();
|
||||
Fail_args_standard(src, src_len, pos);
|
||||
int len = args.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Keyval arg = args[i];
|
||||
tmp_fail_args.Add(arg.Key(), arg.Val_to_str_or_empty());
|
||||
}
|
||||
throw Err_.new_wo_type(Fail_msg(msg, tmp_fail_args));
|
||||
}
|
||||
private void Fail_args_standard(byte[] src, int src_len, int pos) {
|
||||
tmp_fail_args.Add("excerpt_bgn", Fail_excerpt_bgn(src, src_len, pos));
|
||||
tmp_fail_args.Add("excerpt_end", Fail_excerpt_end(src, src_len, pos));
|
||||
tmp_fail_args.Add("pos" , pos);
|
||||
}
|
||||
public static final String Fail_msg_invalid_lxr = "invalid character", Fail_msg_unknown_char = "unknown char", Fail_msg_eos = "end of stream", Fail_msg_nde_stack_empty = "node stack empty";
|
||||
String Fail_msg(String type, Keyval_list fail_args) {
|
||||
tmp_fail_bfr.Add_str_u8(type).Add_byte(Byte_ascii.Colon);
|
||||
int len = fail_args.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
tmp_fail_bfr.Add_byte(Byte_ascii.Space);
|
||||
Keyval kv = fail_args.Get_at(i);
|
||||
tmp_fail_bfr.Add_str_u8(kv.Key());
|
||||
tmp_fail_bfr.Add_byte(Byte_ascii.Eq).Add_byte(Byte_ascii.Apos);
|
||||
tmp_fail_bfr.Add_str_u8(kv.Val_to_str_or_empty()).Add_byte(Byte_ascii.Apos);
|
||||
}
|
||||
return tmp_fail_bfr.To_str_and_clear();
|
||||
}
|
||||
Bry_bfr tmp_fail_bfr = Bry_bfr_.Reset(255);
|
||||
Keyval_list tmp_fail_args = new Keyval_list();
|
||||
private static int excerpt_len = 50;
|
||||
String Fail_excerpt_bgn(byte[] src, int src_len, int pos) {
|
||||
int bgn = pos - excerpt_len; if (bgn < 0) bgn = 0;
|
||||
Fail_excerpt_rng(tmp_fail_bfr, src, bgn, pos);
|
||||
return tmp_fail_bfr.To_str_and_clear();
|
||||
}
|
||||
String Fail_excerpt_end(byte[] src, int src_len, int pos) {
|
||||
int end = pos + excerpt_len; if (end > src_len) end = src_len;
|
||||
Fail_excerpt_rng(tmp_fail_bfr, src, pos, end);
|
||||
return tmp_fail_bfr.To_str_and_clear();
|
||||
}
|
||||
private static void Fail_excerpt_rng(Bry_bfr bfr, byte[] src, int bgn, int end) {
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case Byte_ascii.Tab: bfr.Add(Esc_tab); break;
|
||||
case Byte_ascii.Nl: bfr.Add(Esc_nl); break;
|
||||
case Byte_ascii.Cr: bfr.Add(Esc_cr); break;
|
||||
default: bfr.Add_byte(b); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static final byte[] Esc_nl = Bry_.new_a7("\\n"), Esc_cr = Bry_.new_a7("\\r"), Esc_tab = Bry_.new_a7("\\t");
|
||||
}
|
||||
196
400_xowa/src/gplx/langs/gfs/Gfs_parser_tst.java
Normal file
196
400_xowa/src/gplx/langs/gfs/Gfs_parser_tst.java
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
import org.junit.*;
|
||||
public class Gfs_parser_tst {
|
||||
@Before public void init() {fxt.Clear();} Gfs_parser_fxt fxt = new Gfs_parser_fxt();
|
||||
@Test public void Semicolon() {
|
||||
fxt .Test_parse("a;", fxt.nde_("a"));
|
||||
fxt .Test_parse("a;b;c;", fxt.nde_("a"), fxt.nde_("b"), fxt.nde_("c"));
|
||||
fxt .Test_parse("a_0;", fxt.nde_("a_0"));
|
||||
}
|
||||
@Test public void Dot() {
|
||||
fxt .Test_parse("a.b;", fxt.nde_("a").Subs_add(fxt.nde_("b")));
|
||||
fxt .Test_parse("a.b;c.d;", fxt.nde_("a").Subs_add(fxt.nde_("b")), fxt.nde_("c").Subs_add(fxt.nde_("d")));
|
||||
}
|
||||
@Test public void Parens() {
|
||||
fxt .Test_parse("a();b();", fxt.nde_("a"), fxt.nde_("b"));
|
||||
fxt .Test_parse("a().b();c().d();", fxt.nde_("a").Subs_add(fxt.nde_("b")), fxt.nde_("c").Subs_add(fxt.nde_("d")));
|
||||
}
|
||||
@Test public void Num() {
|
||||
fxt .Test_parse("a(1,2);", fxt.nde_("a").Atrs_add_many(fxt.val_("1"), fxt.val_("2")));
|
||||
}
|
||||
@Test public void Quote() {
|
||||
fxt .Test_parse("a('b');", fxt.nde_("a").Atrs_add(fxt.val_("b")));
|
||||
}
|
||||
@Test public void Quote_escaped() {
|
||||
fxt .Test_parse("a('b''c''d');", fxt.nde_("a").Atrs_add(fxt.val_("b'c'd")));
|
||||
}
|
||||
@Test public void Quote_escaped_2() {
|
||||
fxt .Test_parse("a('a''''b');", fxt.nde_("a").Atrs_add(fxt.val_("a''b")));
|
||||
}
|
||||
@Test public void Quote_mixed() {
|
||||
fxt .Test_parse("a('b\"c');", fxt.nde_("a").Atrs_add(fxt.val_("b\"c")));
|
||||
}
|
||||
@Test public void Comma() {
|
||||
fxt .Test_parse("a('b','c','d');", fxt.nde_("a").Atrs_add_many(fxt.val_("b"), fxt.val_("c"), fxt.val_("d")));
|
||||
}
|
||||
@Test public void Ws() {
|
||||
fxt .Test_parse(" a ( 'b' , 'c' ) ; ", fxt.nde_("a").Atrs_add_many(fxt.val_("b"), fxt.val_("c")));
|
||||
}
|
||||
@Test public void Comment_slash_slash() {
|
||||
fxt .Test_parse("//z\na;//y\n", fxt.nde_("a"));
|
||||
}
|
||||
@Test public void Comment_slash_star() {
|
||||
fxt .Test_parse("/*z*/a;/*y*/", fxt.nde_("a"));
|
||||
}
|
||||
@Test public void Curly() {
|
||||
fxt .Test_parse("a{b;}", fxt.nde_("a").Subs_add(fxt.nde_("b")));
|
||||
}
|
||||
@Test public void Curly_nest() {
|
||||
fxt .Test_parse("a{b{c{d;}}}"
|
||||
, fxt.nde_("a").Subs_add
|
||||
( fxt.nde_("b").Subs_add
|
||||
( fxt.nde_("c").Subs_add
|
||||
( fxt.nde_("d")
|
||||
))));
|
||||
}
|
||||
@Test public void Curly_nest_peers() {
|
||||
fxt .Test_parse(String_.Concat_lines_nl
|
||||
( "a{"
|
||||
, " a0{"
|
||||
, " a00{"
|
||||
, " a000;"
|
||||
, " }"
|
||||
, " a01;"
|
||||
, " }"
|
||||
, " a1;"
|
||||
, "}"
|
||||
)
|
||||
, fxt.nde_("a").Subs_add_many
|
||||
( fxt.nde_("a0").Subs_add_many
|
||||
( fxt.nde_("a00").Subs_add
|
||||
( fxt.nde_("a000")
|
||||
)
|
||||
, fxt.nde_("a01")
|
||||
)
|
||||
, fxt.nde_("a1")
|
||||
));
|
||||
}
|
||||
@Test public void Curly_dot() {
|
||||
fxt .Test_parse("a{a0.a00;a1.a10;}"
|
||||
, fxt.nde_("a").Subs_add_many
|
||||
( fxt.nde_("a0").Subs_add_many(fxt.nde_("a00"))
|
||||
, fxt.nde_("a1").Subs_add_many(fxt.nde_("a10"))
|
||||
));
|
||||
}
|
||||
@Test public void Eq() {
|
||||
fxt .Test_parse("a='b';", fxt.nde_("a").Atrs_add(fxt.val_("b")));
|
||||
fxt .Test_parse("a.b.c='d';"
|
||||
, fxt.nde_("a").Subs_add
|
||||
( fxt.nde_("b").Subs_add_many
|
||||
( fxt.nde_("c").Atrs_add(fxt.val_("d"))
|
||||
)));
|
||||
fxt .Test_parse("a.b{c='d'; e='f'}"
|
||||
, fxt.nde_("a").Subs_add
|
||||
( fxt.nde_("b").Subs_add_many
|
||||
( fxt.nde_("c").Atrs_add(fxt.val_("d"))
|
||||
, fxt.nde_("e").Atrs_add(fxt.val_("f"))
|
||||
)));
|
||||
}
|
||||
@Test public void Curly_nest_peers2() {
|
||||
fxt .Test_parse(String_.Concat_lines_nl
|
||||
( "a() {"
|
||||
, " k1 = 'v1';"
|
||||
, "}"
|
||||
)
|
||||
, fxt.nde_("a").Subs_add_many
|
||||
( fxt.nde_("k1").Atrs_add(fxt.val_("v1"))
|
||||
)
|
||||
);
|
||||
}
|
||||
@Test public void Fail() {
|
||||
fxt .Test_parse_fail("a(.);", Gfs_err_mgr.Fail_msg_invalid_lxr); // (.)
|
||||
fxt .Test_parse_fail("a..b;", Gfs_err_mgr.Fail_msg_invalid_lxr); // ..
|
||||
fxt .Test_parse_fail("a.;", Gfs_err_mgr.Fail_msg_invalid_lxr); // .;
|
||||
fxt .Test_parse_fail("a", Gfs_err_mgr.Fail_msg_eos); // eos
|
||||
fxt .Test_parse_fail("a;~;", Gfs_err_mgr.Fail_msg_unknown_char); // ~
|
||||
}
|
||||
}
|
||||
class Gfs_parser_fxt {
|
||||
public void Clear() {}
|
||||
public Gfs_nde nde_(String v) {return new Gfs_nde().Name_(Bry_.new_a7(v));}
|
||||
public Gfs_nde val_(String v) {return new Gfs_nde().Name_(Bry_.new_a7(v));}
|
||||
public void Test_parse(String src_str, Gfs_nde... expd) {
|
||||
byte[] src_bry = Bry_.new_u8(src_str);
|
||||
Gfs_nde root = parser.Parse(src_bry);
|
||||
Tfds.Eq_str_lines(To_str(null, expd), To_str(src_bry, root.Subs_to_ary()));
|
||||
} private Bry_bfr tmp_bfr = Bry_bfr_.New(), path_bfr = Bry_bfr_.New(); Gfs_parser parser = new Gfs_parser();
|
||||
public void Test_parse_fail(String src_str, String expd_err) {
|
||||
byte[] src_bry = Bry_.new_u8(src_str);
|
||||
try {parser.Parse(src_bry);}
|
||||
catch (Exception e) {
|
||||
String actl_err = Err_.Message_gplx_full(e);
|
||||
actl_err = String_.GetStrBefore(actl_err, ":");
|
||||
boolean match = String_.Has(actl_err, expd_err);
|
||||
if (!match) Tfds.Fail("expecting '" + expd_err + "' got '" + actl_err + "'");
|
||||
return;
|
||||
}
|
||||
Tfds.Fail("expected to fail with " + expd_err);
|
||||
}
|
||||
public String To_str(byte[] src, Gfs_nde[] expd) {
|
||||
int subs_len = expd.length;
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
path_bfr.Clear().Add_int_variable(i);
|
||||
To_str(tmp_bfr, path_bfr, src, expd[i]);
|
||||
}
|
||||
return tmp_bfr.To_str_and_clear();
|
||||
}
|
||||
public void To_str(Bry_bfr bfr, Bry_bfr path, byte[] src, Gfs_nde nde) {
|
||||
To_str_atr(bfr, path, src, Atr_name, nde.Name(), nde.Name_bgn(), nde.Name_end());
|
||||
int atrs_len = nde.Atrs_len();
|
||||
for (int i = 0; i < atrs_len; i++) {
|
||||
Gfs_nde atr = nde.Atrs_get_at(i);
|
||||
int path_len_old = path.Len();
|
||||
path.Add_byte(Byte_ascii.Dot).Add_byte((byte)(Byte_ascii.Ltr_a + i));
|
||||
int path_len_new = path.Len();
|
||||
To_str(bfr, path, src, atr);
|
||||
path.Del_by(path_len_new - path_len_old);
|
||||
}
|
||||
int subs_len = nde.Subs_len();
|
||||
for (int i = 0; i < subs_len; i++) {
|
||||
Gfs_nde sub = nde.Subs_get_at(i);
|
||||
int path_len_old = path.Len();
|
||||
path.Add_byte(Byte_ascii.Dot).Add_int_variable(i);
|
||||
int path_len_new = path.Len();
|
||||
To_str(bfr, path, src, sub);
|
||||
path.Del_by(path_len_new - path_len_old);
|
||||
}
|
||||
}
|
||||
private void To_str_atr(Bry_bfr bfr, Bry_bfr path_bfr, byte[] src, byte[] name, byte[] val, int val_bgn, int val_end) {
|
||||
if (val == null && val_bgn == -1 && val_end == -1) return;
|
||||
bfr.Add_bfr_and_preserve(path_bfr).Add_byte(Byte_ascii.Colon);
|
||||
bfr.Add(name);
|
||||
if (val == null)
|
||||
bfr.Add_mid(src, val_bgn, val_end);
|
||||
else
|
||||
bfr.Add(val);
|
||||
bfr.Add_byte_nl();
|
||||
}
|
||||
private static final byte[] Atr_name = Bry_.new_a7("name=");
|
||||
}
|
||||
46
400_xowa/src/gplx/langs/gfs/Gfs_wtr.java
Normal file
46
400_xowa/src/gplx/langs/gfs/Gfs_wtr.java
Normal 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.langs.gfs; import gplx.*; import gplx.langs.*;
|
||||
public class Gfs_wtr {
|
||||
public byte Quote_char() {return quote_char;} public Gfs_wtr Quote_char_(byte v) {quote_char = v; return this;} private byte quote_char = Byte_ascii.Apos;
|
||||
public Bry_bfr Bfr() {return bfr;} private Bry_bfr bfr = Bry_bfr_.Reset(255);
|
||||
public void Add_grp_bgn(byte[] key) {
|
||||
bfr.Add(key); // key
|
||||
bfr.Add_byte(Byte_ascii.Curly_bgn); // {
|
||||
}
|
||||
public void Add_grp_end(byte[] key) {
|
||||
bfr.Add_byte(Byte_ascii.Curly_end); // }
|
||||
}
|
||||
public void Add_set_eq(byte[] key, byte[] val) {
|
||||
bfr.Add(key); // key
|
||||
bfr.Add_byte_eq(); // =
|
||||
bfr.Add_byte(quote_char); // '
|
||||
Write_val(val);
|
||||
bfr.Add_byte(quote_char); // '
|
||||
bfr.Add_byte(Byte_ascii.Semic); // ;
|
||||
}
|
||||
private void Write_val(byte[] bry) {
|
||||
int bry_len = bry.length;
|
||||
for (int i = 0; i < bry_len; i++) {
|
||||
byte b = bry[i];
|
||||
if (b == quote_char) // byte is quote
|
||||
bfr.Add_byte(b); // double up
|
||||
bfr.Add_byte(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user