2012-09-19 119 views
1

我在使用一種特質時從另一個特性中的方法返回的解析器遇到問題。編譯器抱怨類型不匹配,在我看來,問題是由於路徑依賴類。我不知道如何得到我想要的。由路徑依賴類型挫敗

trait Outerparser extends RegexParsers { 

    def inner: Innerparser 

    def quoted[T](something: Parser[T]) = "\"" ~> something <~ "\"" 
    def quotedNumber = quoted(inner.number)  // Compile error 
    def quotedLocalNumber = quoted(number)  // Compiles just fine 
    def number: Parser[Int] = ("""[1-9][0-9]*"""r) ^^ {str => str.toInt} 

} 

trait Innerparser extends RegexParsers { 

    def number: Parser[Int] = ("""[1-9][0-9]*"""r) ^^ {str => str.toInt} 

} 

和錯誤:

[error] /Path/to/MyParser.scala:6: type mismatch 
[error] found : minerals.Innerparser#Parser[Int] 
[error] required: Outerparser.this.Parser[?] 
[error] def quotedNumber = quoted(inner.number) 

我排序的得到的想法:每個「東西」方法定義語法分析器類型,其路徑是特定的封裝類(Outerparser或Innerparser)。 Outerparser的「quoted」方法需要一個類型爲Outerparser.this.Parser的實例,但得到的是Innerparser#Parser。

我喜歡能夠使用從此類或其他類獲得的解析器引用。我怎樣才能做到這一點?

回答

1

您可以使用自己類型的註釋,使其編譯同時仍然保持模塊化:

trait OuterParser extends RegexParsers { this: InnerParser => 
    def quoted[T](something: Parser[T]) = "\"" ~> something <~ "\"" 
    def quotedNumber = quoted(number)  // Compile error 
} 

trait InnerParser extends RegexParsers { 
    def number: Parser[Int] = ("""[1-9][0-9]*"""r) ^^ {str => str.toInt} 
} 

object MyCompleteParser extends OuterParser with InnerParser 

自我類型註釋基本上說OuterParser依賴InnerParser(它們必須混合在一起才能創建適當的實例化類)。編譯器因此確切知道在OuterParser和InnerParser中,Parser指向相同的類型。

2

是好還是壞,你通常使用Scala的解析器組合庫的方法是在一個封閉的特質來包裝的一切或對象extendsRegexParsers一個特點。我不太確定爲什麼API是這樣設計的。

但是,不管怎樣,一旦他們都屬於RegexParsers同一實例,他們都看到相同Parser類型:

trait Everything extends RegexParsers { 
    trait Outerparser { 
     ... 
    } 

    trait Innerparser { 
     ... 
    } 
} 

而且每個人都高興。


不要以爲它把所有東西放在同一個範圍內;把它看作導入名稱的解析器組合子API的古怪的方式,也就是說,你可以很容易地做到

import scala.util.parsing.combinator._ 
import scala.util.parsing.input._ 

object blah extends RegexParsers 
import blah._ 

trait Outerparser { 
    ... 
} 

trait Innerparser { 
    ... 
} 
+0

我不想把我所有的解析代碼放到同樣的範圍內。任何其他想法? – Ladlestein