2014-01-24 24 views
5

我很難理解當你已經有一個標記列表(不是字符)時應該如何使用scala分析器組合器api。我查看了TokenParsers的源代碼,但我無法理解「詞法」成員是什麼,以及如何插入我自己的Reader實現(或以另一種方式獲取解析器消耗的令牌)。將自定義標記器與Parsers子類連接

在線提供的示例(以及Odersky等人在「Scala編程」一書中提供的示例)並沒有顯示如何在非字符標記中使用api。一些例子顯示解析器的一個子類必須將elem參數設置爲令牌的類型,但是其中是來自哪個令牌? Reader [MyToken]輸入參數在哪裏?

只是爲了澄清:詞法分析已經完成。刪除空白,分隔符,所有這些東西都已完成。我有一個令牌列表,只是想使用解析器組合器的好處來創建一個AST。該標記看起來有點像這樣:

sealed abstract class MyToken { 
    val line : Int 
    val col : Int 
} 
case class LPAREN (line : Int, col : Int) extends MyToken 
case class RPAREN (line : Int, col : Int) extends MyToken 

等等

回答

3

我想通了最後。 phrase()方法需要一個Reader參數,所以我可以包裝我的令牌流並調用它。

class MyParsers extends Parsers { 
    type Elem = MyToken 

    def parse(tokens: Iterable[MyToken]): ParseResult[Any] = { 
    val reader = new MyReader(tokens) 
    phrase(myGrammarRule)(reader) 
    } 

    // ...etc... 
} 

sealed class MyReader(tokens : Iterable[MyToken]) extends Reader[MyToken] { 
    def pos : Position = tokens.head 
    def atEnd : Boolean = tokens.isEmpty 
    def rest : Reader[MyToken] = new MyReader(tokens.tail) 
    def first : MyToken = tokens.head 
} 

sealed abstract class MyToken extends Position { 
    val _line : Int 
    val _col : Int 

    override def column = _col 
    override def line = _line 
    override def lineContents = "" 
} 

case class LPAREN (_line : Int, _col : Int) extends MyToken 
case class RPAREN (_line : Int, _col : Int) extends MyToken 

的位置混入是好的,因爲它允許解析器使用我的令牌已經存在的位置信息,而無需添加任何膠水。

+0

嗯,我想如果我實現lineContents()以及我會從解析器得到更好的診斷信息。 – esl

+0

感謝您的好例子。我一直在自己的自定義令牌解析器,但你的代碼更乾淨:) – michael