構(gòu)建解釋器:part12(譯)

英文原文

不要擔(dān)心走得緩慢捏悬;害怕原地不動(dòng)! - 中國諺語(我表示懷疑H筇荨9馈!)

大家好纺铭,歡迎回來寇钉!

今天我們將要走幾小步來學(xué)習(xí)如何識(shí)別Pascal過程聲明。

babysteps
babysteps

什么是過程聲明彤蔽?一個(gè)過程聲明是一個(gè)語言結(jié)構(gòu)摧莽,它定義了一個(gè)標(biāo)記符,以及一個(gè)關(guān)聯(lián)的Pascal代碼塊顿痪。

在我們深入討論之前镊辕,說幾句關(guān)于Pascal過程以及他們的聲明:

  • Pascal過程沒有返回語句,在到達(dá)程序塊末尾的時(shí)候退出蚁袭。
  • Pascal過程可以相互嵌套征懈。
  • 簡化起見,這篇文章介紹的過程聲明不帶有參數(shù)揩悄。但是卖哎,不要擔(dān)心,我們會(huì)在后續(xù)系列覆蓋這部分內(nèi)容删性。

這是我們今天的測試程序:

PROGRAM Part12;
VAR
   a : INTEGER;

PROCEDURE P1;
VAR
   a : REAL;
   k : INTEGER;

   PROCEDURE P2;
   VAR
      a, z : INTEGER;
   BEGIN {P2}
      z := 777;
   END;  {P2}

BEGIN {P1}

END;  {P1}

BEGIN {Part12}
   a := 10;
END.  {Part12}

就像你看到的亏娜,我們定義了兩個(gè)過程(P1和P2),P2嵌套在P1中蹬挺。在上述代碼中维贺,我用帶有過程名字的注釋來標(biāo)記各個(gè)過程的開始位置和結(jié)束位置。

我們今天的目標(biāo)相當(dāng)明確:學(xué)習(xí)如何識(shí)別上面那樣的代碼巴帮。

首先溯泣,為了添加過程聲明虐秋,我們需要調(diào)整文法。好了垃沦,我們開始客给!

grammar
grammar

過程聲明子規(guī)則包含保留字--PROCEDURE,后面跟著一個(gè)標(biāo)記符(過程名字)肢簿,再跟一個(gè)分號靶剑,分號后面跟著代碼塊,最后以另外一個(gè)分號結(jié)尾池充。

這里是更新后的語法圖抬虽,表示聲明規(guī)則:

syntaxdiagram
syntaxdiagram

從文法以及上述語法圖可以看出,你可以聲明任意數(shù)量想要的過程纵菌。例如,在下面這個(gè)代碼片段中休涤,我們定義了兩個(gè)過程聲明咱圆,P1和P2,位于同一層級功氨。

PROGRAM Test;
VAR
   a : INTEGER;

PROCEDURE P1;
BEGIN {P1}

END;  {P1}

PROCEDURE P1A;
BEGIN {P1A}

END;  {P1A}

BEGIN {Test}
   a := 10;
END.  {Test}

上面的文法和圖表也表明過程聲明是可以嵌套的序苏,因?yàn)檫^程聲明子規(guī)則引用了程序塊規(guī)則,而程序塊規(guī)則又包含聲明規(guī)則捷凄,聲明規(guī)則包含過程聲明忱详,繼而過程聲明是嵌套的。作為提醒跺涤,這里是第十部分關(guān)于程序塊規(guī)則的一個(gè)語法圖和文法:

grammar
grammar

好了匈睁,現(xiàn)在讓我們把目光聚焦到解釋器組件,它也需要更新來支持過程聲明:

更新詞法分析器

我們只要添加新的標(biāo)識(shí)符--PROCEDURE就可以了:

PROCEDURE = 'PROCEDURE'

把PROCEDURE添加進(jìn)保留字中桶错。這里是一份保留字到標(biāo)識(shí)符的完整映射:

RESERVED_KEYWORDS = {
    'PROGRAM': Token('PROGRAM', 'PROGRAM'),
    'VAR': Token('VAR', 'VAR'),
    'DIV': Token('INTEGER_DIV', 'DIV'),
    'INTEGER': Token('INTEGER', 'INTEGER'),
    'REAL': Token('REAL', 'REAL'),
    'BEGIN': Token('BEGIN', 'BEGIN'),
    'END': Token('END', 'END'),
    'PROCEDURE': Token('PROCEDURE', 'PROCEDURE'),
}

更新語法分析器

語法分析器變化總結(jié):

  1. 新的ProcedureDecl 抽象語法樹節(jié)點(diǎn)
  2. 更新語法分析器中過程聲明對應(yīng)的方法航唆,支持過程聲明

實(shí)現(xiàn)這些變化.

1. ProcedureDecl抽象語法樹節(jié)點(diǎn)代表了一個(gè)過程聲明。類構(gòu)造函數(shù)以過程名字以及該過程名字指向的程序塊節(jié)點(diǎn)為參數(shù)院刁。

class ProcedureDecl(AST):
    def __init__(self, proc_name, block_node):
        self.proc_name = proc_name
        self.block_node = block_node

2. 這是更新后的語法分析器的聲明方法

def declarations(self):
    """declarations : VAR (variable_declaration SEMI)+
                    | (PROCEDURE ID SEMI block SEMI)*
                    | empty
    """
    declarations = []

    if self.current_token.type == VAR:
        self.eat(VAR)
        while self.current_token.type == ID:
            var_decl = self.variable_declaration()
            declarations.extend(var_decl)
            self.eat(SEMI)

    while self.current_token.type == PROCEDURE:
        self.eat(PROCEDURE)
        proc_name = self.current_token.value
        self.eat(ID)
        self.eat(SEMI)
        block_node = self.block()
        proc_decl = ProcedureDecl(proc_name, block_node)
        declarations.append(proc_decl)
        self.eat(SEMI)

    return declarations

正如期待的糯钙,上面代碼是相當(dāng)說明性質(zhì)的。它按照前面介紹的文法/語法圖來設(shè)計(jì)退腥。

更新符號表生成器

由于我們目前還不能處理嵌套的過程作用域任岸,所以只是簡單地給SymbolTreeBuilder抽象語法樹訪問者類添加一個(gè)空的visit_ProcedureDecl方法。下一篇文章解決這個(gè)問題狡刘。

def visit_ProcedureDecl(self, node):
    pass

更新解釋器

添加一個(gè)空的visit_ProcedureDecl方法享潜,用來讓我們的解釋器忽略所有過程聲明。

So far, so good.

既然我們已經(jīng)做好了這些必要的準(zhǔn)備颓帝,讓我們看看帶有ProcedureDecl節(jié)點(diǎn)的抽象語法樹長什么樣子米碰。

這是我們的Pascal程序(你可以從Github直接下載):

PROGRAM Part12;
VAR
   a : INTEGER;

PROCEDURE P1;
VAR
   a : REAL;
   k : INTEGER;

   PROCEDURE P2;
   VAR
      a, z : INTEGER;
   BEGIN {P2}
      z := 777;
   END;  {P2}

BEGIN {P1}

END;  {P1}

BEGIN {Part12}
   a := 10;
END.  {Part12}

讓我們生成一顆抽象語法樹窝革,用genastdot.py工具可視化。

$ python genastdot.py part12.pas > ast.dot && dot -Tpng -o ast.png ast.dot
grammar
grammar

在上述的圖形中吕座,你能看到兩個(gè)ProcedureDecl節(jié)點(diǎn):ProcDecl:P1和ProcDecl:P2虐译,分別對應(yīng)過程P1和過程P2。完成使命吴趴!

作為今天最后的一個(gè)條目漆诽,我們快速確認(rèn)一下我們更新后的解釋器能如從前般工作,處理好帶有過程聲明的Pascal程序锣枝。如果還沒有下載厢拭,請下載解釋器和測試程序,在命令行運(yùn)行撇叁。你的輸出看上去應(yīng)該類似這樣:

$ python spi.pi part12.pas
Define: INTEGER
Define: REAL
Lookup: INTEGER
Define: <a:INTEGER>
Lookup: a

Symbol Table contents:
Symbols: [INTEGER, REAL, <a:INTEGER>]

Run-time GLOBAL_MEMORY contents:
a = 10

好供鸠, 所有知識(shí)和經(jīng)驗(yàn)都被我們拿下了,我們準(zhǔn)備解決嵌套作用域的問題陨闹。理解嵌套作用域能幫助我們分析嵌套過程以及讓我們能夠處理過程和函數(shù)調(diào)用楞捂。這就是我們在下一篇文章中將要做的事情:深入理解嵌套作用域。下次見趋厉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寨闹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子君账,更是在濱河造成了極大的恐慌繁堡,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乡数,死亡現(xiàn)場離奇詭異椭蹄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瞳脓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門塑娇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人劫侧,你說我怎么就攤上這事埋酬。” “怎么了烧栋?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵写妥,是天一觀的道長。 經(jīng)常有香客問我审姓,道長珍特,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任魔吐,我火速辦了婚禮扎筒,結(jié)果婚禮上莱找,老公的妹妹穿的比我還像新娘。我一直安慰自己嗜桌,他們只是感情好奥溺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著骨宠,像睡著了一般浮定。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上层亿,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天桦卒,我揣著相機(jī)與錄音,去河邊找鬼匿又。 笑死方灾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碌更。 我是一名探鬼主播迎吵,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼针贬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拢蛋,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤桦他,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后谆棱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體快压,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年垃瞧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蔫劣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡个从,死狀恐怖脉幢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嗦锐,我是刑警寧澤嫌松,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站奕污,受9級特大地震影響萎羔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碳默,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一贾陷、第九天 我趴在偏房一處隱蔽的房頂上張望缘眶。 院中可真熱鬧,春花似錦髓废、人聲如沸巷懈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽砸喻。三九已至,卻和暖如春蒋譬,著一層夾襖步出監(jiān)牢的瞬間割岛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工犯助, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留癣漆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓剂买,卻偏偏與公主長得像惠爽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子瞬哼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理婚肆,服務(wù)發(fā)現(xiàn),斷路器坐慰,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法较性,類相關(guān)的語法,內(nèi)部類的語法结胀,繼承相關(guān)的語法赞咙,異常的語法,線程的語...
    子非魚_t_閱讀 31,627評論 18 399
  • 快樂的時(shí)候糟港, 你想她攀操。 悲傷的時(shí)候, 你想她秸抚。 直到你和她在一起速和, 她看著你,你看著她剥汤, 一同攜手把夢圓健芭!
    小劇在成長閱讀 137評論 0 7
  • 很久沒有正經(jīng)寫過小文章,小豆腐塊秀姐,小詩歌了慈迈。近兩年,光寫郵件就耗掉了太多力氣。公司里口頭說話不算數(shù)痒留,電話也只能當(dāng)急...
    梅麗爾閱讀 348評論 0 0
  • 我是一滴被人遺忘的眼淚 在風(fēng)的哀曲里 我消散了 我是一顆被人丟棄的蘋果 在空氣的壓抑下 我低落了 我是一朵被人忘卻...
    煙波釣者閱讀 160評論 2 10