net.siisise.bnf.AbstractBNF Maven / Gradle / Ivy
The newest version!
package net.siisise.bnf;
import net.siisise.block.ReadableBlock;
import net.siisise.bnf.parser.BNFParser;
import net.siisise.io.FrontPacket;
import net.siisise.io.Input;
import net.siisise.io.Packet;
import net.siisise.io.PacketA;
/**
* 基本実装
* @param
*/
public abstract class AbstractBNF implements BNF {
/**
* 名前、またはABNFに近いもの (まだ抜けもある)
*/
protected String name;
@Override
public String getName() {
if (name == null) {
return "???";
}
return name;
}
@Override
public String toString() {
return name;
}
@Override
public B name(String name) {
return (B) new BNFrule(name, this);
}
/**
* name に 一致する parser を選ぶ.
* @param Parserの戻り型
* @param parsers parser候補
* @return 一致するもの しないときはnull
*/
protected BNFParser extends X> matchParser(BNFParser extends X>[] parsers) {
for (BNFParser ps : parsers) {
if (name.equals(ps.getBNF().getName())) {
return ps;
}
}
return null;
}
@Override
public boolean is(String val) {
return is(rb(val)) != null;
}
@Override
public boolean is(String val, Object ns) {
return is(rb(val), ns) != null;
}
/**
* 先頭一致でパースする。
*
* @param pac 解析対象
* @return 一致した範囲
*/
@Override
public Packet is(FrontPacket pac) {
ReadableBlock res = is(rb(pac));
return res != null ? pac(res) : null;
}
@Override
public Packet is(FrontPacket pac, Object ns) {
ReadableBlock res = is(rb(pac), ns);
return res != null ? pac(res) : null;
}
/**
* sub要素のない場合の軽い対応
* @param パラメータっぽい型
* @param pac 解析データ
* @param parsers サブ要素のparser
* @return 処理結果
*/
@Override
public Match find(FrontPacket pac, BNFParser extends X>... parsers) {
return find(rb(pac), null, parsers);
}
/**
* sub要素のない場合の軽い対応
* @param パラメータっぽい型
* @param pac 解析データ
* @param parsers サブ要素のparser
* @return 処理結果
*/
@Override
public Match find(ReadableBlock pac, BNFParser extends X>... parsers) {
return find(pac, null, parsers);
}
/**
* sub要素のない場合の軽い対応
* @param パラメータっぽい型
* @param pac 解析データ
* @param ns name space
* @param parsers サブ要素のparser
* @return 処理結果
*/
@Override
public Match find(FrontPacket pac, Object ns, BNFParser extends X>... parsers) {
return find(rb(pac), ns, parsers);
}
@Override
public boolean eq(ReadableBlock src) {
ReadableBlock r = is(src);
if (r != null && src.length() == 0) {
return true;
}
if (r != null) {
src.back(r.length());
}
return false;
}
@Override
public boolean eq(FrontPacket src) {
return eq(rb(src));
}
@Override
public boolean eq(String src) {
return eq(rb(src));
}
/**
* Concatenation の単純版
* *(a / b ) a の様なものが解析できないが速そう
* @param val plus する ABNF列
* @return 簡易に比較するABNF
*/
@Override
public B pl(BNF... val) {
if (val.length == 0) {
return (B) this;
}
BNF[] list = new BNF[val.length + 1];
list[0] = this;
System.arraycopy(val, 0, list, 1, val.length);
return (B) new BNFpl(list);
}
/**
* やや厳密に対応する足し算版
* *( a / b ) a にも対応
* @param val plus する ABNF列
* @return 厳密に比較できるABNF
*/
@Override
public B plm(BNF... val) {
if (val.length == 0) {
return (B) this;
}
BNF[] list = new BNF[val.length + 1];
list[0] = this;
System.arraycopy(val, 0, list, 1, val.length);
return (B) new BNFplm(list);
}
/**
* Unicode単位で比較する若干速いのかもしれない版 plm
* @param vals plus する ABNF列
* @return unicodeで比較されるABNF処理
*/
@Override
public B plu(BNF... vals) {
if (vals.length == 0) {
return (B) this;
}
BNF[] list = new BNF[vals.length + 1];
list[0] = this;
System.arraycopy(vals, 0, list, 1, vals.length);
return (B) new BNFplu(list);
}
/**
* 最長一致系
* @param vals 候補BNF
* @return 候補から最長一致を出すBNF
*/
@Override
public B or(BNF... vals) {
BNF[] list = new BNF[vals.length + 1];
list[0] = this;
System.arraycopy(vals, 0, list, 1, vals.length);
return (B) new BNFor(list);
}
/**
* 初一致を返す処理系
* @param vals 候補
* @return thisと候補で最初に一致したものを返すBNF
*/
@Override
public B or1(BNF... vals) {
BNF[] list = new BNF[vals.length + 1];
list[0] = this;
System.arraycopy(vals, 0, list, 1, vals.length);
return (B) new BNFor1(list);
}
@Override
public B x(int min, int max) {
return (B) new BNFx(min, max, this);
}
@Override
public B x(int num) {
return x(num,num);
}
@Override
public B x() {
return x(0, -1);
}
@Override
public B ix() {
return x(1, -1);
}
@Override
public B c() {
return x(0, 1);
}
@Override
public B mn(BNF val) {
return (B)new BNFmn(this, val);
}
public static FrontPacket pac(String str) {
PacketA pac = new PacketA();
pac.dwrite(str.getBytes(UTF8));
return pac;
}
/**
* 文字列を読み込み専用Blockに.
* @param str 元文字列
* @return ReadableBlockに変換された文字列のバイト列
*/
public static final ReadableBlock rb(String str) {
return ReadableBlock.wrap(str);
}
public static final ReadableBlock rb(FrontPacket p) {
return ReadableBlock.wrap(p);
}
public static final Packet pac(ReadableBlock rb) {
Packet pac = new PacketA();
pac.write(rb);
return pac;
}
public static String str(Input pac) {
return new String(pac.toByteArray(), UTF8);
}
/**
* 文字列に起こす。 データは元に戻すので減らない。
* ABNFでは使ってないかも.
* @param pac 元パケット
* @return 文字に変えたもの
*/
public static String strd(FrontPacket pac) {
byte[] data = pac.toByteArray();
String s = new String(data, UTF8);
pac.backWrite(data);
return s;
}
/**
* 文字列に起こす。 データは元に戻すので減らない。
*
* @param pac 元パケット
* @return 文字に変えたもの
*/
public static String strd(ReadableBlock pac) {
byte[] data = pac.toByteArray();
String s = new String(data, UTF8);
pac.back(data.length);
return s;
}
/**
* 名前が該当すればそれ以下を削除して詰め直す
*
* @param 戻りの型
* @param cret 戻り
* @param ns name space
* @param parser 一致するものだけ必要
* @return 戻りからさらにparserを通したものを追加したもの
*/
protected Match subBuild(Match cret, Object ns, BNFParser extends X> parser) {
if (parser != null) {
cret.subs.clear();
long o = cret.sub.backLength();
cret.add(name, parser.parse(cret.sub, ns));
cret.sub.seek(o);
}
return cret;
}
/**
* 結果2を1に混ぜる
* @param 戻り型
* @param ret 結果1
* @param sub 結果2
*/
protected static void mix(Match ret, Match sub) {
sub.subs.forEach((key,vlist) -> {
vlist.forEach((v) -> {
ret.add(key, v);
});
});
}
/**
* UTF-8 HEX
* %x00, %x0000, %x000000 のどれか
* @param ch 1文字
* @return っぽく
*/
protected String uhex(int ch) {
if (ch < 0x80) { // 文字としては 0x80以降は4桁にしておきたい
return "%x" + Integer.toHexString(0x100 + ch).substring(1);
} else if (ch < 0x10000) {
return "%x" + Integer.toHexString(0x10000 + ch).substring(1);
} else {
return "%x" + Integer.toHexString(0x1000000 + ch).substring(1);
}
}
protected String toJavaCh(byte ch) {
switch( ch ) {
case '\b':
return "'\\b'";
case '\t':
return "'\\t'";
case '\n':
return "'\\n'";
case '\r':
return "'\\r'";
case '\f':
return "'\\f'";
case '\'':
return "'\\''";
case '\"':
return "'\\\"'";
case '\\':
return "'\\\\'";
}
StringBuilder s = new StringBuilder();
if ( ch >= 0x20 && ch <= 0x7e) {
s.append('\'');
s.append((char)ch);
s.append('\'');
} else {
s.append("0x");
String hex = "0" + Integer.toHexString(ch & 0xff).toUpperCase();
s.append(hex.substring(hex.length() - 2));
}
return s.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy