Dan
Dan

Reputation: 1813

Capturing all occurrences of interleavened nodes with StandardTokenParsers in Scala

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

Answers (1)

Régis Jean-Gilles
Régis Jean-Gilles

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

Related Questions