2012-02-05 62 views
4

我在Scala中編寫了一個(簡單的)編譯器,並使得tokenizer可迭代,現在需要編寫解析器。該計劃是使用遞歸下降策略,因此解析器將被分解成多個方法,其中每個方法都會調用其中一些方法。共享迭代器

我想這將是必要的/最好保留標記生成器迭代器的狀態和各種方法之間共享。是這樣嗎?我應該怎麼做呢?如果情況並非如此,還有什麼選擇?

+0

我讀完標題後首先想到的是「*不要!*」 – ziggystar 2012-02-05 17:45:09

回答

5

如果你要保持迭代器的狀態,唐使用迭代器!迭代器適用於當你可以隨時摧毀你的狀態時。

可能能夠與使用流脫身。溪流有一種習慣,當他們應該因爲引用持續存在於你不想要的地方時,他們不會放棄自己的記憶(但是如果你仔細想想,你可以告訴它們存在)。所以如果你開始使用迭代器,你可以.toStream並傳入子流,然後傳遞流進行進一步處理。但是如果你想避免將所有內容都保存在內存中,你必須非常小心,不要保留對流的頭部的引用。

另一種方式去是剛剛傾倒一切都變成向量或陣列,並保持在內存中的整個問題;隨後您可以放下不相關的部分(或提前索引)。

最後,如果你是絕對肯定,你不需要任何回溯,那麼你可以直接使用迭代器,而不必擔心「維護狀態」。也就是說,當你從子方法回來時,你已經完全消耗了權限令牌並且不會再有更多的權限,並且可以自由地繼續解析。爲了在沒有至少一個元素的「我沒有使用的下一個標記」的情況下工作,你需要能夠預測最後一個標記的位置(例如,一個無限長度的列表將不得不以作爲列表的一部分的令牌,因此{1,2,3}可能是一個列表(如果您在進入列表處理時看到{,並在您點擊}時退出),但不是1,2,3 + 7(因爲您在使用+之前意識到列表已結束))。

1

你可以只構造記號迭代,因此該令牌級解析從中讀取它向下傳遞每個遞歸解析調用:

def parse2(tokens: Iterator[String]) = List(tokens.next, tokens.next) 
def parse1(tokens: Iterator[String]) = List(parse2(tokens), parse2(tokens)) 

val tokens = List("a","b","c","d").iterator 
val parsed = parse1(tokens) //List(List(a, b), List(c, d))