Skip to content

Instantly share code, notes, and snippets.

@kmizu
Last active July 26, 2017 14:03
Show Gist options
  • Save kmizu/6f7687b0924bd00baab76ae43ef62386 to your computer and use it in GitHub Desktop.
Save kmizu/6f7687b0924bd00baab76ae43ef62386 to your computer and use it in GitHub Desktop.
Javaで始めるパーザコンビネータの作り方(3) ~ Hello or World! ref: http://qiita.com/kmizu/items/c509d726285c2e7416fb
Parser<A> pa = ...;
Parser<B> pb = ...;
String input;
ParseResult<X> lresult = pa.invoke(input); //(1)
if(lresult instanceof ParseResult.Failure<?>) {
return pb.invoke(input);
} else {
return lresult;
}
package parser;
public class Or<X> implements Parser<X> {
private Parser<X> lhs;
private Parser<X> rhs;
public Or(Parser<X> lhs, Parser<X> rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public ParseResult<X> invoke(String input) {
ParseResult<X> lresult = lhs.invoke(input);
if(lresult instanceof ParseResult.Failure<?>) {
return rhs.invoke(input);
} else {
return lresult;
}
}
}
package parser;
public interface Parser<T> {
ParseResult<T> invoke(String input);
default Parser<T> or(Parser<T> rhs) {
return new Or<>(this, rhs);
}
default <U> Parser<Tuple2<T, U>> cat(Parser<U> rhs) {
return new Cat<>(this, rhs);
}
static Parser<String> string(String literal) {
return new StringParser(literal);
}
}
public class Main {
public static void main(String[] args) {
Parser<String> helloOrWorld = Parser.string("Hello").or(Parser.string("World"));
Parser<Tuple2<String, String>> hw = helloOrWorld.cat(helloOrWorld);
System.out.println(hw.invoke("HelloWorld"));
System.out.println(hw.invoke("HelloHello"));
System.out.println(hw.invoke("WorldHello"));
System.out.println(hw.invoke("WorldWorld"));
}
}
Success(Tuple2{item1=Hello, item2=World}, )
Success(Tuple2{item1=Hello, item2=Hello}, )
Success(Tuple2{item1=World, item2=Hello}, )
Success(Tuple2{item1=World, item2=World}, )
package parser;
public interface ParseResult<T> {
public static class Success<T> implements ParseResult<T> {
public final T value;
public final String next;
Success(T value, String next) {
this.value = value;
this.next = next;
}
@Override
public <U> ParseResult<U> map(Function<T, U> fn) {
return new Success<U>(fn.apply(value), next);
}
@Override
public String toString() {
return "Success(" + value + ", " + next + ")";
}
}
public static class Failure<T> implements ParseResult<T> {
public final String message;
public final String next;
public Failure(String message, String next) {
this.message = message;
this.next = next;
}
@Override
public <U> ParseResult<U> map(Function<T, U> fn) {
return (ParseResult<U>)this;
}
@Override
public String toString() {
return "Failure(" + message + ", " + next;
}
}
<U> ParseResult<U> map(Function<T, U> fn);
}
package parser;
import java.util.function.BiFunction;
public class Tuple2<X, Y> {
public final X item1;
public final Y item2;
public Tuple2(X item1, Y item2) {
this.item1 = item1;
this.item2 = item2;
}
public X item1() {
return item1;
}
public Y item2() {
return item2;
}
public <U> U extract(BiFunction<X, Y, U> f) {
return f.apply(item1, item2);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tuple2<?, ?> tp2 = (Tuple2<?, ?>) o;
if (!item1.equals(tp2.item1)) return false;
return item2.equals(tp2.item2);
}
@Override
public int hashCode() {
int result = item1.hashCode();
result = 31 * result + item2.hashCode();
return result;
}
@Override
public String toString() {
return "Tuple2{" + "item1=" + item1 + ", item2=" + item2 + '}';
}
}
package parser;
import java.util.function.BiFunction;
public class Tuple2<X, Y> {
public final X item1;
public final Y item2;
public Tuple2(X item1, Y item2) {
this.item1 = item1;
this.item2 = item2;
}
public X item1() {
return item1;
}
public Y item2() {
return item2;
}
public <U> U extract(BiFunction<X, Y, U> f) {
return f.apply(item1, item2);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tuple2<?, ?> tp2 = (Tuple2<?, ?>) o;
if (!item1.equals(tp2.item1)) return false;
return item2.equals(tp2.item2);
}
@Override
public int hashCode() {
int result = item1.hashCode();
result = 31 * result + item2.hashCode();
return result;
}
@Override
public String toString() {
return "Tuple2{" + "item1=" + item1 + ", item2=" + item2 + '}';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment