2009-11-23 5 views
7

다양한 "명령"문자열을 사용할 응용 프로그램을 작성하고 있습니다. 필자는 명령을 토큰 화하기 위해 Scala 결합 자 라이브러리를 살펴 보았습니다. 나는 많은 경우에 다음과 같이 말하고 싶다. "이 토큰은 질서없는 집합이므로 어떤 순서로도 나타날 수 있고 어떤 것은 나타나지 않을 수도있다". 문법의 내 현재의 지식으로그래머, 스칼라 파싱 연결자 및 주문없는 세트

나는 그런 (의사 문법)로 시퀀스의 모든 조합을 정의해야합니다 :

그래서 제 질문은, tokenA-C가 고유 고려, 짧은 방법이있다
command = action~content 
action = alphanum 
content = (tokenA~tokenB~tokenC | tokenB~tokenC~tokenA | tokenC~tokenB~tokenA .......) 

문법을 사용하여 어떤 순서의 집합을 정의 하는가?

답변

3

주위에 방법이 있습니다. 예를 들어 파서 here을 살펴보십시오. 사전 정의 된 4 개의 숫자를 받아들이며, 다른 숫자에는 나타날 수 있지만 한 번만 나타나야합니다. 이 패턴이 자주 발생하는 경우

OTOH, 당신은, 연결자를 작성할 수

def comb3[A](a: Parser[A], b: Parser[A], c: Parser[A]) = 
    a ~ b ~ c | a ~ c ~ b | b ~ a ~ c | b ~ c ~ a | c ~ a ~ b | c ~ b ~ a 
0

이 상황이 자주 발생하면이 작업을 수행하는 조합 규칙을 작성할 수 있습니다. 한편

는 아마도 옵션은 "tokenA..C"그냥 "토큰"을하고 다음의 핸들러 내에서 차별화 할 수있는 나는 당신이 원하는 구조의 종류를 모르는

+0

이 경우 각 토큰은 json 스타일의 개체 속성입니다. 따라서 명령은 "todo message : 데이터베이스에 Todo 클래스를 연결"due : next tuesday와 같이 보일 수 있습니다. 따라서 스칼라 스타일로 정의 된 일반 규칙은 "token = alphanum ~ ':'~ repsep (alphanum, '')과 유사합니다. 하지만 특정 속성을 다르게 처리해야합니다. –

+0

그리고 같은 것을 두 번 이상 나오지 않도록해야합니까? – ziggystar

+0

그 계획이 맞습니다. 일부 속성은 선택 사항이며 한 번만 발생해야합니다. –

0

"토큰" 지원하기 위해,하지만 좀 더 구체적인 문법을 지정해야합니다.

잭 메시지 : 다른 대답에 귀하의 코멘트에서 데이터베이스에 링크 도도 클래스

난 당신이

잭 메시지 같은 것을 동의하고 싶지 않은 추측 : 데이터베이스 도도로를 링크 등급

"link"와 "to"와 같은 메시지 수준 키워드를 정의하고 싶을 것입니다 ...

def token = alphanum~':'~ "link" ~ alphanum ~ "class" ~ "to" ~ alphanum 
    ^^ { (a:String,b:String,c:String) => /* a == "message", b="Todo", c="database" */ } 

당신은 그 수준에서 문법을 정의해야 할 것입니다.

1

내가 구문이 요구 사항을 적용하려고하지 않을 것입니다. 필자는 허용 된 집합에서 여러 개의 토큰을 허용 한 다음 실제로 파싱 된 키워드의 수용 가능성을 확인하기 위해 비 파싱 방식을 사용하는 제작물을 작성합니다. 더 간단한 문법을 ​​허용하는 것 외에도 잘못된 사용법에 대한 진단을 내린 후 더 쉽게 파싱을 계속할 수 있습니다.

랜달 슐츠는

4

당신은 "파서. ^?"를 사용할 수 있습니다 연산자를 사용하여 중복 구문 분석 요소 그룹을 검사합니다.여기

def tokens = tokenA | tokenB | tokenC 
    def uniqueTokens = (tokens*) ^? (
    { case t if (t == t.removeDuplicates) => t }, 
    { "duplicate tokens found: " + _ }) 

는 임의의 순서로 네 코미디 중 하나를 입력 할 수 있습니다 예를하지만, 중복이 발생했을 경우 구문 분석하는 데 실패

package blevins.example 

import scala.util.parsing.combinator._ 

case class Stooge(name: String) 

object StoogesParser extends RegexParsers { 
    def moe = "Moe".r 
    def larry = "Larry".r 
    def curly = "Curly".r 
    def shemp = "Shemp".r 
    def stooge = (moe | larry | curly | shemp) ^^ { case s => Stooge(s) } 
    def certifiedStooge = stooge | """\w+""".r ^? (
    { case s: Stooge => s }, 
    { "not a stooge: " + _ }) 

    def stooges = (certifiedStooge*) ^? (
    { case x if (x == x.removeDuplicates) => x.toSet }, 
    { "duplicate stooge in: " + _ }) 

    def parse(s: String): String = { 
    parseAll(stooges, new scala.util.parsing.input.CharSequenceReader(s)) match { 
     case Success(r,_) => r.mkString(" ") 
     case Failure(r,_) => "failure: " + r 
     case Error(r,_) => "error: " + r 
    } 
    } 

} 

그리고 일부 사용 예 :

package blevins.example 

object App extends Application { 

    def printParse(s: String): Unit = println(StoogesParser.parse(s)) 

    printParse("Moe Shemp Larry") 
    printParse("Moe Shemp Shemp") 
    printParse("Curly Beyonce") 

    /* Output: 
    Stooge(Moe) Stooge(Shemp) Stooge(Larry) 
    failure: duplicate stooge in: List(Stooge(Moe), Stooge(Shemp), Stooge(Shemp)) 
    failure: not a stooge: Beyonce 
    */ 
}