Reputation: 1813
I'm learning how to use Parsers in Scala, and I'm trying to build a parser (extending from StandardTokenParsers) for a text file that can have occurrences of the same node type with other node types in between. For example:
[NodeA] ...
[Node B] ...
[Node A] ...
[Node A] ...
[Node A] ...
How can I capture all instances of Node A and store them on a collection? I think repsep can only capture sequential instances.
At the end, I want to be able to store all instances of Nodes in different collections.
Is this possible?
Upvotes: 0
Views: 124
Reputation: 32719
What you want is a parser that accept a sequence of either [NodeA] or [NodeB].
All you need, given a parser nodeAParser
and a parser nodeBParser
, is use the |
combinator to parse for either [NodeA] or [NodeB] ( nodeAParser | nodeBParser
), and then use combinator *
to accept a sequence of that ( (nodeAParser | nodeBParser).*
).
Some dummy example:
import scala.util.parsing.combinator.syntactical._
import scala.util.parsing.input._
abstract sealed class Node
case object NodeA extends Node
case object NodeB extends Node
object MyParser extends StandardTokenParsers {
lexical.delimiters ++= Seq("[", "]")
lexical.reserved ++= Seq("NodeA", "NodeB")
lazy val nodeAP: Parser[Node] = "[" ~ "NodeA" ~ "]" ^^ { case _ => NodeA }
lazy val nodeBP: Parser[Node] = "[" ~ "NodeB" ~ "]" ^^ { case _ => NodeB }
lazy val nodesP: Parser[List[Node]] = phrase((nodeAP | nodeBP).*)
def parse( s: String ) = { nodesP( new lexical.Scanner( s ) ) }
}
MyParser.parse(
"""
[NodeA]
[NodeB]
[NodeA]
[NodeA]
[NodeA]
"""
)
Upvotes: 1