Lyubomyr Shaydariv Lyubomyr Shaydariv - 11 months ago 78
Java Question

How do I extract all values from a sequenced parser in JParsec?

I have a JParsec parser that consists of a few "smaller" parsers, and I would like to extract the total value parsed with those parsers. Let's say:

// V-- because of sequence()
private static final Parser<Object> definitionParser = sequence(
substitute, separator, digits4, separator, digits2, separator, description.optional()

Some of the parsers above are dummy and are used to delimit data fields. The dummy parsers are
, and I'm not going to extract anything from them. However, the rest of the parsers makes the interest to me:

private static final Parser<Short> digits4 = ...; // 4 hex digits, just a short value
private static final Parser<Byte> digits2 = ...; // 2 hex digits, just a byte value
private static final Parser<String> description = ...; // arbitrary string

ping the
parser requires a
Map<Object, Definition>
interface implementation propagating the result of the very last sequenced parser
to the
implementation, and the incoming argument is a

private static final Parser<Definition> definitionParser = sequence(
substitute, separator, digits4, separator, digits2, separator, description.optional()
).map(new Map<Object, Definition>() {
public Definition map(final Object o) {
... o is a String here because description.optional() is the last one

Obviously, I can only extract
value here, but I can't find a way to reach the
parsers results. I'm wondering: is it possible to extract
values into a single
object using the approach above? I was thinking of a
builder implementation and passing it through the parsers chain somehow too. Or should it be rethought, and if so, then how?

Answer Source

If you want to use the return values of some or all of your parsers, then sequence(Parser<?> ... parsers) is not the combinator you should use. Depending on the number of parsers you want to combine, you can use one of:

  • The overriden sequence() combinators from 2 to 5 parsers, to which you can apply the appropriate map(),
  • The list() combinator which returns your parsers' results in a List<Object>,
  • The array() combinator which returns an Object[]
  • The tuple() combinators which return from 2 to 5-tuples.

For separator tokens, you could benefit from using Parser.sepBy() or Parser.followedBy(): This would allow you to have a shorter sequence() with only relevant results.