2009-11-25 17 views
9

मैं नीचे दिए गए आदेशों के लिए व्याकरण परिभाषित करने की कोशिश कर रहा हूं।स्कैला पार्सर टोकन डेलीमीटर समस्या

[1.27] parsed: Command(todo,link todo to database,List()) 
[1.36] failure: string matching regex `\z' expected but `:' found 

todo link todo to database deadline: next tuesday context: app.model 
           ^

जहां तक:

action = todo 
message = link todo to database 
properties = [deadline: next tuesday, context: app.model] 

जब मैं नीचे परिभाषित व्याकरण पर इस इनपुट चलाने के लिए, मैं निम्नलिखित त्रुटि संदेश मिलता है: के रूप में

object ParserWorkshop { 
    def main(args: Array[String]) = { 
     ChoiceParser("todo link todo to database") 
     ChoiceParser("todo link todo to database deadline: next tuesday context: app.model") 
    } 
} 

दूसरा आदेश tokenized किया जाना चाहिए मैं देख सकता हूं कि यह विफल हो जाता है क्योंकि संदेश के शब्दों से मेल खाने के लिए पैटर्न संपत्ति कुंजी की कुंजी के लिए पैटर्न के समान है: मूल्य जोड़ी, इसलिए पार्सर यह नहीं बता सकता कि संदेश कहां समाप्त होता है और संपत्ति शुरू होती है। मुझे लगता है कि शुरू टोकन आग्रह इतना की तरह प्रत्येक प्रॉपर्टी के लिए इस्तेमाल किया जा द्वारा इस का समाधान कर सकते हैं:

todo link todo to database :deadline: next tuesday :context: app.model 

लेकिन मैं आदेश यथासंभव निकट प्राकृतिक भाषा में रखना चाहती हैं। मेरे दो प्रश्न हैं:

त्रुटि संदेश का वास्तव में क्या अर्थ है? और दिए गए इनपुट स्ट्रिंग के लिए काम करने के लिए मौजूदा व्याकरण को मैं कैसे संशोधित करूं?

import scala.util.parsing.combinator._ 

case class Command(action: String, message: String, properties: List[Property]) 
case class Property(name: String, value: String) 

object ChoiceParser extends JavaTokenParsers { 
    def apply(input: String) = println(parseAll(command, input)) 

    def command = action~message~properties ^^ {case a~m~p => new Command(a, m, p)} 

    def action = ident 

    def message = """[\w\d\s\.]+""".r 

    def properties = rep(property) 

    def property = propertyName~":"~propertyValue ^^ { 
     case n~":"~v => new Property(n, v) 
    } 

    def propertyName: Parser[String] = ident 

    def propertyValue: Parser[String] = """[\w\d\s\.]+""".r 
} 
+0

मुझे लगता है कि आपको इस तरह के कुछ सिंटैक्स को इस तरह बदलना चाहिए: todo "लिंक टूडो डेटाबेस": समय सीमा: "अगली मंगलवार": संदर्भ: "ऐप।मॉडल " – ziggystar

+0

यह एक समाधान है जिसे मैं टालना चाहता हूं, क्योंकि मैं टोडो व्याकरण को प्राकृतिक भाषा के करीब जितना संभव रखना चाहता हूं। –

उत्तर

21

यह वास्तव में सरल है। जब आप ~ का उपयोग करते हैं, तो आपको यह समझना होगा कि व्यक्तिगत पार्सर्स पर कोई बैकट्रैकिंग नहीं है जो सफलतापूर्वक पूरा हो चुका है।

तो, उदाहरण के लिए, message को कोलन से पहले सबकुछ मिला, क्योंकि यह सब स्वीकार्य पैटर्न है। अगला, propertiesrepproperty है, जिसके लिए propertyName की आवश्यकता है, लेकिन यह केवल कोलन पाता है (पहला char message द्वारा gobbled नहीं है)। तो propertyName विफल रहता है, और property विफल रहता है। अब, properties, जैसा कि बताया गया है, rep है, इसलिए यह 0 पुनरावृत्ति के साथ सफलतापूर्वक समाप्त होता है, जो command सफलतापूर्वक समाप्त करता है।

तो, parseAll पर वापस। command पार्सर सफलतापूर्वक लौट आया, जिससे कोलन से पहले सब कुछ खपत हो गया। फिर यह सवाल पूछता है: क्या हम इनपुट के अंत में हैं (\z)? नहीं, क्योंकि अगला एक कोलन सही है। तो, यह इनपुट के अंत की उम्मीद है, लेकिन एक कोलन मिला।

आपको रेगेक्स को बदलना होगा ताकि यह कोलन से पहले अंतिम पहचानकर्ता का उपभोग न करे। उदाहरण के लिए:

def message = """[\w\d\s\.]+(?![:\w])""".r 

वैसे, जब आप का उपयोग def आप अभिव्यक्ति के लिए मजबूर पुनः मूल्यांकन के लिए। दूसरे शब्दों में, इनमें से प्रत्येक defs प्रत्येक बार कॉल किए जाने पर एक पार्सर बनाते हैं। नियमित अभिव्यक्तियों को तब भी तत्काल किया जाता है जब वे जिन पार्सर्स से संबंधित होते हैं, वे संसाधित होते हैं। यदि आप सब कुछ val में बदलते हैं, तो आपको बेहतर प्रदर्शन मिलेगा।

याद रखें, इन बातों को पार्सर परिभाषित करते हैं, वे नहीं रन करते हैं। यह parseAll है जो एक पार्सर चलाता है।

+0

धन्यवाद डैनियल, बहुत स्पष्ट, अच्छी तरह से लिखित स्पष्टीकरण –

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