2010-03-05 8 views
7

Ayrıştırıcı birleştiricilerle denemeler yapıyorum ve sık sık sonsuz yineleme gibi görünen şeylerle karşılaşıyorum. İşte ben ilk koştu:Ayrıştırıcı ayrıştırıcı yok - ne olup bittiğini nasıl kaydederim?

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) 
    } 

} 

Neler olup bittiğini nasıl yazdırabilirim? Ve bu neden bitmiyor?

cevap

4

notComma ve notEndLine ayrıştırmak için yapılan girişimlerin günlüğe kaydedilmesi, dosyanın (dosya() (...) ("mesg") çıkışında CTRL-Z olarak gösterilen) olduğunu ve tekrar tekrar ayrıştırıldığını gösterir. İşte bu amaç için ayrıştırıcı modifiye edebilirsiniz: I (Ben senin gramer birçok varyasyonlar denedi) Neler oluyor tamamen emin değilim

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

, ama böyle bir şey olduğunu düşünüyorum: EOF gerçekten değil Girdi akışına yapay olarak sokulan karakter, ancak girdinin sonunda bir çeşit kalıcı durum. Böylece, bu hiç tüketilmeyen EOF sözde-karakteri tekrar tekrar "ya bir virgül değil, bir satır sonu" olarak ayrıştırılır.

+0

Ben EOF yapay olarak uygulanan olduğunu düşünüyorum, ama sen Giriş zaten dizinin sonunda olduğunda ek bir karakter. – huynhjl

2

Tamam, sanırım bunu anladım. `CharSequenceReader, girişin sonu için bir işaretçi olarak '\ 032' döndürür. Bu gibi benim girişi değiştirmek, yani çalışır: CharSequenceReaderhere için

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) 
    } 

} 

bakınız kaynak kodu. scaladoc belirtmiş olsaydı, bana çok zaman kazandırabilirdi.

+1

Belirtileceği yeri belirleyin ve bir doktor bileti açın. Eğer modifiye edilmiş scaladoc ile bir yama verebilirseniz, o kadar iyidir. –

+0

Gönderilen https://lampsvn.epfl.ch/trac/scala/ticket/3147. EofCh'yi kullanarak birden çok dosya var, bu yüzden en iyi yerin nerede olduğundan emin değilim. – huynhjl

0

Günlüğe kaydetme işlevinin yazım için son derece garip olduğunu buluyorum. Gibi neden log(parser)("string") yapmak zorundayım? Neden parser.log("string") kadar basit bir şeyiniz yok? Neyse ki üstesinden gelmek için, bunun yerine bu yaptı: sizin ayrıştırıcı Şimdi

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 
    } 
} 

, karıştırıp edilebilmeki bu özelliğin şöyle:

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) 
} 

Ayrıca kapatmak için debug alanını geçersiz kılabilirler eğer istenirse kayıt.

Running bu da ikinci ayrıştırıcı doğru virgül ayrıştırılır gösterir: sağ isterken defalarca defalarca sağlanan görünüyor de ayrıştırılır olduğunu söyleyerek

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