2010-03-05 12 views
7

मैं पार्सर संयोजकों के साथ प्रयोग कर रहा हूं और मैं अक्सर अनंत रिकर्सन की तरह दिखता हूं। यहां पहला व्यक्ति है जिसमें मैंने भाग लिया:पार्सर संयोजक समाप्त नहीं हो रहा है - क्या लॉग ऑन करना है?

import util.parsing.combinator.Parsers 
import util.parsing.input.CharSequenceReader 

class CombinatorParserTest extends Parsers { 

    type Elem = Char 

    def notComma = elem("not comma", _ != ',') 

    def notEndLine = elem("not end line", x => x != '\r' && x != '\n') 

    def text = rep(notComma | notEndLine) 

} 

object CombinatorParserTest { 

    def main(args:Array[String]): Unit = { 
    val p = new CombinatorParserTest() 
    val r = p.text(new CharSequenceReader(",")) 
    // does not get here 
    println(r) 
    } 

} 

मैं क्या प्रिंट कर रहा हूं प्रिंट कर सकता हूं? और यह क्यों खत्म नहीं होता है?

उत्तर

4

प्रयास लॉगिंग पार्स करने के लिए notComma और notEndLine पता चलता है कि यह अंत फ़ाइल है कि बार-बार पार्स किया जाता (लॉग में एक Ctrl-Z (...) ("mesg") आउटपुट के रूप में दिखाया गया है) है। यहाँ कैसे मैं इस उद्देश्य के लिए अपने पार्सर संशोधित है:

def text = rep(log(notComma)("notComma") | log(notEndLine)("notEndLine")) 

मैं पूरी तरह यकीन है कि क्या हो रहा है (मैं अपने व्याकरण पर कई रूपों की कोशिश की) नहीं कर रहा हूँ, लेकिन मुझे लगता है कि यह कुछ इस तरह है: EOF वास्तव में एक नहीं है चरित्र कृत्रिम रूप से इनपुट स्ट्रीम में पेश किया गया, बल्कि इनपुट के अंत में एक तरह की सतत स्थिति। इस प्रकार यह कभी भी उपभोग नहीं किया गया ईओएफ छद्म-चरित्र बार-बार पार्स किया जाता है "या तो एक अल्पविराम नहीं है या अंतहीन नहीं है।"

+0

मुझे लगता है कि EOF कृत्रिम रूप से शुरू की है लगता है, लेकिन आप कर रहे हैं एक अतिरिक्त चरित्र जब इनपुट अनुक्रम के अंत में पहले से ही है। – huynhjl

2

ठीक है, मुझे लगता है कि मैंने इसे समझ लिया है। इनपुट के अंत के लिए मार्कर के रूप में 'CharSequenceReader' \ 032 'देता है। तो अगर मैं इस तरह मेरा इनपुट संशोधित करने, यह काम करता है: CharSequenceReaderhere के लिए

import util.parsing.combinator.Parsers 
import util.parsing.input.CharSequenceReader 

class CombinatorParserTest extends Parsers { 

    type Elem = Char 

    import CharSequenceReader.EofCh 

    def notComma = elem("not comma", x => x != ',' && x!=EofCh) 

    def notEndLine = elem("not end line", x => x != '\r' && x != '\n' && x!=EofCh) 

    //def text = rep(notComma | notEndLine) 
    def text = rep(log(notComma)("notComma") | log(notEndLine)("notEndLine")) 

} 

object CombinatorParserTest { 

    def main(args:Array[String]): Unit = { 
    val p = new CombinatorParserTest() 
    val r = p.text(new CharSequenceReader(",")) 
    println(r) 
    } 

} 

देखें स्रोत कोड। यदि स्कैलाडोक ने इसका उल्लेख किया है, तो यह मुझे बहुत समय बचाएगा।

+1

पता लगाएं कि इसका उल्लेख किया जाना चाहिए, और एक डॉक्टर टिकट खोलें। यदि आप संशोधित स्कैलाडोक के साथ पैच प्रदान कर सकते हैं, तो उतना ही बेहतर होगा। –

+0

प्रस्तुत https://lampsvn.epfl.ch/trac/scala/ticket/3147। 'EofCh' का उपयोग कर कई फाइलें हैं, इसलिए मुझे यकीन नहीं है कि सबसे अच्छी जगह कहां है। – huynhjl

0

मुझे लगता है कि लॉगिंग फ़ंक्शन टाइप करने के लिए बेहद अजीब है। मुझे log(parser)("string") क्यों करना है? parser.log("string") के रूप में कुछ आसान क्यों नहीं है? वैसे भी, पर काबू पाने के लिए है कि, मैं इस बजाय बनाया:

trait Logging { self: Parsers => 

    // Used to turn logging on or off 
    val debug: Boolean 

    // Much easier than having to wrap a parser with a log function and type a message 
    // i.e. log(someParser)("Message") vs someParser.log("Message") 
    implicit class Logged[+A](parser: Parser[A]) { 
     def log(msg: String): Parser[A] = 
      if (debug) self.log(parser)(msg) else parser 
    } 
} 

अब आप अपने पार्सर में, आप मिश्रण-इन कर सकते इस विशेषता तो जैसे:

import scala.util.parsing.combinator.Parsers 
import scala.util.parsing.input.CharSequenceReader 


object CombinatorParserTest extends App with Parsers with Logging { 

    type Elem = Char 

    override val debug: Boolean = true 

    def notComma: Parser[Char] = elem("not comma", _ != ',') 
    def notEndLine: Parser[Char] = elem("not end line", x => x != '\r' && x != '\n') 
    def text: Parser[List[Char]] = rep(notComma.log("notComma") | notEndLine.log("notEndLine")) 

    val r = text(new CharSequenceReader(",")) 

    println(r) 
} 

तुम भी बंद करने के लिए debug क्षेत्र ओवरराइड कर सकते हैं अगर वांछित लॉगिंग।

चल रहा है यह भी पता चलता दूसरा पार्सर सही ढंग से अल्पविराम पार्स: सही कह रही है कि यह बार-बार में यह बार-बार प्रदान की लगता पार्स किया गया है जब का अनुरोध में

trying notComma at [email protected] 
notComma --> [1.1] failure: not comma expected 

, 
^ 
trying notEndLine at [email protected] 
notEndLine --> [1.2] parsed: , 
trying notComma at [email protected] 
notComma --> [1.2] failure: end of input 

, 
^ 
trying notEndLine at [email protected] 
notEndLine --> [1.2] failure: end of input 

, 
^ 
The result is List(,) 

Process finished with exit code 0