A parser combinator for Java 8. Proof of concept.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src/main/java/dk/ahnfelt/parsercombinator
.gitignore
README.md
pom.xml

README.md

parsercombinator

A parser combinator for Java 8. Working, but mostly a proof of concept.

import static dk.ahnfelt.parsercombinator.Parsers.*;
Parser<String> parseFoo = string("foo");
parseFoo.parse("foo") // returns "foo"
parseFoo.parse("bar") // throws Parsers.Failure
Parser<Integer> parseIntegerMatch = regex("[0-9]+").map(m -> Integer.parseInt(m.group()));
parseFoo.parse("42") // returns "42"
parseFoo.parse("bar") // throws Parsers.Failure
Parser<Pair<String, Integer>> parseFooN = parseFoo.then(parseInteger);
parseFoo.parse("foo7") // returns ("foo", 7)
Parser<Integer> parseFooN2 = skip(parseFoo).then(parseInteger);
parseFooN2.parse("foo7") // returns 7
Parser<String> parseFooOrBar = choice(string("foo"), string("bar"));
parseFoo.parse("foo") // returns "foo"
parseFoo.parse("bar") // returns "bar"
parseFoo.parse("quux") // throws Parsers.Failure
// Alternative version of the above
Parser<String> parseFooOrBar2 = 
    regex("[a-z]+").
    map(m -> m.group()).
    filter(t -> t.equals("foo") || t.equals("bar"));
Parser<Pair<Integer, Integer>> parsePlus = 
    parseInteger.
    skip(string("+")).
    then(parseInteger);
Parser<Integer> parseAndCompute = parsePlus.map(match((x, y) -> x + y));
parseAndCompute.parse("7+3") // returns 10
Parser<List<Integer>> parseList = parseInteger.zeroOrMore(string(","));
parseList.parse("1,2,4,8,16,32") // returns [1, 2, 4, 8, 16, 32]
Parser<String> parseToken = regex("\\s*([a-z0-9]+)\\s*").map(m -> m.group(1));
Parser<String> keyword(String name) { return parseToken.filter(t -> t.equals(name)); }

// The nested pairs can get hairy - use .map(match(...)) to get rid of them before you have to write types like this:
Parser<<Pair<Pair<String, String>, Optional<String>>> parseIf = 
    skip(keyword("if")).then(parseToken).
    skip(keyword("then")).then(parseToken).
    then(skip(keyword("else")).then(parseToken).optional()).
    skip(keyword("end"));

parseIf.parse("if x then y else z end") // returns (("x", "y"), Optional["z"])

Parser<String> parseIfAndCompute = 
    parseIf.map(match((x, y, z) -> x.equals("true") ? y : z.orElse("void")));

parseIfAndCompute.parse("if true then y else z end") // returns "y"
parseIfAndCompute.parse("if false then y end") // returns "void"