/* XOWA: the XOWA Offline Wiki Application Copyright (C) 2012-2017 gnosygnu@gmail.com XOWA is licensed under the terms of the General Public License (GPL) Version 3, or alternatively under the terms of the Apache License Version 2.0. You may use XOWA according to either of these licenses as is most appropriate for your project on a case-by-case basis. The terms of each license can be found in the source code repository: GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ 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() {} }