Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how do i throw exceptions with meaningful messages with a scala combination parser?

I'd like to throw an exception when the language doesn't conform to the grammar for a scala combination parser. Here's an example of a rule:

def record: Parser[Record] = "-" ~ opt(recordLabel) ~ repsep(column, ",") ^^ {
    case "-" ~ label ~ columns => new Record(label, columns)
}

Let's say in the repsep(column, ",") part, they accidently make a string like this

a, b, c, d,

This is not valid because it ends with a "," that isn't suppose to be there. Rather than the parser just stopping when you call parseAll(), how do you make this throw a meaningful exception that is human readable? (Custom text, line number, etc.)

EDIT: Okay, I found something that works, but I am not satisfied with it's customizability:

def loadFrom(filename: String) {
    val source = 
        Source.fromFile(filename).getLines.mkString("\n")
    val parseResult = parseAll(tables, source)
    if(!parseResult.successful) {
        throw new TestDataParseException(parseResult.toString)
    }
}

The toString prints an okay message, but it prints weird stuff like wanting "\z" when it found a space instead (which sometimes looks like a block/square in my IDE). I'd rather say, "Hey, you forgot a comma!"

The line numbers/columns do print out in the form of [x.y]. I'd actually like to show [Line: x, Column: y] because people will know what that is more intuitively.

Thanks

like image 817
egervari Avatar asked Oct 21 '10 00:10

egervari


1 Answers

parseAll(tables, source) match {
  case Success(ast, _) => //do something
  case NoSuccess(msg, next) => {
        println("Failed at line %s, column %s: %s".format(
                    next.pos.line, next.pos.column, msg))
  }
}
like image 109
Marimuthu Madasamy Avatar answered Nov 09 '22 17:11

Marimuthu Madasamy