Alok
Alok

Reputation: 1506

Scala Parser Combinators :Handling Repetition of a type

I am new to scala language and its parser combinators. I was working on a task and got stuck at a requirement: My requirement is to get repetitive Type for eg: I created parser for logical operator and word (which means string)

def logicalOperator:Parser[Operator] = "(&&|\\|\\|)".r ^^ {case op => Operator(op)} 

def word: Parser[word] = """[a-z\\\s]+""".r ^^ { case x => word(x) }

Now My input may contain a single word or repetitive words separated by multiple operators. For ex:

   input1=> once&&upon||time||forest.

    input2=> therewasatime // this is also a valid input , it does not have any operators

I would process words as per the operators between them.In case there is no operator present (i.e input is a single word , I would process on single word).

&& operator and || operator would decide the operation. (we can consider it to be  similar to && and || operator in case of boolean values , to understand clearly )

I was thinking of a case class Sentence , which would represent a single word as well as multiple words . And in case of multiple words it would contain operator.In case single word, operator and second word would be null

case class Sentence(word1:Word, op:Operator, word2:Word).

So this would be a tree structure with leaf node contains only Word and rest nodes would contain operators.

But I am not sure how to write Sentence Parser. I tried using :

def sentence = repsep(word,logicalOperator)^^{// creating sentence object here}.

But I cannot extract operator from repsep() operation.

Any suggestion for this case ?

thanks

Upvotes: 0

Views: 354

Answers (1)

corvus_192
corvus_192

Reputation: 422

The problem with repsep is that is discards the result of its second argument, you won't be able to identify which operator was used. Another things is: How do you want once&&upon||time||forest to be represented, if Sentence can only contain Words, not other Sentences. In the following, I assumed you meant something like this:

trait Node
case class Operator(s: String)
case class Word(s: String) extends Node
case class Sentence(a: Node, op: Operator, b: Node) extends Node

Then you can write sentence like this:

def sentence: Parser[Node] = word ~ opt(logicalOperator ~ sentence) ^^ {
    case w ~ Some(op ~ sentence) ⇒ Sentence(w, op, sentence)
    case w ~ None                ⇒ w
}

With this method, once&&upon||time||forest is parsed as

Sentence(
    Word(once),
    Operator(&&),
    Sentence(
        Word(upon),
        Operator(||),
        Sentence(
            Word(time),
            Operator(||),
            Word(forest)
        )
    )
)

Upvotes: 0

Related Questions