From: Francis Russell Date: Tue, 20 Dec 2011 19:56:33 +0000 (+0000) Subject: Handle parse errors more nicely. X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=38ce1b36ff2e8458503b913414e2f4e9e5ae91af;p=francis%2Fofc.git Handle parse errors more nicely. --- diff --git a/src/ofc/OFC.scala b/src/ofc/OFC.scala index 7d42620..9653e70 100644 --- a/src/ofc/OFC.scala +++ b/src/ofc/OFC.scala @@ -1,12 +1,26 @@ package ofc import java.io.FileReader -import parser.Parser +import parser.{Parser,Statement,ParseException} object OFC extends Parser { def main(args: Array[String]) { if (args.isEmpty) throw new IllegalArgumentException("Unspecified input file.") + val reader = new FileReader(args(0)) - println(parseAll(program, reader)) + + try { + val program = parseProgram(reader) + processAST(program) + } catch { + case e: ParseException => { + Console.err.println("Parse failure: "+e) + System.exit(1) + } + } finally { + reader.close + } } + + def processAST(statements : List[Statement]) = print(statements.mkString("\n") + "\n") } diff --git a/src/ofc/parser/Parser.scala b/src/ofc/parser/Parser.scala index 92fe892..b22ea74 100644 --- a/src/ofc/parser/Parser.scala +++ b/src/ofc/parser/Parser.scala @@ -1,11 +1,17 @@ package ofc.parser - import scala.util.parsing.combinator._ +import scala.util.parsing.input.Position +import java.io.Reader sealed abstract class ScalarOperationTag case class MultiplicationTag() extends ScalarOperationTag case class DivisionTag() extends ScalarOperationTag +class ParseException(message: String, pos: Position) extends Exception { + override def toString : String = + message + " at line " + pos.line + ", column " + pos.column + "." +} + class Parser extends JavaTokenParsers { def program : Parser[List[Statement]] = rep(comment | declarations | definition | target | comment | specifics) def comment : Parser[Comment] = "#"~!".*".r ^^ (v => new Comment(v._2)) @@ -51,4 +57,11 @@ class Parser extends JavaTokenParsers { def stringParameter : Parser[StringParameter] = stringLiteral ^^ (x => new StringParameter(x.slice(1, x.length-1))) def numericParameter : Parser[NumericParameter] = floatingPointNumber ^^ (x => new NumericParameter(x.toDouble)) def parameterList : Parser[ParameterList] = "["~>repsep(functionParameter, ",")<~"]" ^^ (x => new ParameterList(x)) + + def parseProgram(in: Reader) : List[Statement] = + parseAll(program, in) match { + case Success(result, _) => result + case r : NoSuccess => + throw new ParseException(r.msg, r.next.pos) + } }