Scala Parser Problems

I'm having trouble testing the Scala Parser Combinator feature for a simple DSL book.

Firstly, there is a book class:

case class Book (name:String,isbn:String) {
def getNiceName():String = name+" : "+isbn
}

Next, there is a simple parser:

object BookParser extends StandardTokenParsers {
  lexical.reserved += ("book","has","isbn")

  def bookSpec  = "book" ~> stringLit ~> "has" ~> "isbn" ~> stringLit ^^ {
            case "book" ~ name ~ "has" ~ "isbn" ~ isbn => new Book(name,isbn) }

  def parse (s: String) = {
    val tokens = new lexical.Scanner(s)
    phrase(bookSpec)(tokens)
  }

  def test (exprString : String) = {
     parse (exprString) match {
         case Success(book) => println("Book"+book.getNiceName())
     }
  }

  def main (args: Array[String]) = {
     test ("book ABC has isbn DEF")
  }   
}

I get a number of errors trying to compile this - some that seem strange to me when trying to decompose other examples on the Internet. For example, is bookSpec almost identical to other examples?

Is this the best way to create a simple parser?

thanks

+5
source share
2 answers

You are on the right track. There are several problems with your parser. I will send the corrected code and then explain the changes.

import scala.util.parsing.combinator._
import scala.util.parsing.combinator.syntactical._

case class Book (name: String, isbn: String) {
  def niceName = name + " : " + isbn
}


object BookParser extends StandardTokenParsers {
  lexical.reserved += ("book","has","isbn")

  def bookSpec: Parser[Book]  = "book" ~ ident ~ "has" ~ "isbn" ~ ident ^^ {
            case "book" ~ name ~ "has" ~ "isbn" ~ isbn => new Book(name, isbn) }

  def parse (s: String) = {
    val tokens = new lexical.Scanner(s)
    phrase(bookSpec)(tokens)
  }

  def test (exprString : String) = {
     parse (exprString) match {
       case Success(book, _) => println("Book: " + book.niceName)
       case Failure(msg, _) => println("Failure: " + msg)
       case Error(msg, _) => println("Error: " + msg)
     }
  }

  def main (args: Array[String]) = {
     test ("book ABC has isbn DEF")
  }   
}

1. Return value of Parser

, inferencer. bookSpec : Parser [Book]. , , .

2. stringLit

stringLit StdTokenParsers. stringLit - , Parser [String], , , , . DSL, stringLit - , . stringLit ident. Java. ISBN, .: -)

ISBN, , idents.

3. -

~ > . , Parser [_] , , . , stringLit, , . , .

, ~ > < ~, .

.

4.

parse(). , Failure() Error(). , Success , Reader. , "_", .

, !

+15

~> <~, , . :

"book" ~> stringLit // discards "book"
"book" ~> stringLit ~> "has" // discards "book" and then stringLit
"book" ~> stringLit ~> "has" ~> "isbn" // discards everything except "isbn"
"book" ~> stringLit ~> "has" ~> "isbn" ~> stringLit // discards everything but the last stringLit

:

def bookSpec: Parser[Book] = ("book" ~> stringLit <~ "has" <~ "isbn") ~ stringLit ^^ {
  case name ~ isbn => new Book(name,isbn) 
}
+6

All Articles