Created
July 25, 2017 03:02
-
-
Save kmizu/022834268e5daced5b82036b00d13515 to your computer and use it in GitHub Desktop.
Javaで始めるパーザコンビネータの作り方(2) ~ Hello + World! ref: http://qiita.com/kmizu/items/694b2bed2338b57d182a
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package parser; | |
public interface Parser<T> { | |
ParseResult<T> invoke(String input); | |
static Parser<String> string(String literal) { | |
return new StringParser(literal); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package parser; | |
public class StringParser implements Parser<String> { | |
public final String literal; | |
public StringParser(String literal) { | |
this.literal = literal; | |
} | |
@Override | |
public ParseResult<String> invoke(String input) { | |
if(input.startsWith(literal)) { | |
return new ParseResult.Success<>(literal, input.substring(literal.length())); | |
}else { | |
return new ParseResult.Failure<>("expect: " + literal, input); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package parser; | |
import java.util.function.*; | |
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); | |
} | |
} | |
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(Function1<T, U> fn) { | |
return (ParseResult<U>)this; | |
} | |
} | |
<U> ParseResult<U> map(Function<T, U> fn); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Parser<A> pa = ...; | |
Parser<B> pb = ...; | |
String input; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ParseResult<A> ra = pa.parse(input); | |
if(ra instanceof ParseResult.Success<*>) { | |
String next = ((ParseResult.Success<A>)ra).next; | |
ParseResult<B> rb = pb.parse(next); | |
if(rb instanceof ParseResult.Success<*>) { | |
return build( | |
((ParseResult.Success<A>)ra), | |
((ParseResult.Success<B>)rb) | |
); | |
} else { | |
return rb; | |
} | |
} else { | |
return ra; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package parser; | |
public class Tuple2<A, B> { | |
public final A item1; | |
public final B item2; | |
public Tuple2(A item1, B item2) { | |
this.item1 = item1; | |
this.item2 = item2; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ParseResult<A> ra = pa.parse(input); | |
if(ra instanceof ParseResult.Success<?>) { | |
String next = ((ParseResult.Success<A>)ra).next; | |
ParseResult<B> rb = pb.parse(next); | |
if(rb instanceof ParseResult.Success<?>) { | |
return new ParseResult.Success<>( | |
new Tuple2<>( | |
((ParseResult.Success<A>)ra).value, | |
((ParseResult.Success<A>)rb).value | |
), | |
((ParseResult.Success<A>)rb).next | |
); | |
} else { | |
return rb; | |
} else { | |
return ra; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package parser; | |
public class Cat<X, Y> implements Parser<Tuple2<X, Y>> { | |
private Parser<X> lhs; | |
private Parser<Y> rhs; | |
public Cat(Parser<X> lhs, Parser<Y> rhs) { | |
this.lhs = lhs; | |
this.rhs = rhs; | |
} | |
@Override | |
public ParseResult<Tuple2<X, Y>> invoke(String input) { | |
ParseResult<X> lresult = lhs.invoke(input); | |
if(lresult instanceof ParseResult.Success<?>) { | |
X value1 = ((ParseResult.Success<X>)lresult).value; | |
String next = ((ParseResult.Success<X>)lresult).next; | |
ParseResult<Y> rresult = rhs.invoke(next); | |
if(rresult instanceof ParseResult.Success<?>) { | |
Y value2 = ((ParseResult.Success<Y>)rresult).value; | |
return new ParseResult.Success<>( | |
new Tuple2<>(value1, value1), | |
((ParseResult.Success<Y>)rresult).next | |
); | |
} else { | |
return rresult; | |
} | |
} else { | |
return lresult; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package parser; | |
public interface Parser<T> { | |
ParseResult<T> invoke(String input); | |
static Parser<String> string(String literal) { | |
return new StringParser(literal); | |
} | |
default <U> Parser<Tuple2<T, U>> cat(Parser<U> rhs) { | |
return new Cat<>(this, rhs); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package parser; | |
public class Main { | |
public static void main(String[] args) { | |
Parser<String> hello = Parser.string("Hello, "); | |
Parser<String> world = Parser.string("World!"); | |
Parser<Tuple2<String, String>> helloWorld = hello.cat(world); | |
ParseResult.Success<Tuple2<String, String>> success = (ParseResult.Success<Tuple2<String, String>>)helloWorld.invoke("Hello, World!"); | |
assert "Hello, ".equals(success.item1); | |
assert "World!".equals(success.item2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment