I am trying to write a simple parser for version numbers using JParsec 3. The version numbers look like:
123
1.2.3
123.4
The rule is:
Up to three non-negative integers, separated by
.
I have a Version
class
with three factory methods:
Version.of(int major)
Version.of(int major, int minor)
Version.of(int major, int minor, int patch)
I would like to write a parser for versions of any of the three types.
Here is what I have so far:
static final Parser<Integer> integerParser = Scanners.INTEGER
.map(x -> Integer.parseUnsignedInt(x));
static final Parser<Version> versionParser1 =
integerParser.map(x -> Version.of(x));
static final Parser<Version> versionParser2 =
Parsers.sequence(
integerParser.followedBy(Scanners.isChar('.')),
integerParser)
.map(x -> Version.of(x.get(0), x.get(1)));
static final Parser<Version> versionParser3 =
Parsers.sequence(
integerParser.followedBy(Scanners.isChar('.')),
integerParser.followedBy(Scanners.isChar('.')),
integerParser)
.map(x -> Version.of(x.get(0), x.get(1), x.get(2)));
public static final Parser<Version> versionParser =
versionParser1.or(versionParser2).or(versionParser3);
This doesn't actually compile, because where I have x.get(0)
, x
is an Integer
.
How should I be using JParsec here?
You can use the Parsers.sequence(p1,p2,...,map)
functions instead. The Parsers.sequence(p1...).map(f)
behaviour is to drop the output of all parsers but the last. Then combine all parsers using a different combinator than or()
because it will fail if parsers consume input but do not succeed. A possible solution is
public static final Parser<Version> versionParser =
Parsers.longest(versionParser1, versionParser2, versionParser3);