How can I create a parser combinator in which line endings are significant?

前端 未结 2 1947
名媛妹妹
名媛妹妹 2020-12-31 04:51

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

2条回答
  •  情书的邮戳
    2020-12-31 05:26

    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
    }
    

提交回复
热议问题