2012-11-03 18 views
13

Tôi đã viết một phân tích cú pháp như sau:Scala phân tích cú pháp Combinator, tập tin lớn vấn đề

class LogParser extends JavaTokenParsers { 

    def invertedIndex: Parser[Array[Array[(Int, Int)]]] = { 
    num ~> num ~> num ~> rep(postingsList) ^^ { 
     _.toArray 
    } 
    } 

    def postingsList: Parser[Array[(Int, Int)]] = { 
    num ~> rep(entry) ^^ { 
     _.toArray 
    } 
    } 

    def entry = { 
    num ~ "," ~ num ^^ { 
     case docID ~ "," ~ count => (docID.toInt, count.toInt) 
    } 
    } 

    def num = wholeNumber ^^ (_.toInt) 

} 

Nếu tôi phân tích từ một (270MB) tập tin với một FileReader như sau:

val index = parseAll(invertedIndex, new FileReader("path/to/file")).get 

tôi nhận được một Exception in thread "main" java.lang.StackOverflowError (Tôi cũng đã thử gói trong một BufferedReader) nhưng tôi có thể sửa chữa nó bằng cách đầu tiên đọc tệp vào một Chuỗi như vậy:

val input = io.Source.fromFile("path/to/file") 
val str = input.mkString 
input.close() 
val index = parseAll(invertedIndex, str).get 

Tại sao lại xảy ra trường hợp này? Có cách nào để tránh đọc nó như là một String đầu tiên, nó có vẻ như một sự lãng phí?

+2

kích thước hiện tại của chồng của bạn là gì, và làm thế nào lớn hơn nhiêu bạn phải chắc chồng của bạn để tránh StackOverflowException? Ngăn xếp phải nhỏ hơn bao nhiêu để làm cho tràn phiên bản String? (Bạn có thể đặt ngăn xếp thành 16MB bằng cách khởi chạy như vậy: 'scala -J-Xss16M') – DaoWen

+0

Tôi chỉ sử dụng kích thước ngăn xếp mặc định, nhưng khi tôi đặt thành 16M thì chương trình vẫn chạy 30 phút sau ... – Robert

+1

có thể liên quan đến lỗi Scala 2.9.2 [SI-6520] (https://issues.scala-lang.org/browse/SI-6520). –

Trả lời

1

Có một thư viện khác [1] rất giống với bộ phối hợp phân tích cú pháp phân tích cú pháp hỗ trợ Trampolining, đó là những gì bạn cần để ngăn chặn lỗi ngăn xếp.

[1] https://github.com/djspiewak/gll-combinators