2

What is the correct way to parse a list consuming all but the last element using scala parser-combinators? For example, if I want to parse "spam spam spam spam spam and eggs" into List("spam", "spam", "spam", "spam") ~ "spam and eggs".

If I just use "spam".+, then all the spam is consumed before I get to match "spam and eggs". Naturally, I could match on "and eggs" but in practice I might already have a complicated "spam and eggs" parser that I'd rather not alter.

2
  • It isn't a complete answer but ("spam and eggs" | "spam").+ would work for this case, if accepting "spam and eggs spam" etc. is acceptable. If not and nobody does earlier, I'll try to answer tomorrow. Commented Feb 14, 2020 at 21:03
  • The best I came up with was def allButOne[T](p:Parser[T]):Parser[List[T]] = ((p ~ guard(p) ~ allButOne(p)) ^^ { case a ~ b ~ c => List(a) ++ c })|(p <~ guard(p) ^^ { a => List(a) }) but wondered if there was a more natural pattern. Commented Feb 14, 2020 at 21:18

1 Answer 1

3

Here is a simple but inefficient version:

def allButOne[T](p: Parser[T]): Parser[List[T]] = (p <~ guard(p)).+
Sign up to request clarification or add additional context in comments.

1 Comment

That's far more elegant. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.