I know the difference between def
and val
and lazy val
in general, but I'm not sure about their repercussions when it comes to Parser Combinators. All examples I have seen contain code like this:
def statement: Parser[Statement] =
ifStatement |
whileStatement |
expressionStatement | ...
From a few experiments I have done, it seems val
and lazy val
work as well, but I'm not sure if there are cases where they wouldn't work anymore, like recursion or positioned parsers or whatnot.
Please enlighten me!
If you look at the api documentation, the parser-building methods and operators are implemented using by-name parameters which are then cached using
lazy val
.That being said, you still have to be careful about order of initialization. The following code will result in a null reference exception:
However the following is fine (because the argument to
~
is by-name):Putting
lazy
in front of everything will 'help', but is noisy. Performance should not be a big deal, as generally you will only want to initialize the grammar once.def
expressions will be initialized once for each point they are referenced.You can be a bit clever and eliminate plumbing for your 'minor' productions using block syntax: