解釋器模式

2021-02-15 C Sharp基礎

解釋器(Interpreter)模式的定義:給分析對象定義一個語言,並定義該語言的文法表示,再設計一個解析器來解釋語言中的句子。也就是說,用編譯語言的方式來分析應用中的實例。這種模式實現了文法表達式處理的接口,該接口解釋一個特定的上下文。

這裡提到的文法和句子的概念同編譯原理中的描述相同,「文法」指語言的語法規則,而「句子」是語言集中的元素。例如,漢語中的句子有很多,「我是中國人」是其中的一個句子,可以用一棵語法樹來直觀地描述語言中的句子。

解釋器模式是一種類行為型模式,其主要優點如下:

解釋器模式的主要缺點如下:

執行效率較低:解釋器模式中通常使用大量的循環和遞歸調用,當要解釋的句子較複雜時,其運行速度很慢,且代碼的調試過程也比較麻煩。

會引起類膨脹:解釋器模式中的每條規則至少需要定義一個類,當包含的文法規則很多時,類的個數將急劇增加,導致系統難以管理與維護。

可應用的場景比較少:在軟體開發中,需要定義語言文法的應用實例非常少,所以這種模式很少被使用到。

解釋器模式常用於對簡單語言的編譯或分析實例中,為了掌握好它的結構與實現,必須先了解編譯原理中的「文法、句子、語法樹」等相關概念。

文法文法是用於描述語言的語法結構的形式規則。沒有規矩不成方圓,任何事情都要有規則,語言也一樣,不管它是機器語言還是自然語言,都有它自己的文法規則。例如,中文中的「句子」的文法如下:

〈句子〉::=〈主語〉〈謂語〉〈賓語〉
〈主語〉::=〈代詞〉|〈名詞〉
〈謂語〉::=〈動詞〉
〈賓語〉::=〈代詞〉|〈名詞〉
〈代詞〉你|我|他
〈名詞〉7大學生I筱霞I英語
〈動詞〉::=是|學習

註:這裡的符號「::=」表示「定義為」的意思,用「〈」和「〉」括住的是非終結符,沒有括住的是終結符。

句子:句子是語言的基本單位,是語言集中的一個元素,它由終結符構成,能由「文法」推導出。例如,上述文法可以推出「我是大學生」,所以它是句子。

語法樹:語法樹是句子結構的一種樹型表示,它代表了句子的推導結果,它有利於理解句子語法結構的層次。下圖所示是「我是大學生」的語法樹:

有了以上基礎知識,現在來介紹解釋器模式的結構就簡單了。解釋器模式的結構與組合模式相似,不過其包含的組成元素比組合模式多,而且組合模式是對象結構型模式,而解釋器模式是類行為型模式

模式的結構

解釋器模式包含以下主要角色:

抽象表達式(Abstract Expression)角色:定義解釋器的接口,約定解釋器的解釋操作,主要包含解釋方法 Interpret()。

終結符表達式(Terminal Expression)角色:是抽象表達式的子類,用來實現文法中與終結符相關的操作,文法中的每一個終結符都有一個具體終結表達式與之相對應。

非終結符表達式(Nonterminal Expression)角色:也是抽象表達式的子類,用來實現文法中與非終結符相關的操作,文法中的每條規則都對應於一個非終結符表達式。

環境(Context)角色:通常包含各個解釋器需要的數據或是公共的功能,一般用來傳遞被所有解釋器共享的數據,後面的解釋器可以從這裡獲取這些值。

客戶端(Client):主要任務是將需要分析的句子或表達式轉換成使用解釋器對象描述的抽象語法樹,然後調用解釋器的解釋方法,當然也可以通過環境角色間接訪問解釋器的解釋方法。

解釋器模式的結構圖如圖所示:

模式的實現

解釋器模式實現的關鍵是定義文法規則、設計終結符類與非終結符類、畫出結構圖,必要時構建語法樹,其代碼結構如下:

static void Main(string[] args){    Context context = new Context();    IList<AbstractExpression> list = new List<AbstractExpression>();    list.Add(new TerminalExpression());    list.Add(new NonterminalExpression());    list.Add(new TerminalExpression());    list.Add(new TerminalExpression());
foreach (AbstractExpression exp in list) { exp.Interpret(context); }
Console.Read();}

class Context{    private string input;    public string Input    {        get { return input; }        set { input = value; }    }    private string output;    public string Output    {        get { return output; }        set { output = value; }    }} abstract class AbstractExpression{    public abstract void Interpret(Context context);} class TerminalExpression : AbstractExpression{    public override void Interpret(Context context)    {        Console.WriteLine("終端解釋器");    }}class NonterminalExpression : AbstractExpression{    public override void Interpret(Context context)    {        Console.WriteLine("非終端解釋器");    }}

程序運行結果如下:

前面介紹了解釋器模式的結構與特點,下面分析它的應用場景:

注意:解釋器模式在實際的軟體開發中使用比較少,因為它會引起效率、性能以及維護等問題。如果碰到對表達式的解釋,在 C# 中可以用 Expression類 或 Flee 等來設計

相關焦點

  • 設計模式之——解釋器模式
    簡介今天給大家介紹的設計模式叫做「解釋器模式」,該模式是「行為型設計模式」中的一員。解釋器模式的核心思想是:給定一個語言,定義它的文法的一種表示,並定義一個解釋器,使用該解釋器來解釋語言中的句子。聽完這句話話是不是頓時感覺一臉懵?什麼語言、文法、句子,都是些什麼鬼?別慌讓「菜鳥」來給你分析一波。
  • 「補課」進行時:設計模式(20)——解釋器模式
    解釋器模式 解釋器模式這個模式和前面的訪問者模式比較像,當然,我說的比較像是難的比較像,以及使用率是真的比較低,基本上沒有使用的場景,訪問者模式還有點使用場景,解釋器模式,我們又不寫解釋器,這玩意 JVM 都幫我們實現掉了,哪用我們自己實現。
  • MicroPython的交互式解釋器模式 (又稱REPL)
    此部分介紹了MicroPython的交互式解釋器模式的特性,其常用術語為REPL(讀取read-評估eval-列印print-循環
  • Google Assistant解釋器模式植入iOS和Android系統
    今年年初,谷歌將其實時翻譯功能,即解釋器模式,引入了Google Home揚聲器和Smart Display上。現在,該功能正在全球範圍內推廣到Android和iOS手機上。要使用翻譯器模式,您可以這樣說「嘿,谷歌,做我的德語翻譯器吧」,或者「嘿,谷歌,幫我說泰語吧」。谷歌助手會聽對話,翻譯後的文字記錄會出現在你的手機上。Google Assistant可能會通過巧妙的回答提供建議的回答,以使對話更快、更流暢。
  • 《前端5分鐘》之使用解釋器模式實現獲取元素Xpath路徑的算法
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫前端領域裡基於javascript的設計模式和算法有很多,在很多複雜應用中也扮演著很重要的角色,接下來就介紹一下javascript設計模式中的解釋器模式,並用它來實現一個獲取元素Xpath路徑的算法
  • Python編譯器與解釋器
    對於Python語言,廣義上的「編譯器」,叫做解釋器。三、 編譯器與解釋器編譯器/解釋器:高級語言與機器之間的翻譯官都是將代碼翻譯成機器可以執行的二進位機器碼,只不過在運行原理和翻譯過程有不同而已。那麼兩者有什麼區別呢?用一個通俗的例子進行比喻:我們去飯館吃飯,點了八菜一湯。
  • python解釋器到底是什麼?
    有很多入門學習python的同學都沒有搞清python解釋器是怎麼回事,所以今天在這裡追根溯源的解釋一下。 計算機程式語言 從計算機程式語言說起,它主要分為三類:機器語言、彙編語言、高級語言。
  • Python IDE和解釋器的區別是什麼?
    2、解釋器(1)什麼是解釋器我們都知道,Python是一門解釋型語言,解釋器是Python運行必不可少的一種工具。所以,我們搭建Pyhton環境,本質上就是對Pyhton進行配置或者定製。而解釋器是能夠執行用其他計算機語言編寫的程序的系統軟體,它是一種翻譯程序。它的執行方式是一邊翻譯一邊執行,因此其執行效率一般偏低,但是解釋器的實現較為簡單,而且編寫源程序的高級語言可以使用更加靈活和富於表現力的語法。
  • 【答疑釋惑】JavaScript解釋器是幹什麼用的?
    問題:JavaScript解釋器主要是幹什麼用的?解答:JavaScript是一門腳本語言,是需要被別人解釋執行的,這個別人就是JavaScript解釋器。它讀取一條JS語句、翻譯、執行,然後再讀取下一條JS語句,周而復始。
  • 【Python面試】 說說Python解釋器種類以及特點?
    開始今天的題目:問:說說Python解釋器種類以及特點?答:Python是一門解釋器語言,代碼想運行,必須通過解釋器執行,Python存在多種解釋器,分別基於不同語言開發,每個解釋器有不同的特點,但都能正常運行Python代碼。
  • 實現JavaScript語言解釋器(一)
    因此為了更好地理解JavaScript的語言特性,我就自己動手實現了一個叫做Simple的JavaScript語言解釋器,這個解釋器十分簡單,它基於TypeScript實現了JavaScript語法的子集,主要包括下面這些功能:複雜數據類型object, array和function
  • Python 之父考慮重構 Python 解釋器​​​​​​​
    在該文中,Guido 說他正在考慮使用 PEG Parser 代替現有的類 LL(1) Parser(名為pgen),來重構 Python 解釋器。原因是現在的 pgen 限制了 Python 語法的自由度,使得一些語法難以實現,也讓當前的語法樹不夠整潔,一定程度上影響了語法樹的表意,不能最好地體現設計者的意圖。
  • 用 Python 實現 Python 解釋器(下)
    (塊的細節不是解釋器的核心,我們不會花時間在它身上,把它列在這裡,是因為 Byterun 需要它。)VirtualMachine 類每次程序運行時只會創建一個VirtualMachine實例,因為我們只有一個 Python 解釋器。VirtualMachine 保存調用棧、異常狀態、在幀之間傳遞的返回值。
  • 11 個優秀的 Python 編譯器和解釋器
    其解釋器可在Windows、Linux 和 Mac OS 等多種作業系統上使用。它的可移植性和可伸縮性等特性使得它更加容易被運用。本文重點介紹了適用於 Python 程式設計師的 11 種優秀的 Python 編譯器和解釋器。很好的 Python 編譯器和解釋器1.Brython
  • 實例教程,用python實現字節碼編譯器和解釋器
    對於一個語言來說,有兩個最重要功能,編譯器和解釋器。實現由原始碼到字節碼的轉化,然後才能執行。本文中蟲蟲以CPython 3.6位元組碼為實例,實現一個我們自己的字節碼編譯器和解釋器,以此來熟悉基本的編譯器工作原理(),當然如果想深入理論學習,建議大家去學習了《編譯原理》這本教材。
  • 微軟宣布開源GW-BASIC解釋器
    作為一款 BASIC 程式語言解釋器,GW-BASIC 由 IBM Advanced BASIC / BASICA 衍生而來(算是 Microsoft BASIC 的一項移植)。不過今日,微軟已經正式將它開源,感興趣的朋友可到 GitHub 上查看完整的源碼。
  • BM即將推出WASM解釋器,目前已通過測試,解釋執行和編譯執行了解一下
    BM在EOS官方群裡表示,「即將推出WASM解釋器,用來解釋執行 WebAssembly 智能合約,目前已經通過所有測試並接入到主網和測試網。EOS之前本來是編譯執行,即直接將代碼編譯成為可執行的二進位機器碼。
  • eval5 1.2.0 發布:JavaScript 解釋器
    eval5是完全基於JavaScript編寫的JavaScript解釋器,支持ECMA5語法。
  • 深入 Python 解釋器源碼,我終於搞明白了字符串駐留的原理!
    在本文中,我們將深入研究 Python 的內部實現,並了解 Python 如何使用一種名為字符串駐留(String Interning)的技術,實現解釋器的高性能。全文提綱如下:(在 Python貓 公眾號回複數字「0215」,下載思維導圖)字符串駐留是一種編譯器/解釋器的優化方法,它通過緩存一般性的字符串,從而節省字符串處理任務的空間和時間
  • GoF 的 23 種設計模式的分類和功能
    根據目的來分根據模式是用來完成什麼工作來劃分,這種方式可分為創建型模式、結構型模式和行為型模式 3 種。創建型模式:用於描述「怎樣創建對象」,它的主要特點是「將對象的創建與使用分離」。GoF 中提供了單例、原型、工廠方法、抽象工廠、建造者等 5 種創建型模式。