欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

以Golang為例詳解AST抽象語(yǔ)法樹(shù)的原理與實(shí)現(xiàn)

 更新時(shí)間:2024年01月17日 08:17:56   作者:燈火消逝的碼頭  
AST?使用樹(shù)狀結(jié)構(gòu)來(lái)表達(dá)編程語(yǔ)言的結(jié)構(gòu),樹(shù)中的每一個(gè)節(jié)點(diǎn)都表示源碼中的一個(gè)結(jié)構(gòu),本文將以GO語(yǔ)言為例,為大家介紹一下AST抽象語(yǔ)法樹(shù)的原理與實(shí)現(xiàn),希望對(duì)大家有所幫助

前言

各位同行有沒(méi)有想過(guò)一件事,一個(gè)程序文件,比如 hello.go 是如何被編譯器理解的,平常在編寫(xiě)程序時(shí),IDE 又是如何提供代碼提示的。在這奧妙無(wú)窮的背后, AST(Abstract Syntax Tree)抽象語(yǔ)法樹(shù)功不可沒(méi),他站在每一行程序的身后,默默無(wú)聞的工作,為繁榮的互聯(lián)網(wǎng)世界立下了汗馬功勞。

AST 抽象語(yǔ)法樹(shù)

AST 使用樹(shù)狀結(jié)構(gòu)來(lái)表達(dá)編程語(yǔ)言的結(jié)構(gòu),樹(shù)中的每一個(gè)節(jié)點(diǎn)都表示源碼中的一個(gè)結(jié)構(gòu)。聽(tīng)到這或許你的心里會(huì)咯噔一下,其實(shí)說(shuō)通俗一點(diǎn),在源代碼解析后會(huì)得到一串?dāng)?shù)據(jù),這個(gè)數(shù)據(jù)自然的呈現(xiàn)樹(shù)狀結(jié)構(gòu),它被稱(chēng)之為 CST(Concrete Syntax Tree) 具體語(yǔ)法樹(shù),在 CST 的基礎(chǔ)上保留核心結(jié)構(gòu)。忽略一些不重要的結(jié)構(gòu),比如標(biāo)點(diǎn)符號(hào),空白符,括號(hào)等,就得到了 AST。

如何生成 AST 

生成 AST 大概需要兩個(gè)步驟,詞法分析lexical analysis和語(yǔ)法分析syntactic analysis 。

詞法分析 lexical analysis

lexical analysis 簡(jiǎn)稱(chēng) lexer ,它表示字符串序列,也就是我們的源代碼轉(zhuǎn)化為 token 的過(guò)程,進(jìn)行詞法分析的工具叫做詞法分析器(lexical analyzer,簡(jiǎn)稱(chēng)lexer),也叫掃描器(scanner)。Go 語(yǔ)言的 go/scanner 包提供詞法分析。 

func ScannerDemo() {
	// 源代碼
	src := []byte(`
func demo() {
	fmt.Println("When you are old and gray and full of sleep")
}
`)

	// 初始化標(biāo)記
	var s scanner.Scanner
	fset := token.NewFileSet()
	file := fset.AddFile("", fset.Base(), len(src))
	s.Init(file, src, nil, scanner.ScanComments)

	// Scan 進(jìn)行掃碼并打印出結(jié)果
	for {
		pos, tok, lit := s.Scan()
		if tok == token.EOF {
			break
		}
		fmt.Printf("%s\t%s\t%q\n", fset.Position(pos), tok, lit)
	}
}

打印的結(jié)果我們接著往下看。

標(biāo)記 token

標(biāo)記(token)  是詞法分析后留下的產(chǎn)物,是構(gòu)成源代碼的最小單位,但是這些 token 之間沒(méi)有任何邏輯關(guān)系。以上述代碼為例:

func demo() {
	fmt.Println("When you are old and gray and full of sleep")
}

經(jīng)過(guò)詞法分析后,會(huì)得到:

tokenliteral(字面量,以string表示)
func"func"
IDENT"demo"
(""
)""
{""
IDENT"fmt"
.""
IDENT"Println"
(""
STRING"\"When you are old and gray and full of sleep\""
)""
;"\n"
}""
;"\n"

在 Go 語(yǔ)言中,如果 token 類(lèi)型就是一個(gè)字面量,例如整型,字符串類(lèi)型等,那么它的值就是相對(duì)應(yīng)的值,比如上表的 STRING;如果 token 是 Go 的關(guān)鍵詞,那么它的值就是關(guān)鍵詞,比如上表的 fun;對(duì)于分號(hào),它的值則是換行符;其他 token 類(lèi)要么是不合法的,如果是合法的,則值為空字符串,比如上表的 {。

語(yǔ)法分析 syntactic analysis

不具備邏輯關(guān)系的 token 經(jīng)過(guò)語(yǔ)法分析(syntactic analysis,也叫 parsing)就可以得到具有邏輯關(guān)系的 CST 具體語(yǔ)法樹(shù),然后對(duì) CST 進(jìn)行分析提煉即可得到 AST 抽象語(yǔ)法樹(shù)。完成語(yǔ)法分析的工具叫做語(yǔ)法分析器(parser)。Go 語(yǔ)言的 go/parser 提供語(yǔ)法分析。

func ParserDemo() {
	src := `
package main
`
	fset := token.NewFileSet()
	// 如果 src 為 nil,則使用第二個(gè)參數(shù),它可以是一個(gè) .go 文件地址
	f, err := parser.ParseFile(fset, "", src, 0)
	if err != nil {
		panic(err)
	}

	ast.Print(fset, f)
}

打印出來(lái)的 AST:

 0  *ast.File {
 1  .  Package: 2:1
 2  .  Name: *ast.Ident {
 3  .  .  NamePos: 2:9
 4  .  .  Name: "main"
 5  .  }
 6  .  FileStart: 1:1
 7  .  FileEnd: 2:14
 8  .  Scope: *ast.Scope {
 9  .  .  Objects: map[string]*ast.Object (len = 0) {}
10  .  }
11  }

它包含了源代碼的結(jié)構(gòu)信息,看起來(lái)像一個(gè) JSON。

總結(jié)

源代碼經(jīng)過(guò)詞法分析后得到 token(標(biāo)記),token 經(jīng)過(guò)語(yǔ)法分析得到 CST 具體語(yǔ)法樹(shù),在 CST 上創(chuàng)建 AST 抽象語(yǔ)法樹(shù)。 來(lái)個(gè)圖圖或許更直觀:

Go 的抽象語(yǔ)法樹(shù)

這里我們以一個(gè)具體的例子來(lái)看:從 go 代碼中提取所有結(jié)構(gòu)體的名稱(chēng)。

// 源碼
type A struct{}
type B struct{}
type C struct{}
func ExampleGetStructName() {
	fileSet := token.NewFileSet()
	node, err := parser.ParseFile(fileSet, "demo.go", nil, parser.ParseComments)
	if err != nil {
		return
	}

	ast.Inspect(node, func(n ast.Node) bool {
		if v, ok := n.(*ast.TypeSpec); ok {
			fmt.Println(v.Name.Name)
		}
		return true
	})
	// Output:
	// A
	// B
	// C
}

到此這篇關(guān)于以Golang為例詳解AST抽象語(yǔ)法樹(shù)的原理與實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Go AST抽象語(yǔ)法樹(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言中init函數(shù)和defer延遲調(diào)用關(guān)鍵詞詳解

    Go語(yǔ)言中init函數(shù)和defer延遲調(diào)用關(guān)鍵詞詳解

    這篇文章主要介紹了Go語(yǔ)言中init函數(shù)和defer延遲調(diào)用關(guān)鍵詞,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • 詳解golang中?work與?module?的區(qū)別與聯(lián)系

    詳解golang中?work與?module?的區(qū)別與聯(lián)系

    Go?模塊通常由一個(gè)項(xiàng)目或庫(kù)組成,并包含一組隨后一起發(fā)布的?Go?包,Go?模塊通過(guò)允許用戶(hù)將項(xiàng)目代碼放在他們選擇的目錄中并為每個(gè)模塊指定依賴(lài)項(xiàng)的版本,解決了原始系統(tǒng)的許多問(wèn)題,本文將給大家介紹一下golang中?work與?module?的區(qū)別與聯(lián)系,需要的朋友可以參考下
    2023-09-09
  • Golang內(nèi)存泄露場(chǎng)景與定位方式的實(shí)現(xiàn)

    Golang內(nèi)存泄露場(chǎng)景與定位方式的實(shí)現(xiàn)

    Golang有自動(dòng)垃圾回收機(jī)制,但是仍然可能會(huì)出現(xiàn)內(nèi)存泄漏的情況,本文主要介紹了Golang內(nèi)存泄露場(chǎng)景與定位方式的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-04-04
  • 解決Golang中g(shù)oroutine執(zhí)行速度的問(wèn)題

    解決Golang中g(shù)oroutine執(zhí)行速度的問(wèn)題

    這篇文章主要介紹了解決Golang中g(shù)oroutine執(zhí)行速度的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05
  • golang sql語(yǔ)句超時(shí)控制方案及原理

    golang sql語(yǔ)句超時(shí)控制方案及原理

    一般應(yīng)用程序在執(zhí)行一條sql語(yǔ)句時(shí),都會(huì)給這條sql設(shè)置一個(gè)超時(shí)時(shí)間,本文主要介紹了golang sql語(yǔ)句超時(shí)控制方案及原理,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Go語(yǔ)言開(kāi)發(fā)區(qū)塊鏈只需180行代碼(推薦)

    Go語(yǔ)言開(kāi)發(fā)區(qū)塊鏈只需180行代碼(推薦)

    這篇文章主要介紹了Go語(yǔ)言開(kāi)發(fā)區(qū)塊鏈只需180行代碼,文章中將不會(huì)涉及工作量證明算法(PoW)以及權(quán)益證明算法(PoS)這類(lèi)的共識(shí)算法。需要的朋友可以參考下
    2018-05-05
  • 提升編程技能:學(xué)習(xí)如何在Go語(yǔ)言中正確格式化時(shí)間

    提升編程技能:學(xué)習(xí)如何在Go語(yǔ)言中正確格式化時(shí)間

    想知道如何在Go語(yǔ)言中輕松地格式化時(shí)間嗎?別再浪費(fèi)時(shí)間了!本文將帶你快速入門(mén),讓你的代碼更加優(yōu)雅高效,快來(lái)學(xué)習(xí)吧!
    2024-01-01
  • go中switch語(yǔ)句的用法詳解

    go中switch語(yǔ)句的用法詳解

    在Go中的switch語(yǔ)句類(lèi)似于C、C++、Java、JavaScript和PHP中的switch語(yǔ)句,不同之處在于它只執(zhí)行匹配的case,因此不需要使用break語(yǔ)句,下面我們就一起來(lái)學(xué)習(xí)一下switch語(yǔ)句的具體使用吧
    2023-09-09
  • 淺談Go連接池的設(shè)計(jì)與實(shí)現(xiàn)

    淺談Go連接池的設(shè)計(jì)與實(shí)現(xiàn)

    本文主要介紹了淺談Go連接池的設(shè)計(jì)與實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Go實(shí)現(xiàn)基于RSA加密算法的接口鑒權(quán)

    Go實(shí)現(xiàn)基于RSA加密算法的接口鑒權(quán)

    這篇文章主要介紹了Go實(shí)現(xiàn)基于RSA加密算法的接口鑒權(quán),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06

最新評(píng)論