深入V8引擎-AST(2)
先聲明一下,這種長(zhǎng)系列的大塊頭博客只能保證盡可能的深入到每一行源碼,有些代碼我不樂(lè)意深究就寫(xiě)個(gè)注釋說(shuō)明一下作用。另外,由于本地整理的比較好,博客就隨心寫(xiě)了。
整個(gè)Compile過(guò)程目前只看到asmjs之前,簡(jiǎn)單的過(guò)了幾遍,大部分方法沒(méi)有點(diǎn)進(jìn)去看,實(shí)在是太復(fù)雜了。上一篇的結(jié)尾指出了AST的入口,也就是命名空間parsing的一個(gè)公共方法,如下。
bool ParseProgram(ParseInfo* info, Isolate* isolate) {// .../*** 生成一個(gè)Parser實(shí)例* 調(diào)用內(nèi)部方法啟動(dòng)轉(zhuǎn)換*/Parser parser(info);FunctionLiteral* result = nullptr;/*** 轉(zhuǎn)換AST后將結(jié)果賦值給ParseInfo的literal_*/result = parser.ParseProgram(isolate, info);info->set_literal(result);// ...return (result != nullptr); }所需要關(guān)心的核心代碼就是這些,非常簡(jiǎn)單,Parser對(duì)象的初始化屬性非常多,這里就不列出來(lái)了。
接下來(lái)進(jìn)入第二個(gè)核心方法,即ParseProgram。
FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {// .../*** scanner_為Parser類(lèi)的一個(gè)私有屬性* 這里僅僅進(jìn)行初始化*/scanner_.Initialize();FunctionLiteral* result = DoParseProgram(isolate, info);// ...return result; }同樣,所需要關(guān)心代碼只有兩行,其中第一步則是啟動(dòng)了scanner的初始化,第二步則是開(kāi)始全面解析。
Scanner包含scanner、scanner-character-strams兩個(gè)部分,其中stream則是經(jīng)過(guò)初步處理的源String,必須轉(zhuǎn)換后才能進(jìn)行解析。處理的過(guò)程在之前省略的代碼中,這里稍微給出大概的轉(zhuǎn)換流程。
bool ParseProgram(ParseInfo* info, Isolate* isolate) {// .../*** 1、info->script()返回的是字符串的描述信息 source是Local<String>類(lèi)型的源字符串* 2、ScannerStream是scanner-character-streams頭文件的類(lèi) 內(nèi)部方法均為靜態(tài)類(lèi)型 可以直接調(diào)用* 3、返回的具體類(lèi)型根據(jù)String類(lèi)型不同而不同 但是由于均繼承于Utf16CharacterStream 所以直接用父類(lèi)接*/Handle<String> source(String::cast(info->script()->source()), isolate);std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(isolate, source));info->set_character_stream(std::move(stream));// ... }/*** 有四種特殊的String類(lèi)型 分別new不同的子類(lèi)* ScannerStream::For(isolate, data, 0, data->length());*/ Utf16CharacterStream* ScannerStream::For(Isolate* isolate, Handle<String> data, int start_pos, int end_pos) {size_t start_offset = 0;// ...if (data->IsSeqOneByteString()) {return new BufferedCharacterStream<OnHeapStream>(static_cast<size_t>(start_pos), Handle<SeqOneByteString>::cast(data),start_offset, static_cast<size_t>(end_pos));} }常規(guī)的字符串一般都是OneByteString,這里就不細(xì)講了。最后返回一個(gè)特殊Stream類(lèi),其屬性記錄字符串的長(zhǎng)度、當(dāng)前的解析進(jìn)度、解析的開(kāi)始與結(jié)束標(biāo)記等等。
將字符串轉(zhuǎn)換后,就可以利用Scanner來(lái)進(jìn)行逐步解析,在此之前,需要對(duì)Scanner類(lèi)有一個(gè)簡(jiǎn)單的了解,如下。
/*** Scanner類(lèi)* 跟Utf16CharacterStream一個(gè)文件*/ class V8_EXPORT_PRIVATE Scanner {public:// 返回next_的token類(lèi)型Token::Value peek() const { return next().token; }// 返回current_的位置信息const Location& location() const { return current().location; }private:// 當(dāng)前字符的Unicode編碼 -1表示結(jié)尾(typedef int32_t uc32) uc32 c0_;TokenDesc* current_; // desc for current token (as returned by Next())TokenDesc* next_; // desc for next token (one token look-ahead)TokenDesc* next_next_; // desc for the token after next (after PeakAhead())// 從Handle<String>轉(zhuǎn)換后的類(lèi)型 負(fù)責(zé)執(zhí)行解析的實(shí)際類(lèi)Utf16CharacterStream* const source_; }選取了一些比較簡(jiǎn)單的屬性和方法,Scanner內(nèi)部有三個(gè)游標(biāo)屬性負(fù)責(zé)遍歷字符串,分別是current_、next_、next_next_,字面意思理解就行了。source_則是之前說(shuō)的轉(zhuǎn)換Stream類(lèi),所有的解析實(shí)際上都是調(diào)用這個(gè)屬性的方法。而兩個(gè)結(jié)構(gòu)體TokenDesc、Location也非常重要,一個(gè)負(fù)責(zé)詞法描述,一個(gè)負(fù)責(zé)記錄詞法位置信息,如下。
/*** 詞法結(jié)構(gòu)體* 每一個(gè)TokenDesc代表單獨(dú)一段詞法*/ struct TokenDesc {/*** 詞法所在位置* 該結(jié)構(gòu)體比較簡(jiǎn)單 就不展開(kāi)了 兩個(gè)值代表起始、結(jié)束位置* 例如sample中 "'Hello' + ' World'" 'Hello'會(huì)被解析為T(mén)OKEN::STRING location為{0, 7}*/Location location = {0, 0};/*** 字符串詞法相關(guān)*/LiteralBuffer literal_chars;LiteralBuffer raw_literal_chars;/*** 詞法的枚舉類(lèi)型* 例如 '(' 是 TOKEN::LPAREN '===' 是 TOKEN::EQ_STRICT* 所有類(lèi)型可見(jiàn)token.h*/Token::Value token = Token::UNINITIALIZED;MessageTemplate invalid_template_escape_message = MessageTemplate::kNone;Location invalid_template_escape_location;// 小整數(shù)uint32_t smi_value_ = 0;bool after_line_terminator = false; }通過(guò)這個(gè)結(jié)構(gòu)體和一些方法,就能完整的將源字符串逐步轉(zhuǎn)換為抽象語(yǔ)法樹(shù)。但是實(shí)際轉(zhuǎn)換過(guò)程非常復(fù)雜,分支極多,后面再繼續(xù)探究。
轉(zhuǎn)載于:https://www.cnblogs.com/QH-Jimmy/p/11115324.html
總結(jié)
以上是生活随笔為你收集整理的深入V8引擎-AST(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: 写文件+三剑客+别名
 - 下一篇: DQL