Interpreter (Entwurfsmuster)

Der Interpreter (englisch interpreter pattern) ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung und gehört zu der Kategorie der Verhaltensmuster (englisch behavioural patterns). Das Muster ist eines der sogenannten GoF-Muster.

Das Interpretermuster definiert eine Repräsentation für die Grammatik einer Sprache und die Möglichkeit, Sätze dieser Sprache zu interpretieren.[1]

Verwendung

Wenn ähnliche Probleme oft genug gelöst werden müssen, ist es häufig sinnvoll, das Problem mit einer einfachen Sprache zu beschreiben. Beispiele für ein solches Problem sind das Auswerten von regulären Ausdrücken und die Berechnung von logischen oder mathematischen Formeln.

UML-Diagramm

UML-Klassendiagramm
UML-Klassendiagramm

Bestandteile

Die abstrakte Klasse AbstrakterAusdruck schreibt eine Methode Interpretiere() vor, die von allen abgeleiteten, konkreten Klassen implementiert werden muss und den entsprechenden Ausdruck auswertet.

Ein TerminalerAusdruck steht für einen Ausdruck, der keinen Unterausdruck hat, d. h. für einen festen Wert innerhalb eines gemäß der Grammatik geformten Satzes. Z. B. steht Zahl für einen Zahlenwert innerhalb einer mathematischen Formel.

Ein NonterminalerAusdruck steht für einen Ausdruck, der aus Unterausdrücken besteht, zum Beispiel Addition oder Multiplikation, die beide zwei Operanden als Unterausdrücke benötigen. Ein Unterausdruck kann sowohl ein TerminalerAusdruck als auch ein NichtterminalAusdruck sein.

Für den zu interpretierenden Satz wird gemäß der Grammatik ein Syntaxbaum aus Nichtterminal- und Terminalausdrücken aufgebaut. Dies kann durch einen externen Parser oder den Klienten selbst geschehen. Der Klient wertet diesen Syntaxbaum aus, indem er für den obersten Ausdruck die Methode Interpretiere() aufruft.

Im Kontext werden die konkreten Werte der Terminalausdrücke gekapselt, mit denen der Satz interpretiert werden soll, z. B. die Belegung von Variablen.

Vorteile

Die Grammatik kann durch dieses Entwurfsmuster leicht geändert oder erweitert, derselbe Satz oder Ausdruck durch Ändern des Kontextes immer wieder auf neue Art und Weise interpretiert werden.

Nachteile

Für komplexe Grammatiken und sehr große Sätze ist das Interpretermuster ungeeignet, da die Klassenhierarchie zu groß wird und die Effizienz bei großen Syntaxbäumen leidet. Sollen komplexe Grammatiken verarbeitet werden, eignet sich Rekursiver Abstieg oder Parsergenerator besser. Große Syntaxbäume werden üblicherweise in andere Strukturen konvertiert und zum Beispiel mit Hilfe von Zustandsautomaten bearbeitet.

Beispiele

Diese C++11 Implementierung basiert auf dem vor C++98 Beispielcode im Buch Entwurfsmuster.

#include <iostream>
#include <map>
#include <cstring>

class Kontext;

class BoolscherAusdruck {
public:
  BoolscherAusdruck() = default;
  virtual ~BoolscherAusdruck() = default;
  virtual bool werteAus(Kontext&) = 0;
  virtual BoolscherAusdruck* ersetze(const char*, BoolscherAusdruck&) = 0;
  virtual BoolscherAusdruck* kopiere() const = 0;
};

class VariablenAusdruck;

class Kontext {
public:
  Kontext() :m() {}
  bool lookup(const VariablenAusdruck* key) { return m.at(key); }
  void weiseZu(const VariablenAusdruck* key, bool value) { m[key] = value; }
private:
  std::map<const VariablenAusdruck*, bool> m;
};

class VariablenAusdruck : public BoolscherAusdruck {
public:
  VariablenAusdruck(const char* name_) :name(nullptr) {
    name = strdup(name_);
  }
  virtual ~VariablenAusdruck() = default;
  virtual bool werteAus(Kontext& einKontext) {
    return einKontext.lookup(this);
  }
  virtual BoolscherAusdruck* ersetze(const char* name_, BoolscherAusdruck& ausdruck) {
    if (0 == strcmp(name_, name)) {
      return ausdruck.kopiere();
    } else {
      return new VariablenAusdruck(name);
    }
  }
  virtual BoolscherAusdruck* kopiere() const {
    return new VariablenAusdruck(name);
  }
  VariablenAusdruck(const VariablenAusdruck&) = delete; // Dreierregel
  VariablenAusdruck& operator=(const VariablenAusdruck&) = delete;
private:
  char* name;
};

class UndAusdruck : public BoolscherAusdruck {
public:
  UndAusdruck(BoolscherAusdruck* op1, BoolscherAusdruck* op2)
    :operand1(nullptr), operand2(nullptr) {
    operand1 = op1;
    operand2 = op2;
  }
  virtual ~UndAusdruck() = default;
  virtual bool werteAus(Kontext& einKontext) {
    return operand1->werteAus(einKontext) && operand2->werteAus(einKontext);
  }
  virtual BoolscherAusdruck* ersetze(const char* name_, BoolscherAusdruck& ausdruck) {
    return new UndAusdruck(operand1->ersetze(name_, ausdruck),
      operand2->ersetze(name_, ausdruck));
  }
  virtual BoolscherAusdruck* kopiere() const {
    return new UndAusdruck(operand1->kopiere(), operand2->kopiere());
  }
  UndAusdruck(const UndAusdruck&) = delete; // Dreierregel
  UndAusdruck& operator=(const UndAusdruck&) = delete;
private:
  BoolscherAusdruck* operand1;
  BoolscherAusdruck* operand2;
};

int main() {
  BoolscherAusdruck* ausdruck;
  Kontext kontext;
  VariablenAusdruck* x = new VariablenAusdruck("X");
  VariablenAusdruck* y = new VariablenAusdruck("Y");
  ausdruck = new UndAusdruck(x, y);

  kontext.weiseZu(x, false);
  kontext.weiseZu(y, true);
  bool resultat = ausdruck->werteAus(kontext);
  std::cout << resultat << '\n';

  kontext.weiseZu(x, true);
  kontext.weiseZu(y, true);
  resultat = ausdruck->werteAus(kontext);
  std::cout << resultat << '\n';
}

Die Programmausgabe ist:

0
1

In der umgekehrten polnischen Notation (UPN) sind Ausdrücke gemäß folgender Grammatik gegeben:

expression ::= plus | minus | variable | number
plus ::= expression expression '+'
minus ::= expression expression '-'
variable ::= 'a' | 'b' | 'c' | ... | 'z'
number ::= '-'? ('0' | '1' | '2' | ... | '9')+

Beispiele für Ausdrücke, die dieser Grammatik entsprechen, sind

1 1 +
a 2 + 3 -
5 4 - a b + +

Der Interpreter sieht für jeden Terminal-Ausdruck und für jeden Nichtterminal-Ausdruck eine konkrete Klasse vor, die eine gemeinsame Schnittstelle implementiert. Diese Schnittstelle schreibt vor, dass die jeweilige Klasse einen zu ihr passenden Ausdruck in einem Kontext interpretieren können muss. Der Kontext ist hier die Belegung der Variablen:

import java.util.*;

/**
 * Interface for all expression types
 */
interface IExpressable {
    /**
     * Interprets the passed variables
     * @param variables
     * @return Result
     */
    int interpret(final HashMap<String, Integer> variables);
}

/**
 * Class for a non-terminal expression
 */
class Plus implements IExpressable {
    /** Left operation */
    private IExpressable leftOperand = null;
    /** Right operation */
    private IExpressable rightOperand = null;

    /**
     * Constructor
     * @param left Left expression
     * @param right Right expression
     */
    public Plus(final IExpressable left, final IExpressable right) {
        leftOperand  = left;
        rightOperand = right;
    }

    /* (non-Javadoc)
     * @see interpreter.IExpressable#interpret(java.util.HashMap)
     */
    @Override
    public int interpret(final HashMap<String, Integer> variables) {
        return leftOperand.interpret(variables)
                + rightOperand.interpret(variables);
    }

    /**
     * Converts the content to a readable string by overloading the Object
     * method.
     * @return String representation
     */
    public String toString() {
        return leftOperand.toString() + " + "
                + rightOperand.toString();
    }
}

/**
 * Class for a non-terminal expression
 */
class Minus implements IExpressable {
    /** Left operation */
    private IExpressable leftOperand = null;
    /** Right operation */
    private IExpressable rightOperand = null;

    /**
     * Constructor
     * @param left Left expression
     * @param right Right expression
     */
    public Minus(final IExpressable left,
            final IExpressable right) {
        leftOperand  = left;
        rightOperand = right;
    }

    /* (non-Javadoc)
     * @see interpreter.IExpressable#interpret(java.util.HashMap)
     */
    @Override
    public int interpret(final HashMap<String, Integer> variables) {
        return leftOperand.interpret(variables)
                - rightOperand.interpret(variables);
    }
}

/**
 * Class for a terminal expression
 */
class Variable implements IExpressable {
    /** Variable name */
    private String name = null;

    /**
     * Constructor
     * @param name
     */
    public Variable(final String name) {
        this.name = name;
    }

    /* (non-Javadoc)
     * @see interpreter.IExpressable#interpret(java.util.HashMap)
     */
    @Override
    public int interpret(final HashMap<String, Integer> variables) {
        return variables.get(name);
    }
}

/**
 * Class for a terminal expression
 */
class Number implements IExpressable {
    /** Number object */
    private int number = 0;

    /**
     * Constructor
     * @param number
     */
    public Number(final int number) {
        this.number = number;
    }

    /* (non-Javadoc)
     * @see interpreter.IExpressable#interpret(java.util.HashMap)
     */
    @Override
    public int interpret(final HashMap<String, Integer> variables) {
        return number;
    }
}

Der Interpreter beschäftigt sich nicht mit dem Parsen des ursprünglichen Ausdrucks und dem Erzeugen des Syntax-Baumes, der dem Ausdruck entspricht.[2] Der Vollständigkeit halber hier die Implementierung eines einfachen Parsers. Er ist unvollständig in dem Sinne, dass er manche nicht-gültige Ausdrücke nicht verwirft! (Aber alle gültigen Ausdrücke parst er korrekt und erzeugt den Syntax-Baum dafür.)

class Parser {
    /**
     * Parser method
     * @param expression
     * @return Parsed result
     */
    static public IExpressable parseExpression(final String expression) {
        IExpressable syntaxTree = null;
        Pattern numberPattern = Pattern.compile("[+-]?\\d+");

        Stack<IExpressable> expressionStack = new Stack<IExpressable>();
        for (String token : expression.split(" ")) {
            if  (token.equals("+")) {
                IExpressable subExpression = new Plus(expressionStack.pop(),
                        expressionStack.pop());
                expressionStack.push(subExpression);
            } else if (token.equals("-")) {
                IExpressable subExpression = new Minus(expressionStack.pop(),
                        expressionStack.pop());
                expressionStack.push(subExpression);
            } else if(numberPattern.matcher(token).matches()) {
                expressionStack.push(new Number(Integer.parseInt(token.trim())));
            } else expressionStack.push(new Variable(token));
        }

        syntaxTree = expressionStack.pop();

        return syntaxTree;
    }
}

/**
 * Test class
 */
public class InterpreterExample {
    /**
     * Test method for the interpreter
     * @param arguments
     */
    public static void main(final String[] arguments) {
        final String expression = "w x z - + -2 +";
        final HashMap<String, Integer> variables =
                new HashMap<String, Integer>();

        variables.put("w", 5);
        variables.put("x", 33);
        variables.put("z", 10);

        final IExpressable tree = Parser.parseExpression(expression);

        System.out.println(tree.interpret(variables));
    }
}

Es ist nun recht einfach, die Grammatik zu erweitern und die erweiterten Ausdrücke zu interpretieren. Um eine Quadrier-Funktion sqr einzubauen (einen unären Operator), muss nur eine neue Klasse eingeführt werden:

/**
 * Class for a non-terminal expression
 */
class SqrFunction implements IExpressable {
    /** Operand */
    IExpressable operand = null;

    /**
     * Constructor
     * @param operand
     */
    public SqrFunction(final IExpressable operand)  {
        this.operand = operand;
    }

    /* (non-Javadoc)
     * @see interpreter.IExpressable#interpret(java.util.HashMap)
     */
    @Override
    public int interpret(final HashMap<String,Integer> variables) {
        int tmp = operand.interpret(variables);
        return tmp*tmp;
    }
}

Der (unvollständige) Parser kann folgendermaßen erweitert werden, um auch sqr-Ausdrücke zu parsen:

     else if(token.equals("sqr")) {
        IExpressable subExpression = new SqrFunction(expressionStack.pop());
                expressionStack.push( subExpression );
     }

Verwandte Entwurfsmuster

Der Syntaxbaum wird durch ein Kompositum beschrieben.

Ein Visitor kann das Verhalten aller Nichtterminalsymbole in sich kapseln, um die Anzahl der Klassen zu verringern und/oder das Verhalten dieser austauschbar zu gestalten.

Mit Hilfe des Flyweight können Terminalsymbole gemeinsam genutzt werden.

Ein Iterator kann verwendet werden, um den Syntaxbaum zu traversieren.

Einzelnachweise

  1. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Entwurfsmuster. 5. Auflage. Addison-Wesley, 1996, ISBN 3-8273-1862-9, S. 319.
  2. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995, ISBN 0-201-63361-2, S. 247

Read other articles:

F.C. KøbenhavnNama lengkapFootball Club KøbenhavnBerdiri1 Juli 1992; 31 tahun lalu (1992-07-01)StadionStadion Parken, Kopenhagen, Denmark(Kapasitas: 38.065)PemilikParken Sport & EntertainmentKetuaAllan AgerholmKepala pelatihJacob NeestrupLigaSuperliga2022–23Superliga, ke-1 dari 12 (Juara)Situs webSitus web resmi klub Kostum kandang Kostum tandang Kostum ketiga Football Club København, dikenal juga dengan FC København, FC Copenhagen, FC Kopenhagen, Copenhagen, atau FCK) (pe...

 

Juan Carlos Henao Informasi pribadiNama lengkap Juan Carlos Henao ValenciaTanggal lahir 30 Desember 1971 (umur 52)Tempat lahir Medellín, ColombiaTinggi 1,81 m (5 ft 11+1⁄2 in)Posisi bermain KiperInformasi klubKlub saat ini Once CaldasNomor 1Karier senior*Tahun Tim Tampil (Gol)1991 Dinastia Río Sucio 4 (0)1992–2004 Once Caldas 259 (0)2002 →Atlético Bucaramanga (pinjaman) 25 (0)2005 Santos 4 (0)2005–2007 Millonarios 39 (0)2007–2008 Maracaibo 38 (0)2009–20...

 

Helen dari Yunani dan DenmarkIbu Suri RumaniaKelahiran(1896-05-02)2 Mei 1896Athens, Kerajaan YunaniKematian28 November 1982(1982-11-28) (umur 86)Lausanne, SwissPemakaman2 Desember 1982Pemakaman Bois-de-Vaux, Lausanne, SwissWangsaGlücksburgAyahKonstantinus I dari YunaniIbuSophia dari PrusiaPasanganCarol II dari Rumania ​ ​(m. 1921; bercerai 1928)​AnakMichael I dari RumaniaAgamaGereja Ortodoks Helen dari Yunani dan Denmark (bahasa Yunani:...

Nama: -Rehan Putra dwi. A -Ega saputra -Tazarudin -Jovan -Muhammad Nazriel -Muhammad Gumilang |provinsi =Jawa Barat |dati2 =Kabupaten |nama dati2 =Cirebon |kecamatan =Karangwareng |kode pos=45184 |luas =3,1624 km2 |penduduk =4.297 jiwa |kepadatan =1358,78 jiwa/km2 }} Kubangdeleg adalah desa di kecamatan Karangwareng, Cirebon, Jawa Barat, Indonesia. Terdiri dari 6 dusun, 4 dusun di induk dan 2 dusun cantilan yaitu Dusun 5 Kampung baru dan dusun 6 yaitu Kampung Bantar Sari. Dari segi geogrgafis...

 

Duta Besar Indonesia untuk KenyaMerangkap Republik Demokratik Kongo, Somalia, Uganda, UNEP, dan UN-HABITATLambang Kementerian Luar Negeri Republik IndonesiaPetahanaMohamad Hery Saripudinsejak 14 September 2020KantorNairobi, KenyaDitunjuk olehPresiden IndonesiaPejabat perdanaR. SupangatDibentuk1982[1]Situs webkemlu.go.id/nairobi/id Berikut adalah daftar diplomat Indonesia yang pernah menjabat Duta Besar Republik Indonesia untuk Kenya: No. Foto Nama Mulai menjabat Selesai menjabat ...

 

Laksamana TNI (Purn.)Slamet Soebijanto Kepala Staf TNI Angkatan Laut ke-19Masa jabatan18 Februari 2005 – 7 November 2007PresidenSusilo Bambang Yudhoyono PendahuluBernard Kent SondakhPenggantiSumardjono Informasi pribadiLahir4 Juni 1951 (umur 72)Mojokerto, Jawa TimurKebangsaanIndonesiaAlma materAKABRI (1973)ProfesiTentaraKarier militerPihak IndonesiaDinas/cabang TNI Angkatan LautMasa dinas1973 - 2007Pangkat Laksamana TNISatuanKorps PelautSunting kotak info �...

NacionalCalcio Naça, Leão da Vila Municipal, Leão do Amazonas , Rei do Amazonas, Clube da Estrela Azul, O Maior do Amazonas, N.F.C. Segni distintivi Uniformi di gara Casa Trasferta Colori sociali Blu, bianco Dati societari Città Manaus Nazione  Brasile Confederazione CONMEBOL Federazione CBF Campionato Campionato AmazonenseSérie D Fondazione 1913 Presidente Nazareno Pereira Allenatore Alan George Stadio Arena da Amazônia(42 374 posti) Sito web www.nacionalfc.com.br Palmarès ...

 

Willem van OuthoornPotret Willem van Outhoorn Gubernur Jenderal Hindia Belanda ke-16Masa jabatan1684–1691PendahuluJohannes CamphuysPenggantiJoan van Hoorn Informasi pribadiLahir(1635-05-04)4 Mei 1635 Larike, Leihitu Barat, Maluku TengahMeninggal27 November 1720(1720-11-27) (umur 85) Batavia, Hindia BelandaKebangsaanBelandaPekerjaanGubernur KolonialSunting kotak info • L • B Willem van Outhoorn (4 Mei 1635 – 27 November 1720) adalah Gubernur-Jenderal Hindia...

 

この項目には、一部のコンピュータや閲覧ソフトで表示できない文字が含まれています(詳細)。 数字の大字(だいじ)は、漢数字の一種。通常用いる単純な字形の漢数字(小字)の代わりに同じ音の別の漢字を用いるものである。 概要 壱万円日本銀行券(「壱」が大字) 弐千円日本銀行券(「弐」が大字) 漢数字には「一」「二」「三」と続く小字と、「壱」「�...

Belgian cyclist This article relies largely or entirely on a single source. Relevant discussion may be found on the talk page. Please help improve this article by introducing citations to additional sources.Find sources: Emile Brichard – news · newspapers · books · scholar · JSTOR (March 2021) Emile BrichardPersonal informationBorn(1899-12-20)20 December 1899Arsimont, BelgiumDied8 July 2004(2004-07-08) (aged 104)Villers-Poterie, BelgiumTeam inform...

 

artikel ini perlu dirapikan agar memenuhi standar Wikipedia. Tidak ada alasan yang diberikan. Silakan kembangkan artikel ini semampu Anda. Merapikan artikel dapat dilakukan dengan wikifikasi atau membagi artikel ke paragraf-paragraf. Jika sudah dirapikan, silakan hapus templat ini. (Pelajari cara dan kapan saatnya untuk menghapus pesan templat ini) Artikel ini membutuhkan rujukan tambahan agar kualitasnya dapat dipastikan. Mohon bantu kami mengembangkan artikel ini dengan cara menambahkan ruj...

 

The oldest part of Edinburgh Old Town, EdinburghUNESCO World Heritage SiteThe Old Town seen from Princes StreetLocationEdinburgh, Scotland, United KingdomPart ofOld and New Towns of EdinburghCriteriaCultural: (ii)(iv)Reference728Inscription1995 (19th Session)Coordinates55°56′51.26″N 3°11′29.87″W / 55.9475722°N 3.1916306°W / 55.9475722; -3.1916306Location of Old Town, Edinburgh in the City of Edinburgh council areaShow map of the City of Edinburgh counc...

Radio station in Batavia, New YorkWBTABatavia, New YorkBroadcast areaRochester areaFrequency1490 kHzBrandingWBTA FM 100.1 AM 1490ProgrammingFormatSoft adult contemporaryOwnershipOwnerJames Ernst(Majic Tones Communications, LLC)HistoryFirst air date1941Technical information[1]Licensing authorityFCCFacility ID31811ClassCPower1,000 watts day710 watts nightTransmitter coordinates42°58′35″N 78°11′12″W / 42.97639°N 78.18667°W / 42.97639; -78.18667Translat...

 

British Conservative Party MP Dame Edith PittDBE MPMember of Parliamentfor Birmingham EdgbastonIn office2 July 1953 – 27 January 1966(died in office)Preceded byPeter BennettSucceeded byJill Knight Personal detailsBornEdith Maud Pitt14 October 1906Birmingham, England, UKDied27 January 1966 (aged 59)Queen Elizabeth Hospital BirminghamPolitical partyConservativeResidence(s)Yardley, Birmingham, England, UK Dame Edith Maud Pitt, DBE (14 October 1906 – 27 January 1966) was a Britis...

 

Computing server located in a private residence This article needs additional citations for verification. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.Find sources: Home server – news · newspapers · books · scholar · JSTOR (January 2010) (Learn how and when to remove this message) A home server is a computing server located in a private computing residence providing services ...

1904 opera by Giacomo Puccini Madame Butterfly redirects here. For other uses, see Madame Butterfly (disambiguation). Madama ButterflyOpera by Giacomo PucciniOriginal 1904 poster by Adolfo HohensteinLibrettist Luigi Illica Giuseppe Giacosa LanguageItalianBased on David Belasco, Madame Butterfly: A Tragedy of Japan John Luther Long, Madame Butterfly Premiere17 February 1904 (1904-02-17)La Scala, Milan Madama Butterfly (Italian pronunciation: [maˈdaːma ˈbatterflai]; Ma...

 

Pour l’article ayant un titre homophone, voir Karashi. Karachi Héraldique Dans le sens des aiguilles d'une montre, de haut en bas, Vue de Karachi, bureaux administratifs de la Karachi Port Trust, la PRC Towers (à gauche) et un bâtiment de la PNSC (à droite), un vendeur de tissus, phare de la pointe Manora, l'échangeur Nagan Chowrangi, et le Mazar-e-Quaid. Administration Pays Pakistan Province Sind Division Karachi Maire Iftikhar Shallwani(administrateur) Code postal 74xxx – 75xxx D�...

 

Berkecet-biru jawa Myiomela diana Status konservasiRisiko rendahIUCN22710114 TaksonomiKelasAvesOrdoPasseriformesSuperfamiliMuscicapoideaFamiliMuscicapidaeGenusMyiomelaSpesiesMyiomela diana Lesson, 1834 Berkecet-biru jawa ( Myiomela diana ) adalah salah satu spesies burung dalam keluarga Muscicapidae . Ini endemik di pulau Jawa, Indonesia. Habitat aslinya adalah hutan pegunungan lembab subtropis atau tropis.Berkecet-biru sumatra ( Myiomela sumatrana ) sebelumnya dianggap sebagai subspesies M. ...

Action driven by intention which leads to future consequences For the use of this term in other Indian religions, see Karma. Translations ofkarmaEnglishkarmaSanskritकर्मन् (IAST: karman)Pali𑀓𑀫𑁆𑀫​ (kamma)Bengaliকর্ম (kôrmô)Burmeseကံ (MLCTS: kàɰ̃)Chinese業 or 业 (Pinyin: yè)Japanese業 or ごう (Rōmaji: gou)Khmerកម្ម(UNGEGN: kâmm; ALA-LC: kamm; IPA: [kam])Korean업 or 業 (RR: uhb)Sinhalaකර්ම (karma)Tibetanལས། (Wylie...

 

مد البصر معلومات عامة الاختصاص تصحيح البصر،  وطب العيون  من أنواع خطأ انكسار،  ومرض  التاريخ وصفها المصدر قاموس بروكهاوس وإفرون الموسوعي الصغير  [لغات أخرى]‏،  والموسوعة السوفيتية الأرمينية، المجلد السادس  [لغات أخرى]‏  تعديل مصدري - تعديل ...