Jan*_*ano 21 scala parser-combinators
我是相当新的Scala和一边念叨解析器组合(魔术解析器组合的背后,在斯卡拉领域特定语言),我遇到的方法定义来是这样的:
def classPrefix = "class" ~ ID ~ "(" ~ formals ~ ")"
Run Code Online (Sandbox Code Playgroud)
我一直在阅读scala.util.parsing.Parsers的API文档,它定义了一个名为(代字号)的方法,但我仍然不能理解它在上面例子中的用法.在该示例中(代字号)是在java.lang.String上调用的方法,该方法没有该方法并导致编译器失败.我知道(代字号)被定义为
case class ~ [+a, +b] (_1: a, _2: b)
Run Code Online (Sandbox Code Playgroud)
但是这对上面的例子有什么帮助呢?
如果有人能给我一些提示来了解这里发生了什么,我会很高兴.非常感谢你提前!
一月
Rex*_*err 30
这里的结构有点棘手.首先,请注意,您始终在某个解析器的子类中定义这些内容,例如class MyParser extends RegexParsers.现在,您可能会注意到两个隐含的定义RegexParsers:
implicit def literal (s: String): Parser[String]
implicit def regex (r: Regex): Parser[String]
Run Code Online (Sandbox Code Playgroud)
这些将做什么是采取任何字符串或正则表达式并将它们转换为匹配该字符串或正则表达式作为标记的解析器.它们是隐含的,因此它们将在需要时随时应用(例如,如果你在Parser[String]其上调用方法String(或Regex)没有).
但这是什么Parser东西?这是一个内部定义的内部类Parsers,超级用于RegexParser:
class Parser [+T] extends (Input) ? ParseResult[T]
Run Code Online (Sandbox Code Playgroud)
看起来它是一个接受输入并将其映射到结果的函数.嗯,这很有道理!你可以在这里看到它的文档.
现在我们可以查看~方法:
def ~ [U] (q: ? Parser[U]): Parser[~[T, U]]
A parser combinator for sequential composition
p ~ q' succeeds if p' succeeds and q' succeeds on the input left over by p'.
Run Code Online (Sandbox Code Playgroud)
所以,如果我们看到类似的东西
def seaFacts = "fish" ~ "swim"
Run Code Online (Sandbox Code Playgroud)
会发生什么,首先,"fish"没有~方法,所以它被隐式转换为Parser[String].~然后该方法需要一个类型的参数Parser[U],因此我们隐式转换"swim"为Parser[String](即U== String).现在我们有一些匹配输入的东西,输入"fish"中剩下的东西应该匹配"swim",如果两者都是,那么seaFacts它将在匹配中成功.
Did*_*ont 13
~解析器上的方法将两个解析器组合在一起,连续应用两个原始解析器并返回两个结果.这可能只是(在Parser[T])
def ~[U](q: =>Parser[U]): Parser[(T,U)].
Run Code Online (Sandbox Code Playgroud)
如果你从未组合过两个以上的解析器,那就没问题了.但是,如果您将他们三人p1,p2,p3,与返回类型T1,T2,T3,那么p1 ~ p2 ~ p3,这意味着p1.~(p2).~(p3)是类型Parser[((T1, T2), T3)].如果你把它们中的五个组合起来就像你的例子那样Parser[((((T1, T2), T3), T4), T5)].然后,当你对结果进行模式匹配时,你也会拥有所有这些parantheses:
case ((((_, id), _), formals), _) => ...
Run Code Online (Sandbox Code Playgroud)
这非常不舒服.
然后是一个聪明的句法技巧.当案例类有两个参数时,它可以显示在中缀而不是模式中的前缀位置.也就是说,如果你有
case class X(a: A, b: B),你可以模式匹配case X(a, b),但也可以case a X b.(这是使用x::xs匹配非空List 的模式完成的,::是一个案例类).当你写出案例时a ~ b ~ c,它意味着case ~(~(a,b), c),但是更愉快,更令人愉快case ((a,b), c),这对于正确而言是棘手的.
因此~Parser中的方法返回a Parser[~[T,U]]而不是a Parser[(T,U)],因此您可以轻松地对多个〜的结果进行模式匹配.在那旁边, ~[T,U]并且(T,U)是几乎同样的事情,因为同构的,你可以得到.
在解析器和结果类型中为组合方法选择相同的名称,因为生成的代码很自然.人们可以立即看到结果处理中的每个部分如何与语法规则的项目相关.
parser1 ~ parser2 ~ parser3 ^^ {case part1 ~ part2 ~ part3 => ...}
Run Code Online (Sandbox Code Playgroud)
选择Tilda是因为它的优先级(紧密绑定)与解析器上的其他运算符很好地配合.
最后一点,有辅助运算符~>,<~它们丢弃操作数之一的结果,通常是规则中不包含有用数据的常量部分.所以人们宁愿写信
"class" ~> ID <~ ")" ~ formals <~ ")"
Run Code Online (Sandbox Code Playgroud)
并在结果中仅获取ID和formals的值.
| 归档时间: |
|
| 查看次数: |
10121 次 |
| 最近记录: |