2012-03-20 20 views
8

बनाना मैं स्कैला के लिए नया हूं लेकिन मैं सोच रहा था कि भाषा में एक सरल समीकरण पार्सर को कार्यान्वित करना संभव है। स्ट्रिंग निकालनेस्कैला - एक मूल गतिशील फ़ंक्शन पार्सर

LEN(String) - - एक स्ट्रिंग

OR(cond1, cond2, ... condn)

AND(cond1, cond2, ... condn) की लंबाई

IF(Cond a=b, val_true, val_false)

MID(String, Start_pos, num_chars):

मैं कुछ कार्य (ज्यादा एक्सेल कार्यों की तरह) कहो

तो विचार मैं एक सूत्र में साथ-साथ एक कमांड लाइन तर्क के रूप में एक उपयोगकर्ता से एक स्ट्रिंग के रूप रनटाइम पर गुजर सकता है हो सकता है किसी अन्य पैरामीटर कहना IF(LEN(param1)=4,MID(param1,2,1), MID(param1,0,LEN(param1)))

विचार समारोह का मूल्यांकन करना है, इसलिए यदि उपयोगकर्ता उपरोक्त सूत्र और स्ट्रिंग "स्कैट" प्रदान करता है तो आउटपुट "ए" होगा। यदि स्ट्रिंग "स्कैला" दिया गया था तो आउटपुट "स्कैला" होगा ...

स्कैला में इसे कार्यान्वित करना कितना आसान होगा? सबसे अच्छा डिजाइन दृष्टिकोण क्या है? मुझे पता है कि कोई फंक्शन पॉइंटर्स नहीं हैं (सी में मैंने फॉर्मूला स्ट्रिंग को फंक पॉइंट्स के संग्रह में पार्स किया होगा और वहां से चले गए थे) ...

कुशल स्कैला शैली में इसका उपयोग करने के तरीके पर कोई सलाह की सराहना की जाएगी।

चीयर्स!

+1

वहाँ _are_ फ़ंक्शन पॉइंटर्स के बराबर है, अर्थात् अज्ञात फ़ंक्शन अक्षर। –

+0

विचार सूत्र को पास करना होगा और फिर क्या करना होगा? फॉर्मूला को लागू करने वाला एक फ़ंक्शन लौटाएं, एक ऑब्जेक्ट को पारदर्शी अभिव्यक्ति का प्रतिनिधित्व करते हुए वापस करें? – huynhjl

+0

क्षमा करें, यह पर्याप्त स्पष्ट नहीं है। "मैं एक सूत्र में गुजर सकता हूं": कैसे? कहा पे? चलने के समय पर? संकलन समय पर? स्रोत कोड के रूप में? रस्सी जैसी? और क्या आप ऐसा करने की उम्मीद करते हैं जब आप इसे पास करते हैं? अगर मैं आप थे, तो मैं फिर से पूरे प्रश्न को फिर से लिखूंगा। –

उत्तर

8

इस प्रश्न ने 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 प्रकारों को जोड़ा गया लेकिन बिना eval विधि के, फिर उत्पादन ^^ ..., फिर मैंने अंत में Expr विशेषता और उप- कक्षाएं।

+0

धन्यवाद !!! बहुत बढ़िया जवाब! – NightWolf

संबंधित मुद्दे