Unten tut es mir leid, aber ich werde es in einem Zustand belassen, in dem ich es eine Weile nicht ertragen kann, als Artikel zu lesen ...
Erstellen Sie eine Klasse namens Utf32Iterator und eine Klasse namens IteratorInput, um die Zeichenfolge zu analysieren. Ich werde auch Ersatzpaare in Betracht ziehen.
StringParser.java
public class StringParser {
//Iterator, der die Zeichenfolge als Unicode-Codepunkt behandelt. Betrachten Sie auch Ersatzpaare.
public static class Utf32Iterator implements Iterator<Integer> {
private int position, nextCodePoint = -1;
private final String source;
public Utf32Iterator(String source_) {source = source_; position = 0;}
@Override public boolean hasNext() {
nextCodePoint = -1;
return position <= source.length(); // position == source.length()Der Fall ist EOF. Gibt null zurück und macht dann EndOfInputException.
}
@Override public Integer next() {
if (position == source.length()) { //EOF, wenn die Länge der Zeichenfolge genau richtig ist. Gibt null zurück.
position ++;
return null;
}
if (nextCodePoint < 0) { //Wenn nextCodePoint nicht festgelegt ist, verwenden Sie codePointAt, um das Zeichen abzurufen und den Wert nur einmal festzulegen.
nextCodePoint = source.codePointAt(position);
position = source.offsetByCodePoints(position, 1);
}
return nextCodePoint;
}
}
//Eingabeklasse zum Übergeben des Iterators an Parser
public static class IteratorInput<T> implements Input<T> {
private final Iterator<T> iterator;
private final int position;
private final T current;
public IteratorInput(Iterator<T> iterator_) {iterator = iterator_; position = 0; current = iterator.hasNext() ? iterator.next(): null;}
public IteratorInput(Iterator<T> iterator_, int position_) {iterator = iterator_; position = position_; current = iterator.hasNext() ? iterator.next() : null;}
@Override public T current() {return current;}
@Override public String positionDescription() {return "" + position;}
private IteratorInput<T> next = null; //Behalten Sie den Cache bei, da next aufgrund von oder möglicherweise mehrmals angefordert wird.
@Override public Input<T> next() throws EndOfInputException {
if (next != null) return next;
if (iterator.hasNext()) return (next = new IteratorInput<T>(iterator, position + 1)); throw new EndOfInputException();
}
}
//Stapelliste des Unicode-Codepunkts in eine Zeichenfolge
public static Parser<Integer, String> concat(Parser<Integer, List<Integer>> parser) {
return apply(reduce(parser, () -> new StringBuilder(), (sb, i) -> sb.appendCodePoint(i)), sb -> sb.toString());
}
public static Parser<Integer, String> concatStr(Parser<Integer, List<String>> parser) {
return apply(reduce(parser, () -> new StringBuilder(), (sb, i) -> sb.append(i)), sb -> sb.toString());
}
//Parser, der nur ein in str enthaltenes Zeichen übergibt
public static Parser<Integer, Integer> consistsOf(String str) {return satisfy(i -> str.indexOf(i) >= 0);}
//Parser, der dieselbe Zeichenfolge wie str verwendet
public static Parser<Integer, String> word(String str) {
List<Parser<Integer, Integer>> result = new ArrayList<>();
str.chars().forEach(i -> result.add(satisfy(j -> j == i)));
return concat(lst(result));
}
public static String codePointToString(int[] codePoint) {return new String(codePoint, 0, codePoint.length);}
public static String codePointToString(int codePoint) {return codePointToString(new int[] {codePoint});}
//Parser, der Eingaben verbraucht, bis dieselbe Zeichenfolge wie str angezeigt wird
public static Parser<Integer, String> until(String str) {
ParserMemoizer<Integer, String> result = new ParserMemoizer<Integer, String>();
result.defun(() -> or(word(str), apply(seq(satisfy(i -> true) /*Parser, der ein einzelnes Zeichen verbraucht*/ , result), tpl2 -> codePointToString(tpl2.car) + tpl2.cdr.car)));
return result;
}
}
Recommended Posts