이 질문은 combinator parsers으로 실험 할 동기가 있습니다.
이
import scala.util.parsing.combinator._
object Expr { type VARS = Map[String, Any] }
import Expr._
sealed trait Expr { def eval(v: VARS) : Any }
case class If(cond: Cond, ifTrue: Expr, ifFalse: Expr) extends Expr {
def eval(v: VARS) =
if (cond.eval(v)) ifTrue.eval(v) else ifFalse.eval(v)
}
case class Cond(left: Expr, right: Expr) extends Expr {
def eval(v: VARS) = left.eval(v) == right.eval(v)
}
case class Len(ident: String) extends Expr {
def eval(v: VARS) = v(ident).toString.size
}
case class Mid(ident: String, start: Expr, count: Expr) extends Expr {
def eval(v: VARS) = {
val s = start.eval(v).asInstanceOf[Int]
val e = s + count.eval(v).asInstanceOf[Int]
v(ident).asInstanceOf[String].substring(s, e)
}
}
case class Ident(ident: String) extends Expr { def eval(v:VARS) = v(ident) }
case class StringLit(value: String) extends Expr { def eval(v:VARS) = value }
case class Number(value: String) extends Expr { def eval(v:VARS) = value.toInt }
Expr
오브젝트하여 주어진 식을 구문 분석하고 돌아갑니다 다음 파서 정의 : 결과를 분석하고 평가하는 그런
class Equation extends JavaTokenParsers {
def IF: Parser[If] = "IF" ~ "(" ~ booleanExpr ~","~ expr ~","~ expr ~ ")" ^^ {
case "IF" ~ "(" ~ booleanExpr ~ "," ~ ifTrue ~ "," ~ ifFalse ~ ")" =>
If(booleanExpr, ifTrue, ifFalse)
}
def LEN: Parser[Len] = "LEN" ~> "(" ~> ident <~ ")" ^^ (Len(_))
def MID: Parser[Mid] = "MID" ~ "(" ~ ident ~ "," ~ expr ~ "," ~ expr ~ ")" ^^ {
case "MID" ~ "(" ~ ident ~ "," ~ expr1 ~ "," ~ expr2 ~ ")" =>
Mid(ident, expr1, expr2)
}
def expr: Parser[Expr] = (
stringLiteral ^^ (StringLit(_))
| wholeNumber ^^ (Number(_))
| LEN
| MID
| IF
| ident ^^ (Ident(_))
)
def booleanExpr: Parser[Cond] = expr ~ "=" ~ expr ^^ {
case expr1 ~ "=" ~ expr2 => Cond(expr1, expr2)
}
}
될 수있는 표현의 하위 집합을 나타내는 다음과 같은 대수 데이터 유형을 감안할 때
val equation = new Equation
val parsed = equation.parseAll(equation.expr,
"""IF(LEN(param1)=4,MID(param1,2,1), MID(param1,0,LEN(param1)))""")
parsed match {
case equation.Success(expr, _) =>
println(expr)
// If(Cond(Len(param1),Number(4)),
// Mid(param1,Number(2),Number(1)),
// Mid(param1,Number(0),Len(param1)))
println(expr.eval(Map("param1" -> "scala"))) // prints scala
println(expr.eval(Map("param1" -> "scat"))) // prints a
case _ =>
println("cannot parse")
}
내가 제공 한 문법은 예제를 구문 분석하기에 최소값이며 abso라는 점에 유의하십시오. 대충 오류 관리 나 유형 검사가 없습니다. 프로세스를 현명하게하기 위해, 먼저 ^^ ...
을 생성하지 않고 문법을 생각해 냈습니다. 그런 다음 Expr
유형을 추가했지만 평가 방법을 사용하지 않은 경우 ^^ ...
을 생성 한 다음 Expr
특성 및 하위 유형에 eval 메소드를 추가했습니다. 수업.
거기에는 함수 포인터와 동등한 익명 함수 리터럴이 있습니다. –
아이디어는 수식을 전달하고 무엇을 할 것입니까? 수식을 구현하는 함수를 반환하고 구문 분석 된 표현식을 나타내는 개체를 반환합니까? – huynhjl
죄송합니다. "수식을 전달할 수있다": 어떻게? 어디에? 런타임에? 컴파일 시간에? 소스 코드로? 문자열로? 당신이 그것을 통과 할 때 일어날 것으로 예상합니까? 내가 너라면, 다시 전체 질문을 다시 써야 겠어. –