2014-01-24 1 views
5

이미 토큰 목록 (문자가 아님)이있는 경우 scala 파서 연결자 API가 사용되는 방식을 이해하기 위해 노력합니다. TokenParsers의 소스 코드를 살펴 보았습니다. 그러나 "어휘"멤버가 무엇인지, 독자 구현 (또는 파서에서 소비 한 토큰을 얻는 또 다른 방법)을 어떻게 플러그인 할 수 있는지 이해하지 못했습니다.Parsers 하위 클래스와 사용자 정의 토크 나이저 연결

온라인에서 사용할 수있는 예제 (Odersky 외의 "Programming in 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

관련 문제