2010-07-21 2 views
2

스칼라 파서 결합자를 사용할 때 내 Lexer에서 파서로 오는 토큰 시퀀스를 어떻게 필터링합니까?스칼라 파서 결합 자의 토큰 필터링

내가 설명하자면 - 상당히 표준적인 패턴의 렉서 (확장형 StdLexical)와 파서 (확장형 StdTokenParsers)가 있다고 가정 해 보겠습니다. 렉서는 일련의 문자를 일련의 토큰으로 변환 한 다음 파서가 토큰 시퀀스를 추상 구문 트리 (유형이 Expr)로 바꿉니다.

스트림의 어느 곳에서나 발생할 수있는 일부 토큰은 필터링 할 수있는 옵션이 있기 때문에 Lexer와 Parser가 이러한 토큰을 제거하는 기능을 원합니다. 예를 들어, 렉서가 주석을 토큰 화하고 나중에이 주석을 필터링하도록 할 수 있습니다.

이 필터를 작성하는 가장 좋은 방법은 무엇입니까? 이것은 파서 결합 자 관용구를 사용할 수 있지만 그렇게 할 필요는 없습니다.

샘플 현재 코드 :

val reader = new PagedSeqReader(PagedSeq.fromReader(reader)) 
val tokens = new MyParser.lexical.Scanner(reader) 
val parse = MyParser.phrase(parser)(filter(tokens)) 

답변

1

당신이 공백과 주석을 제거하는 RegexParsers를 사용하여 생각 해 봤나 :

val reader = new PagedSeqReader(PagedSeq.fromReader(reader)) 
val tokens = new MyParser.lexical.Scanner(reader) 
val parse = MyParser.phrase(parser)(tokens) 

나는 이런 식으로 뭔가를 쓸 수 있도록하고 싶습니다?

편집하는 것은

당신은 간단한 필터를

import scala.util.parsing.input._ 

object ReaderFilter { 
    def filter[T](reader: Reader[T], check: T => Boolean): Reader[T] = { 
    new Reader[T] { 
     var orig = reader 
     def first = { trim; orig.first } 
     def atEnd = { trim; orig.atEnd } 
     def rest: Reader[T] = { trim; ReaderFilter.filter(orig.rest, check) } 
     def pos = orig.pos 
     private def trim = { 
     while (!orig.atEnd && !check(orig.first)) 
      orig = orig.rest 
     } 
    } 
    } 
} 

을 할 수 있으며 ("#"있는 토큰을 제거하기 위해)이 방식을 사용

val tokens = ReaderFilter.filter(new MyParser.lexical.Scanner(reader), 
      {t:ExprParser.lexical.Token => t.chars != "#"}) 
+0

나는 이미 적절하게 처리하고 있습니다. 질문에 설명 된대로 필터를 작성하고 싶습니다. 응용 프로그램이 주석을 제거하지 않고 있습니다. 이것은 문제를 설명하는 가장 쉬운 방법 일뿐입니다. –

+0

나는 그것을 직접 썼다. 그리고 돌아와서 편집했다고 깨달았다. 당신은 그 코드가 어떻게 비슷한지 흥미로운 대답을 할 수 있습니다. 재귀를 사용하고 while 루프를 사용했지만 그 외에도 거의 동일합니다 :-) –

2

나 ' 지금 해봤 어, 결과는 여기있다. 핵심 통찰력은 파서 결합 자의 파서가 scala.util.parsing.input.Reader을 입력으로 사용한다는 것입니다. 따라서 우리는 Reader을 래핑하는 클래스가 필요하며, 그 자체는 어떤 조건에서 엔트리를 걸러내는 Reader입니다.

작성시 Reader을 작성하므로 원하지 않는 모든 항목을 건너 뛰고 첫 번째 항목이나 끝에서 중지합니다. 그런 다음 모든 호출은 rest을 제외하고는 원래의 독자에게 위임되며 다른 TokenFilter를 차례로 생성합니다.

import scala.util.parsing.input._ 

class Filter[T](parent : Reader[T], exclude : T=>Boolean) extends Reader[T] { 
    private val start = nextOk(parent) 
    def nextOk(r : Reader[T]) : Reader[T] = 
    if(r.atEnd) r else (if (exclude(r.first)) nextOk(r.rest) else r) 

    override def source = start.source 
    override def offset: Int = start.offset 
    override def first: T = start.first 
    override def rest: Reader[T] = new Filter(start.rest, exclude) 
    override def pos: Position = start.pos 
    override def atEnd = start.atEnd 
}