1.script先由ResourceGroupMgr在prepare函數(shù)里根據(jù)不同的后綴名選擇不同的ScriptLoader的派生類來(lái)加載,這里我們就以ScriptCompilerMgr為例。(今天開(kāi)始細(xì)看材質(zhì)加載部分的代碼才發(fā)現(xiàn)ogre的材質(zhì)解析原來(lái)還有兩套,以前的一套是MaterialSerializer,1.6之后默認(rèn)使用的是ScriptCompilerMgr.)
2.調(diào)用ScriptCompilerMgr內(nèi)部ScriptCompiler對(duì)象的compile函數(shù),這里其實(shí)也沒(méi)有進(jìn)行實(shí)際分析,只是創(chuàng)建并調(diào)用了分析和編譯的對(duì)象:ScriptLexer,ScriptParser,ScriptCompiler。
3.先由ScriptLexer對(duì)文本進(jìn)行分析,創(chuàng)建一個(gè)包含了所有token信息節(jié)點(diǎn)的列表,注意這一步僅僅是將所有材質(zhì)里的詞匯單元提取出來(lái)而已,還沒(méi)有生成CST,乃至AST(當(dāng)然這里的CST和AST都是簡(jiǎn)化的),這里的實(shí)現(xiàn)比較易讀在ScriptLexer::tokenize中對(duì)文本的每個(gè)字符進(jìn)行遍歷,查找token(在ogre里也就是譬如{ } // \ : newline等,當(dāng)然普通的字符肯定也算的),最后生成一個(gè)tokenlist。
4. 接下來(lái)將tokenList傳入ScriptParser的parse函數(shù)中,這些token節(jié)點(diǎn)將被根據(jù)標(biāo)記符的關(guān)系,而生成一個(gè)簡(jiǎn)單有父子關(guān)系的分析樹(shù),也就是CST了。到這里你就發(fā)現(xiàn)之前動(dòng)輒就100個(gè)的nodelist已經(jīng)變成了ConcreteNodeList,當(dāng)然這里的node每個(gè)都是一個(gè)樹(shù)了.以最外面的{}為根.當(dāng)然沒(méi)有{}的部分就變成一個(gè)節(jié)點(diǎn)(知道找到{或者別的標(biāo)記符)
5.接著,在ScriptCompiler里將之前生成的CST轉(zhuǎn)化為AST(這里的具體轉(zhuǎn)化的代碼我還沒(méi)細(xì)看。。)
6.呼,終于要到最后了,根據(jù)每個(gè)AST的類型調(diào)用不同的ScriptTranslator,例如材質(zhì)的話就取得MaterialTranslator來(lái)解釋成最終的material,然后對(duì)其中的每個(gè)AST子節(jié)點(diǎn)再調(diào)用對(duì)應(yīng)的ScriptTranslator,(例如pass就調(diào)用PassTranslator等)把所有的值都設(shè)置好,這樣所有解釋的工作終于完成了。
呼,的確是個(gè)很漫長(zhǎng)的過(guò)程。。個(gè)人感覺(jué)如果把scriptLexer換成已有的什么文本解釋庫(kù)讀取的速度會(huì)不會(huì)得到很多提升呢?譬如如今比較流行的rapidXml什么的,畢竟個(gè)人覺(jué)得這些專門優(yōu)化文本庫(kù)的性能還是很高的(雖然我得說(shuō)尖括號(hào)啥的的確不是那么易讀~)。當(dāng)然我覺(jué)得ogre這么寫的架勢(shì)很可能有想將原來(lái)普通的腳本配置文件提升成ogre專用的腳本語(yǔ)言的趨勢(shì)?(最早只是寫了一堆Serializer而已)