2010-07-27 16 views
6

इम इस वाक्य से मिलान करने की कोशिश कर रहा:स्कैला पार्सर कॉम्बिनेटर्स रिकर्सिव बीएनएफ के लिए चाल?

pgm ::= exprs 
exprs ::= expr [; exprs] 
expr ::= ID | expr . [0-9]+ 

मेरे स्केला packrat पार्सर Combinator इस तरह दिखता है:

import scala.util.parsing.combinator.PackratParsers 
import scala.util.parsing.combinator.syntactical._ 

object Dotter extends StandardTokenParsers with PackratParsers { 
    lexical.delimiters ++= List(".",";") 
    def pgm = repsep(expr,";") 
    def expr :Parser[Any]= ident | expr~"."~num 
    def num = numericLit 

     def parse(input: String) = 
    phrase(pgm)(new PackratReader(new lexical.Scanner(input))) match { 
     case Success(result, _) => println("Success!"); Some(result) 
     case n @ _ => println(n);println("bla"); None 
    } 

    def main(args: Array[String]) { 
     val prg = "x.1.2.3;" + 
      "y.4.1.1;" + 
      "z;" + 
      "n.1.10.30" 


      parse(prg); 
    } 
} 

लेकिन यह काम नहीं करता है। या तो यह "लालची मेल खाता है" और मुझसे कहता है:

[1.2] failure: end of input expected 
x.1.2.3;y.4.1.1;z;n.1.10.30 

या अगर मैं एक ||| को | बदलने मैं एक stackoverflow मिलती है:

Exception in thread "main" java.lang.StackOverflowError 
at java.lang.Character.isLetter(Unknown Source) 
at java.lang.Character.isLetter(Unknown Source) 
at scala.util.parsing.combinator.lexical.Lexical$$anonfun$letter$1.apply(Lexical.scala:32) 
at scala.util.parsing.combinator.lexical.Lexical$$anonfun$letter$1.apply(Lexical.scala:32) 
... 

मैं समझता हूँ kindoff कारण है कि मैं त्रुटियों मिल; उपर्युक्त की तरह वाक्यविन्यास को पार्स करने के लिए मैं क्या कर सकता हूं? यह प्रतीत नहीं करता है

संपादित करें मेरे लिए गूढ़ है कि: कागज http://scala-programming-language.1934581.n4.nabble.com/Packrat-parser-guidance-td1956908.html में संदर्भित मुझे पता चला कि मेरे कार्यक्रम फ्लॉप वास्तव में नए packrat पार्सर का उपयोग के आधार पर।

आईई। PackratParser[Any] को Parser[Any] बदल सकते हैं और lazy valdef

के बजाय मैं यह करने के लिए ऊपर दुबारा लिखा का उपयोग करें:

import scala.util.parsing.combinator.PackratParsers 
import scala.util.parsing.combinator.syntactical._ 

object Dotter extends StandardTokenParsers with PackratParsers { 
    lexical.delimiters ++= List(".",";") 
    lazy val pgm : PackratParser[Any] = repsep(expr,";") 
    lazy val expr :PackratParser[Any]= expr~"."~num | ident 
    lazy val num = numericLit 

    def parse(input: String) = 
    phrase(pgm)(new PackratReader(new lexical.Scanner(input))) match { 
     case Success(result, _) => println("Success!"); Some(result) 
     case n @ _ => println(n);println("bla"); None 
    } 

    def main(args: Array[String]) { 
     val prg = "x.1.2.3 ;" + 
      "y.4.1.1;" + 
      "z;" + 
      "n.1.10.30" 


      parse(prg); 
    } 
} 

उत्तर

10

समस्या (कम से कम आंशिक रूप से) है कि आप वास्तव में पैक्रेट पार्सर्स का उपयोग नहीं कर रहे हैं। स्काला के PackratParsers विशेषता, जो कहते हैं

PackratParsers का उपयोग करना बहुत Parsers उपयोग करने के समान है के लिए दस्तावेज़ देखें:

  • किसी भी वर्ग/ऐसी विशेषता है जो Parsers (प्रत्यक्ष या एक उपवर्ग के माध्यम से) फैली में मिश्रण कर सकते हैं PackratParsers। उदाहरण: वस्तु MyGrammar PackratParsers
  • प्रत्येक व्याकरण उत्पादन पहले से औपचारिक पैरामीटर के बिना एक डीईएफ़ के रूप में घोषित एक आलसी वैल, हो जाता है और उसके प्रकार पार्सर [Elem] से PackratParser [Elem] कर दिया गया है साथ StandardTokenParsers फैली हुई है। तो, उदाहरण के लिए, डीईएफ़ उत्पादन: PackratParser [इंट] = {...}
  • महत्वपूर्ण:: एक सब कुछ या कुछ निर्णय PackratParsers का उपयोग नहीं है पार्सर [इंट] = {...} आलसी वैल उत्पादन हो जाता है । वे एक व्याकरण में नियमित पार्सर्स के साथ मुफ्त मिश्रित हो सकते हैं।

मैं पर्याप्त जानकारी नहीं है के बारे में स्काला 2.8 के पार्सर combinators यह पूरी तरह ठीक करने के लिए, लेकिन निम्नलिखित संशोधनों के साथ, मैं इसे अर्धविराम, जो एक सुधार है के रूप में जहाँ तक पार्स करने के लिए प्राप्त करने में सक्षम था जो आपने पूरा किया है उसके ऊपर।

object Dotter extends StandardTokenParsers with PackratParsers { 
    lexical.delimiters ++= List(".",";") 
    lazy val pgm:PackratParser[Any] = repsep(expr,";") 
    lazy val expr:PackratParser[Any]= ident ||| (expr~"."~numericLit) 

    def parse(input: String) = phrase(expr)(lex(input)) match { 
     case Success(result, _) => println("Success!"); Some(result) 
     case n @ _ => println(n);println("bla"); None 
    } 

    def lex(input:String) = new PackratReader(new lexical.Scanner(input)) 
} 
+0

बिल्कुल! मैं प्रलेखन को दोबारा पढ़ रहा था और इसे समझ लिया। आखिरी चीज की आवश्यकता पार्स विधि में एक टाइपो है: 'वाक्यांश (expr) 'वाक्यांश होना चाहिए (पीजीएम)'। चीयर्स! – svrist

1

उत्पादन

expr ::= ID | expr . [0-9]+ 

पुनरावर्ती छोड़ दिया है। यह

expr ::= ID 
expr ::= expr . [0-9]+ 

जहां दूसरी पंक्ति पर बाएं रिकर्सन होता है। यही कारण है कि पार्सर स्टैक को बहने का कारण बनता है।

आपको अपने व्याकरण को बाएं रिकर्सिव प्रस्तुतियों से परहेज करना चाहिए।

expr ::= ID {. [0-9]+} 
+2

क्या पैट्रेट पार्सर मुझे बाएं-रिकर्सन करने की अनुमति देने वाला नहीं था? – svrist

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