Scala Parser,为什么不"轻拍<~pat~> pat"工作?

Sur*_*apu 3 scala parser-combinators

试用一个简单的解析器组合器,我遇到了编译错误.

我想解析一下 - "Smith,Joe"进入Name对象,如Name(Joe,Smith).我想这很简单.

这是与之相关的代码:

    import util.parsing.combinator._

    class NameParser extends JavaTokenParsers {
      lazy val name: Parser[Name] = 
        lastName <~ "," ~> firstName ^^ {case (l ~ f) => Name(f, l)}
      lazy val lastName = stringLiteral
      lazy val firstName = stringLiteral
    }

    case class Name(firstName:String, lastName: String)
Run Code Online (Sandbox Code Playgroud)

我正在测试它

object NameParserTest {
  def main(args: Array[String]) {
    val parser = new NameParser()
    println(parser.parseAll(parser.name, "Schmo, Joe"))
  }
}
Run Code Online (Sandbox Code Playgroud)

获取编译错误:

error: constructor cannot be instantiated to expected type;
found   : NameParser.this.~[a,b]
required: java.lang.String
lazy val name: Parser[Name] = lastName <~ "," ~> firstName ^^ {case (l ~ f) => Name(f, l)}
Run Code Online (Sandbox Code Playgroud)

我在这里失踪的是什么?

Rac*_*lit 8

在这一行:

  lazy val name: Parser[Name] = 
    lastName <~ "," ~> firstName ^^ {case (l ~ f) => Name(f, l)}
Run Code Online (Sandbox Code Playgroud)

你不想同时使用<~~>.您正在创建一个仅匹配","firstName保留的解析器,","然后您将创建一个匹配lastName的解析器和之前的解析器并仅保留lastName.

您可以将其替换为:

(lastName <~ ",") ~ firstName ^^ {case (l ~ f) => Name(f, l)}
Run Code Online (Sandbox Code Playgroud)

但是,虽然这将按照您想要的方式进行编译和组合,但它不会解析您想要的内容.我尝试时得到了这个输出:

[1.1] failure: string matching regex `"([^"\p{Cntrl}\\]|\\[\\/bfnrt]|\\u[a-fA-F0-9]{4})*"' expected but `S' found

Schmo, Joe
^
Run Code Online (Sandbox Code Playgroud)

stringLiteral期望在代码中看起来像字符串文字的东西(引号中的东西).(JavaTokenParsers旨在解析看起来像Java的东西.)这有效:

scala> val x = new NameParser
x: NameParser = NameParser@1ea8dbd

scala> x.parseAll(x.name, "\"Schmo\", \"Joe\"")
res0: x.ParseResult[Name] = [1.15] parsed: Name("Joe","Schmo")
Run Code Online (Sandbox Code Playgroud)

您应该用一个正则表达式替换它,该正则表达式指定您将接受名称的字符串类型.如果你看一下这里的文档,你会看到:

implicit def regex (r: Regex) : Parser[String]

A parser that matches a regex string
Run Code Online (Sandbox Code Playgroud)

所以你可以把一个Regex对象放在那里,它将被转换成一个匹配它的解析器.


Mar*_*ing 7

~>组合子忽略了左侧和<~组合子忽略右侧.所以结果lastName <~ "," ~> firstName不能包括的结果firstNamelastName.实际上只有lastName因为"," ~> firstName被忽略的解析结果.您需要在此处使用顺序合成:

lazy val name: Parser[Name] =         
  lastName ~ "," ~ firstName ^^ {case (l ~_~ f) => Name(f, l)}
Run Code Online (Sandbox Code Playgroud)

或者如果你想要一个更漂亮的模式匹配:

lazy val name: Parser[Name] =         
  lastName ~ ("," ~> firstName) ^^ {case (l ~ f) => Name(f, l)}
Run Code Online (Sandbox Code Playgroud)