2011-10-01 6 views

답변

23

REPL에서 실행될 다음 코드를 작성하여 테스트 해보니 재미 있다고 생각했습니다. 주어진 :

val ops = List(
    "letter", "|", "^", 
    "&", "<", ">", "!", 
    "+", "-", "*", "/", "%", "?", 
    "=?", // add ? to prevent assignment 
    ":?" // add ? to prevent right-association 
) 

먼저 연산자를 사용하고 테스트하는 중간 스칼라 파일을 생성하십시오.

letter 
| 
^ 
& 
! =? 
< > 
:? 
+ - 
*/% 
? 

그래서 사양과의 주요 차이점은 = !로 전환 할 < > 필요하다 :

import java.io._ 

// generate a class with all ops operators defined 
// where operator combines in a way we can figure out the precedence 
val methods = ops.map("""def %s(o: Op) = Op("["+o.v+v+"]")""".format(_)) 
val body = methods.mkString("\n") 
val out = new PrintWriter(new FileWriter("Op.scala")) 
out.println("case class Op(v: String) {\n%s\n}".format(body)) 

// generate tests for all combinations and store in comps 
// Op(".") op1 Op(".") op2 Op(".") v returns "[[..].]" when op2 > op1 
// returns "[.[..]]" when op1 <= op2 
def test(op1: String, op2:String) = { 
    """("%s","%s") -> (Op(".") %s Op(".") %s Op(".")).v.startsWith("[[")""". 
    format(op1, op2, op1, op2) 
} 
val tests = for (op1 <- ops; op2 <- ops) yield { test(op1, op2) } 
out.println("val comps = Map[(String, String), Boolean](%s)".format(
    tests.mkString(",\n"))) 
out.close 

그런 다음 연산 클래스를로드, 실행 테스트 및 부하

:load Op.scala 

// order operators based on tests 
val order = ops.sortWith((x,y) => comps(x -> y)) 

// if op1 or op2 don't have higher precedence, they have the same precedence 
def samePrecedence(op1: String, op2: String) = 
    !comps(op1 -> op2) && !comps(op2 -> op1) 

def printPrecedenceGroups(list: List[String]): Unit = { 
    if (list != Nil) { 
    val (same, rest) = list.span(op => samePrecedence(op, list.head)) 
    println(same.mkString(" ")) 
    printPrecedenceGroups(rest) 
    } 
} 

printPrecedenceGroups(order) 

이 인쇄 콤프.

+0

매우 똑똑합니다. +1 –