I am creating a DSL, and using Scala\'s parser combinator library to parse the DSL. The DSL follows a simple, Ruby-like syntax. A source file can contain a series of blocks
I get the same error in both ways, but I think you are misinterpreting it. What it's saying is that it is expecting an end
, but it already reached the end of the input.
And the reason that is happening is that end
is being read as a statement. Now, I'm sure there's a nice way to solve this, but I'm not experienced enough with Scala parsers. It seems the way to go would be to use token parsers with a scanning part, but I couldn't figure a way to make the standard token parser not treat newlines as whitespace.
So, here's an alternative:
import scala.util.parsing.combinator.JavaTokenParsers
class ML3D extends JavaTokenParsers {
override val whiteSpace = """[ \t]+""".r
def keywords: Parser[Any] = "do" | "end"
def identifier: Parser[Any] = not(keywords)~ident
def model: Parser[Any] = commandList
def commandList: Parser[Any] = rep(commandBlock)
def commandBlock: Parser[Any] = command~"do"~eol~statementList~"end"~opt(eol)
def eol: Parser[Any] = """(\r?\n)+""".r
def command: Parser[Any] = commandName~opt(commandLabel)
def commandName: Parser[Any] = identifier
def commandLabel: Parser[Any] = stringLiteral
def statementList: Parser[Any] = rep(statement)
def statement: Parser[Any] = functionName~argumentList~eol
def functionName: Parser[Any] = identifier
def argumentList: Parser[Any] = repsep(argument, ",")
def argument: Parser[Any] = stringLiteral | constant
def constant: Parser[Any] = wholeNumber | floatingPointNumber
}
You can either override
the protected val whiteSpace
(a Regex) whose default is """\s+""".r
or override
the protected def handleWhiteSpace(...)
method if you need more control than is readily achieved with a regular expression. Both these members orginate in RegexParsers, which is the base class for JavaTokenParsers.