簡易Parser入門【一】:從樹的遞歸開始

Parser就是將字符串轉化成AST(Abstract Syntax Tree)的程序python

首先咱們從樹類的簡單解析開始,假設有一個樹節點(它是一個二叉樹節點):bash

class Tr:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

咱們用這個樹節點構造一棵樹:函數

t_root = Tr(5, Tr(3, Tr(4), Tr(6)),
               Tr(1, Tr(2), Tr(7)))

它的結構如圖所示,咱們想打印從根節點到每一個葉子節點的路徑怎麼辦呢?遍歷樹通常都能想到用遞歸,可是遞歸到底遞歸什麼東西呢?遞歸函數的參數如何選擇?返回什麼?code

思考遞歸的時候,咱們能夠從問題點出發,先尋找中止遞歸的條件。咱們須要打印從根節點到每一個葉子節點的路徑,因此中止條件就是到達葉子節點了。能夠先用代碼寫出來:blog

def print_leaf(tr_in):
    # type: (Tr) -> None
    if tr_in.left is None and tr_in.right is None:
        # todo: stop here and do something

咱們達到中止條件須要作什麼呢?須要打印。打印什麼?打印從根節點到葉子節點的路徑。好了,咱們如今達到了葉子節點,函數擁有該節點tr_in的val,可是以前路徑的值咱們尚未。咱們須要有,那麼先假設咱們有一個,這個怎麼來的呢,根據思考,以前路徑的值固然是沿途遍歷節點傳進來的,那麼天然須要當成函數輸入傳進來:遞歸

def print_leaf(tr_in, str_in):
    # type: (Tr, str) -> None
    if tr_in.left is None and tr_in.right is None:
        print(str_in + str(tr_in.val))

接着咱們思考,咱們沒有到達葉子節點的時候,須要作什麼。到達葉子節點是中止的標誌,那麼沒有到達葉子節點就是遞歸的標誌。咱們構造左節點或右節點還有葉子的狀況:字符串

def print_leaf(tr_in, str_in=""):
    # type: (Tr, str) -> None
    if tr_in.left is not None:
        print_leaf(tr_in.left, str_in + str(tr_in.val))

    if tr_in.right is not None:
        print_leaf(tr_in.right, str_in + str(tr_in.val))

    if tr_in.left is None and tr_in.right is None:
        print(str_in + str(tr_in.val))

這樣整個代碼就寫好了,咱們實現了一個遞歸函數,它遇到有子節點的狀況就遞歸調用本身,並一路把沿途的值存到str_in裏邊,到達最深層葉子的時候就中止,並把路徑打印出來,完整代碼以下:it

class Tr:

    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


def print_leaf(tr_in, str_in=""):
    # type: (Tr, str) -> None
    if tr_in.left is not None:
        print_leaf(tr_in.left, str_in + str(tr_in.val))

    if tr_in.right is not None:
        print_leaf(tr_in.right, str_in + str(tr_in.val))

    if tr_in.left is None and tr_in.right is None:
        print(str_in + str(tr_in.val))


if __name__ == "__main__":
    t_root = Tr(5, Tr(3, Tr(4), Tr(6)),
                   Tr(1, Tr(2), Tr(7)))
    print_leaf(t_root)

打印效果以下:class

534
536
512
517
相關文章
相關標籤/搜索