Commit 6d1bb3e2 authored by Kateřina Sloupová's avatar Kateřina Sloupová
Browse files

bug in counterexample searching fixed

parent 6692d464
Loading
Loading
Loading
Loading
Loading
+10 −14
Original line number Original line Diff line number Diff line
@@ -392,27 +392,23 @@ class DFA:
        for state in succ:
        for state in succ:
            succ[state] = succ[state].intersection(terminable)
            succ[state] = succ[state].intersection(terminable)


        # for state in completed:
        #     print(state.name, ": ")
        #     print(','.join(set(map(lambda x: x.name, pred[state]))),
        #     ','.join(set(map(lambda x: x.name, succ[state]))))
        # print()
        # terminable = self.terminating_states(completed, pred)
        #print(','.join(set(map(lambda x: x.name, completed))))
        #print(','.join(set(map(lambda x: x.name, terminable))))
        #print(','.join(set(map(lambda x: x.name, on_cycle))))

        if self.init in self.final:
        if self.init in self.final:
            return IsEmptyResult('ε', len(on_cycle.intersection(terminable)) > 0)
            return IsEmptyResult('ε', len(on_cycle.intersection(terminable)) > 0)


        word: str = []
        word: List[str] = []
        state: State = self.init
        state: State = self.init
        used: Set[State] = set()
        used: Set[State] = {self.init}

        while state not in self.final:
        while state not in self.final:
            unused = succ[state].difference(used)
            unused = succ[state].difference(used)
            new = self.one_of(unused) if len(unused) > 0 else self.one_of(succ[state])
            if len(unused) > 0:
                new = self.one_of(unused)
            else:
                used = used.difference(succ[state])
                new = self.one_of(succ[state])

            word.append(self.get_character(state, new).name)
            word.append(self.get_character(state, new).name)
            used.add(state)
            used.add(new)
            state = new
            state = new


        if len(on_cycle.intersection(terminable)) > 0:
        if len(on_cycle.intersection(terminable)) > 0:
+39 −36
Original line number Original line Diff line number Diff line
@@ -14,69 +14,72 @@
  <!--[if lt IE 9]>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
  <![endif]-->
  <style>code { background-color: #ddd; padding: 0.2em; }</style>
</head>
</head>
<body>
<body>
<h1 id="zadávání-formalismů-pro-popis-regulárních-jazyků">Zadávání formalismů pro popis regulárních jazyků</h1>
<header id="title-block-header">
<h1 class="title">Zadávání formalismů pro popis regulárních jazyků</h1>
</header>
<h2 id="konečné-automaty-dfa-nfa-nfa-s-ε-kroky">Konečné automaty (DFA, NFA, NFA s ε-kroky)</h2>
<h2 id="konečné-automaty-dfa-nfa-nfa-s-ε-kroky">Konečné automaty (DFA, NFA, NFA s ε-kroky)</h2>
<p>Pro popis konečného automatu je třeba zapsat iniciální stav, přechodovou funkci a množinu koncových stavů.</p>
<p>Pro popis konečného automatu je třeba zapsat iniciální stav, přechodovou funkci a množinu koncových stavů.</p>
<p>Počáteční stav lze explicitně definovat jako <code>init=stav</code> na počátku zápisu automatu. Není-li počáteční stav takto specifikován, pak je jako počáteční stav vyhodnocen ten, který se jako první objeví v přechodové funkci.</p>
<p>Počáteční stav lze explicitně definovat jako <code>init=stav</code> na počátku zápisu automatu. Není-li počáteční stav takto specifikován, pak je jako počáteční stav vyhodnocen ten, který se jako první objeví v přechodové funkci.</p>
<p>Přechodová funkce sestává z pravidel ve tvaru:
<p>Přechodová funkce sestává z pravidel ve tvaru:</p>
<ul>
<ul>
<li><code>(vstupní_stav,znak)=výstupní_stav</code> pro deterministické automaty,</li>
<li><code>(vstupní_stav,znak)=výstupní_stav</code> pro deterministické automaty,</li>
<li><code>(vstupní_stav,znak)={výstupní_stav1,výstupní_stav2, ..., výstupní_stavN}</code> pro nedeterministické automaty.</li>
<li><code>(vstupní_stav,znak)={výstupní_stav1,výstupní_stav2, ..., výstupní_stavN}</code> pro nedeterministické automaty.</li>
</ul></p>
</ul>
<p>V nedeterminstických automatech s ε-kroky lze místo znaku v přechodové funkci zapsat přechod pod prázdným slovem pomocí znaku <code>ε</code> nebo <code>\e</code>. Pokud se pro stejnou dvojici <code>(vstupní_stav,znak)</code> objeví v přechodové funkci více přechodů, vyhodnocovací služba upozorní na možný problém.</p>
<p>V nedeterminstických automatech s ε-kroky lze místo znaku v přechodové funkci zapsat přechod pod prázdným slovem pomocí znaku <code>ε</code> nebo <code>\e</code>. Pokud se pro stejnou dvojici <code>(vstupní_stav,znak)</code> objeví v přechodové funkci více přechodů, vyhodnocovací služba upozorní na možný problém.</p>
<p>Zápis množiny koncových stavů je <code>final={koncový_stav1,koncový_stav2, ..., koncový_stavN}</code>, je na samém konci zápisu a nelze jej vynechat.</p>
<p>Zápis množiny koncových stavů je <code>final={koncový_stav1,koncový_stav2, ..., koncový_stavN}</code>, je na samém konci zápisu a nelze jej vynechat.</p>
<p>Validní automat musí obsahovat alespoň jeden stav.</p>
<p>Validní automat musí obsahovat alespoň jeden stav.</p>
<p>V názvech stavů a znaků lze použít malá i velká písmena anglické abecedy, číslice a znaky <code>_</code> (!). Lze tvořit i víceznakové sekvence jako názvy stavů. Bílé znaky (mezera, tab, konec řádku) nemají na vyhodnocení automatu vliv.</p>
<p>V názvech stavů a znaků lze použít malá i velká písmena anglické abecedy, číslice <code>0-9</code> a znaky <code>_</code> a <code>'</code>. Lze tvořit i víceznakové sekvence jako názvy stavů. Bílé znaky (mezera, tab, konec řádku) nemají na vyhodnocení automatu vliv.</p>
<h3 id="příklady">Příklady:</h3>
<h3 id="příklady">Příklady:</h3>
<ul>
<ul>
<li><code>init=0 (0,a)=1 (0,b)=1 final={0,1}</code></li>
<li><code>init=0 (0,a)=1 (0,b)=1 final={0,1}</code> (DFA s počátečním stavem <code>0</code>)</li>
<li><code>(q_0, a) = q_1 (q_0, b) = q_1 (q_1, a) = q_1 final = {q_1} (počáteční stav bude q_0)</code></li>
<li><code>(q_0, a) = q_1 (q_0, b) = q_1 (q_1, a) = q_1 final = {q_1}</code> (DFA s počátečním stavem <code>q_0</code>)</li>
<li><code>init=init (init,a)={fst,snd} (fst,b)={snd} (snd,b)={fst} final={fst,snd}</code></li>
<li><code>init=init (init,a)={fst,snd} (fst,b)={snd} (snd,b)={fst} final={fst,snd}</code></li>
<li><code>(0,ε)={1} final={}</code></li>
<li><code>(0,ε)={1} final={}</code> (NFA s epsilon kroky, počátečním stavem <code>init</code> a žádnými koncovými stavy)</li>
</ul>
</ul>
<h2 id="regulární-výrazy">Regulární výrazy</h2>
<h2 id="regulární-výrazy">Regulární výrazy</h2>
<p>Základní regulární výrazy jsou znak, prázdné slovo a prázdný jazyk:
<p>Základní regulární výrazy jsou znak, prázdné slovo a prázdný jazyk:</p>
<ul>
<ul>
<li>jako znaky lze použít malá i velká písmena anglické abecedy a čísla;</li>
<li>jako znaky lze použít malá i velká písmena anglické abecedy a číslice <code>0-9</code>,</li>
<li>prázdné slovo (epsilon) se značí jako <code>\e</code> nebo <code>ε</code>;</li>
<li>prázdné slovo (epsilon) se značí jako <code>\e</code> nebo <code>ε</code>,</li>
<li>prázdný jazyk je možné zapsat jako <code>\0</code> nebo <code></code>.</li>
<li>prázdný jazyk je možné zapsat jako <code>\0</code> nebo <code></code>.</li>
</ul></p>
</ul>
<p>Další regulární výrazy vznikají použitím operací iterace, zřetězení a sjednocení:
<p>Další regulární výrazy vznikají použitím operací iterace, zřetězení a sjednocení:</p>
<ul>
<ul>
<li>regulární výraz je možné iterovat operátory <code>^*</code> (iterace) a <code>^+</code> (pozitivní iterace), jako iterovaný se vyhodnotí nejbližší znak nebo regulární výraz v nejbližší závorce (nejblíže operátoru zleva);</li>
<li>regulární výraz je možné iterovat operátory <code>^*</code> (iterace) a <code>^+</code> (pozitivní iterace), jako iterovaný se vyhodnotí nejbližší znak nebo regulární výraz v nejbližší závorce (nejblíže operátoru zleva),</li>
<li>každé dva regulární výrazy lze zřetězit operátorem <code>.</code>;</li>
<li>každé dva regulární výrazy lze zřetězit operátorem <code>.</code>,</li>
<li>sjednocení dvou regulárních výrazů lze zapsat pomocí operátoru <code>+</code>.</li>
<li>operaci <code>+</code>, která sémanticky odpovídá sjednocení dvou regulárních výrazů, lze zapsat pomocí operátoru <code>+</code>.</li>
</ul></p>
</ul>
<p>Operace jsou seřazeny podle priority od nejvyšší po nejnižší, nejdříve se tedy budou vyhodnocovat iterace, po nich zřetězení a s nejnižší prioritou sjednocení. Regulární výrazy je možné uzavírat do jednoduchých závorek ( <code>(</code> a <code>)</code> ), mezery jsou ignorovány. Implicitní zřetězení (bez explicitního zápisu pomocí tečky) funguje pro sekvence znaků, iterovaných regulárních výrazů a regulárních výrazů v závorkách. Znak je tvořen vždy jen jedním písmenem, více znaků následujících za sebou se vyhodnotí jako jejich implicitní zřetězení (<code>ab</code> je ekvivalentní <code>a.b</code>).</p>
<p>Operace jsou seřazeny podle priority od nejvyšší po nejnižší, nejdříve se tedy budou vyhodnocovat iterace, po nich zřetězení a s nejnižší prioritou operace <code>+</code>. Regulární výrazy je možné uzavírat do jednoduchých závorek ( <code>(</code> a <code>)</code> ), mezery jsou ignorovány. Implicitní zřetězení (bez explicitního zápisu pomocí tečky) funguje pro sekvence znaků, iterovaných regulárních výrazů a regulárních výrazů v závorkách. Znak je tvořen vždy jen jedním písmenem, více znaků následujících za sebou se vyhodnotí jako jejich implicitní zřetězení (<code>ab</code> je ekvivalentní <code>a.b</code>).</p>
<h3 id="příklady-1">Příklady:</h3>
<h3 id="příklady-1">Příklady:</h3>
<ul>
<ul>
<li><code>ab^*</code> se vyhodnotí jako <code>a.((b)^*)</code></li>
<li><code>ab^*</code> je ekvivalentní s <code>a.((b)^*)</code></li>
<li><code>a(bc)^*d</code> se vyhodnotí jako <code>a.(b.c)^*.d</code></li>
<li><code>a(bc)^*d</code> je ekvivalentní s <code>a.(b.c)^*.d</code></li>
<li><code>(a + b + c^*) + \e</code> se vyhodnotí jako <code>a + b + (c)^* + ε</code></li>
<li><code>(a + b + c^*) + \e</code> je ekvivalentní s <code>a + b + (c)^* + ε</code></li>
</ul>
</ul>
<h2 id="regulární-gramatiky">Regulární gramatiky</h2>
<h2 id="regulární-gramatiky">Regulární gramatiky</h2>
<p>Z gramatiky stačí definovat množinu pravidel ve tvaru <code>S -&gt; aS | a</code>, kde <code>S</code> je neterminál a <code>a</code> je terminál. Více možných přepisů pro stejný neterminál lze zapsat jako více pravidel nebo také pomocí oddělovače <code>|</code>. Jednotlivá pravidla pro každý neterminál je třeba oddělit středníkem nebo koncem řádku. Jako šipku lze psát <code>-&gt;</code> i unicodový znak <code></code>.</p>
<p>Z gramatiky stačí definovat množinu pravidel, iniciálním neterminálem je první vyskytující se neterminál. Pravidla regulární gramatiky mohou být tvaru:</p>
<p>Neterminál je tvořen (hovoříme o písmenech anglické abecedy):
<ul>
<ul>
<li>jedním velkým písmenem (např. <code>S</code>, <code>A</code>),</li>
<li><code>Neterminál -&gt; TerminálNeterminál</code> (např. <code>A -&gt; aA</code>),</li>
<li>jedním malým nebo velkým písmenem s jedním nebo více apostrofy (např. <code>S'</code>, <code>a''</code>),</li>
<li><code>Neterminál -&gt; Terminál</code> (např. <code>B -&gt; b</code>),</li>
<li>sekvencí malých a velkých písmen, čísel nebo znaku <code>_</code> uzavřenou do lomených závorek <code>&lt;&gt;</code> (např. <code>&lt;abAB&gt;</code>, <code>&lt;S_0&gt;</code>).</li>
<li><code>Neterminál -&gt; ε</code> (např. <code>S -&gt; ε</code>),</li>
</ul></p>
</ul>
<p>Terminálem může být jedno malé písmeno anglické abecedy nebo číslo <code>0-9</code>.</p>
<p>Pokud regulární gramatika generuje prázdné slovo (ε), pak lze v pravidle použít symbol <code>ε</code> nebo <code>\e</code> (ovšem pouze u iniciálního neterminálu, který se v tomto případě nesmí objevit v pravé straně žádného z pravidel). Pravidla pro různé neterminály je třeba oddělit středníkem nebo koncem řádku. Jako šipku lze psát <code>-&gt;</code> i unicodový znak <code></code>. Více přepisovacích pravidel se stejnou levou stranou lze zapsat také pomocí oddělovače <code>|</code> (např. <code>A -&gt; aA | b</code>).</p>
<p>Regulární gramatika může také generovat prázdné slovo, pak lze v pravidle použít symbol <code>ε</code> nebo <code>\e</code> (ovšem pouze u iniciálního neterminálu, který se v tomto případě nesmí objevit v pravé straně žádného z pravidel).</p>
<p>Neterminál je tvořen (hovoříme o písmenech anglické abecedy):</p>
<h3 id="příklady-2">Příklady</h3>
<ul>
<ul>
<li><code>S -&gt; aS | aA | a; A -&gt; bA | aS</code></li>
<li>jedním velkým písmenem anglické abecedy (např. <code>S</code>, <code>A</code>),</li>
<li><code>A -&gt; aB</code> <br> <code>A -&gt; bA</code> <br> <code>B -&gt; aB</code> <br> <code>B -&gt; a</code></li>
<li>jedním malým nebo velkým písmenem anglické abecedy s jedním nebo více apostrofy (např. <code>S'</code>, <code>a''</code>),</li>
<li><code>&lt;init&gt; -&gt; a&lt;00X&gt; | a&lt;ab&gt; | ε; &lt;ab&gt; -&gt; b</code></li>
<li>sekvencí malých a velkých písmen anglické abecedy, číslic nebo znaku <code>_</code> uzavřenou do lomených závorek <code>&lt;&gt;</code> (např. <code>&lt;abAB&gt;</code>, <code>&lt;S_0&gt;</code>).</li>
</ul>
</ul>
<h2 id="bezkontextové-gramatiky">Bezkontextové gramatiky</h2>
<p>Terminálem může být jedno malé písmeno anglické abecedy nebo číslice <code>0-9</code>.</p>
<p>Pro zápis CFG platí všechna pravidla jako pro regulární gramatiky kromě omezení tvaru pravidel. Pravé strany pravidel nemusí být jen typu samotný terminál nebo dvojice terminál a neterminál, ale mohou obsahovat terminály i neterminály v libovolné kombinaci.</p>
<p>Regulární gramatika může také generovat prázdné slovo, pak lze v pravidle použít symbol <code>ε</code> nebo <code>\e</code> (ovšem pouze u iniciálního neterminálu, který se v tomto případě nesmí objevit v pravé straně žádného z pravidel).</p>
<h3 id="příklad">Příklad</h3>
<h3 id="příklady-2">Příklady</h3>
<ul>
<ul>
<li><code>S -&gt; aAa | bBb | ε; A -&gt; aAa | bab | bbb; B-&gt; bBaBb | A | a</code></li>
<li><code>S -&gt; aS | aA | a; A -&gt; bA | aS</code> <br></br></li>
<li><code>A -&gt; aB</code> <br></br> <code>A -&gt; bA</code> <br></br> <code>B -&gt; aB</code> <br></br> <code>B -&gt; a</code> <br></br></li>
<li><code>&lt;init&gt; -&gt; a&lt;00X&gt; | a&lt;ab&gt; | ε</code> <br></br> <code>&lt;ab&gt; -&gt; b</code></li>
</ul>
</ul>
</body>
</body>
</html>
</html>
+36 −27
Original line number Original line Diff line number Diff line
# Zadávání formalismů pro popis regulárních jazyků
---
header-includes: "<style>code { background-color: #ddd; padding: 0.2em; }</style>"
title: Zadávání formalismů pro popis regulárních jazyků
---



## Konečné automaty (DFA, NFA, NFA s ε-kroky)
## Konečné automaty (DFA, NFA, NFA s ε-kroky)


@@ -7,6 +11,7 @@ Pro popis konečného automatu je třeba zapsat iniciální stav, přechodovou f
Počáteční stav lze explicitně definovat jako `init=stav` na počátku zápisu automatu. Není-li počáteční stav takto specifikován, pak je jako počáteční stav vyhodnocen ten, který se jako první objeví v přechodové funkci.
Počáteční stav lze explicitně definovat jako `init=stav` na počátku zápisu automatu. Není-li počáteční stav takto specifikován, pak je jako počáteční stav vyhodnocen ten, který se jako první objeví v přechodové funkci.


Přechodová funkce sestává z pravidel ve tvaru:
Přechodová funkce sestává z pravidel ve tvaru:

* `(vstupní_stav,znak)=výstupní_stav` pro deterministické automaty,
* `(vstupní_stav,znak)=výstupní_stav` pro deterministické automaty,
* `(vstupní_stav,znak)={výstupní_stav1,výstupní_stav2, ..., výstupní_stavN}` pro nedeterministické automaty.
* `(vstupní_stav,znak)={výstupní_stav1,výstupní_stav2, ..., výstupní_stavN}` pro nedeterministické automaty.


@@ -16,56 +21,60 @@ Zápis množiny koncových stavů je `final={koncový_stav1,koncový_stav2, ...,


Validní automat musí obsahovat alespoň jeden stav.
Validní automat musí obsahovat alespoň jeden stav.


V názvech stavů a znaků lze použít malá i velká písmena anglické abecedy, číslice a znaky `_` (!). Lze tvořit i víceznakové sekvence jako názvy stavů. Bílé znaky (mezera, tab, konec řádku) nemají na vyhodnocení automatu vliv.
V názvech stavů a znaků lze použít malá i velká písmena anglické abecedy, číslice `0-9` a znaky `_` a `'`. Lze tvořit i víceznakové sekvence jako názvy stavů. Bílé znaky (mezera, tab, konec řádku) nemají na vyhodnocení automatu vliv.


### Příklady:
### Příklady:
* `init=0 (0,a)=1 (0,b)=1 final={0,1}`
* `init=0 (0,a)=1 (0,b)=1 final={0,1}` (DFA s počátečním stavem `0`)
* `(q_0, a) = q_1 (q_0, b) = q_1 (q_1, a) = q_1 final = {q_1} (počáteční stav bude q_0)`
* `(q_0, a) = q_1 (q_0, b) = q_1 (q_1, a) = q_1 final = {q_1}` (DFA s počátečním stavem `q_0`)
* `init=init (init,a)={fst,snd} (fst,b)={snd} (snd,b)={fst} final={fst,snd}`
* `init=init (init,a)={fst,snd} (fst,b)={snd} (snd,b)={fst} final={fst,snd}`
* `(0,ε)={1} final={}`
* `(0,ε)={1} final={}` (NFA s epsilon kroky, počátečním stavem `init` a žádnými koncovými stavy)


## Regulární výrazy
## Regulární výrazy


Základní regulární výrazy jsou znak, prázdné slovo a prázdný jazyk:
Základní regulární výrazy jsou znak, prázdné slovo a prázdný jazyk:
* jako znaky lze použít malá i velká písmena anglické abecedy a čísla;

* prázdné slovo (epsilon) se značí jako `\e` nebo `ε`;
* jako znaky lze použít malá i velká písmena anglické abecedy a číslice `0-9`,
* prázdné slovo (epsilon) se značí jako `\e` nebo `ε`,
* prázdný jazyk je možné zapsat jako `\0` nebo `∅`.
* prázdný jazyk je možné zapsat jako `\0` nebo `∅`.


Další regulární výrazy vznikají použitím operací iterace, zřetězení a sjednocení:
Další regulární výrazy vznikají použitím operací iterace, zřetězení a sjednocení:
* regulární výraz je možné iterovat operátory `^*` (iterace) a `^+` (pozitivní iterace), jako iterovaný se vyhodnotí nejbližší znak nebo regulární výraz v nejbližší závorce (nejblíže operátoru zleva);
* každé dva regulární výrazy lze zřetězit operátorem `.`;
* sjednocení dvou regulárních výrazů lze zapsat pomocí operátoru `+`.


Operace jsou seřazeny podle priority od nejvyšší po nejnižší, nejdříve se tedy budou vyhodnocovat iterace, po nich zřetězení a s nejnižší prioritou sjednocení. Regulární výrazy je možné uzavírat do jednoduchých závorek ( `(` a `)` ), mezery jsou ignorovány. Implicitní zřetězení (bez explicitního zápisu pomocí tečky) funguje pro sekvence znaků, iterovaných regulárních výrazů a regulárních výrazů v závorkách. Znak je tvořen vždy jen jedním písmenem, více znaků následujících za sebou se vyhodnotí jako jejich implicitní zřetězení (`ab` je ekvivalentní `a.b`).
* regulární výraz je možné iterovat operátory `^*` (iterace) a `^+` (pozitivní iterace), jako iterovaný se vyhodnotí nejbližší znak nebo regulární výraz v nejbližší závorce (nejblíže operátoru zleva),
* každé dva regulární výrazy lze zřetězit operátorem `.`,
* operaci `+`, která sémanticky odpovídá sjednocení dvou regulárních výrazů, lze zapsat pomocí operátoru `+`.

Operace jsou seřazeny podle priority od nejvyšší po nejnižší, nejdříve se tedy budou vyhodnocovat iterace, po nich zřetězení a s nejnižší prioritou operace `+`. Regulární výrazy je možné uzavírat do jednoduchých závorek ( `(` a `)` ), mezery jsou ignorovány. Implicitní zřetězení (bez explicitního zápisu pomocí tečky) funguje pro sekvence znaků, iterovaných regulárních výrazů a regulárních výrazů v závorkách. Znak je tvořen vždy jen jedním písmenem, více znaků následujících za sebou se vyhodnotí jako jejich implicitní zřetězení (`ab` je ekvivalentní `a.b`).


### Příklady:
### Příklady:
* `ab^*` se vyhodnotí jako `a.((b)^*)`
* `ab^*` je ekvivalentní s `a.((b)^*)`
* `a(bc)^*d` se vyhodnotí jako `a.(b.c)^*.d`
* `a(bc)^*d` je ekvivalentní s `a.(b.c)^*.d`
* `(a + b + c^*) + \e` se vyhodnotí jako `a + b + (c)^* + ε`
* `(a + b + c^*) + \e` je ekvivalentní s `a + b + (c)^* + ε`






## Regulární gramatiky
## Regulární gramatiky


Z gramatiky stačí definovat množinu pravidel ve tvaru `S -> aS | a`, kde `S` je neterminál a `a` je terminál. Více možných přepisů pro stejný neterminál lze zapsat jako více pravidel nebo také pomocí oddělovače `|`. Jednotlivá pravidla pro každý neterminál je třeba oddělit středníkem nebo koncem řádku. Jako šipku lze psát `->` i unicodový znak `→`.
Z gramatiky stačí definovat množinu pravidel, iniciálním neterminálem je první vyskytující se neterminál. Pravidla regulární gramatiky mohou být tvaru:

* `Neterminál -> TerminálNeterminál` (např. `A -> aA`),
* `Neterminál -> Terminál` (např. `B -> b`),
* `Neterminál -> ε` (např. `S -> ε`),

Pokud regulární gramatika generuje prázdné slovo (ε), pak lze v pravidle použít symbol `ε` nebo `\e` (ovšem pouze u iniciálního neterminálu, který se v tomto případě nesmí objevit v pravé straně žádného z pravidel). Pravidla pro různé neterminály je třeba oddělit středníkem nebo koncem řádku. Jako šipku lze psát `->` i unicodový znak `→`. Více přepisovacích pravidel se stejnou levou stranou lze zapsat také pomocí oddělovače `|` (např. `A -> aA | b`). 


Neterminál je tvořen (hovoříme o písmenech anglické abecedy):
Neterminál je tvořen (hovoříme o písmenech anglické abecedy):
* jedním velkým písmenem (např. `S`, `A`),
* jedním malým nebo velkým písmenem s jedním nebo více apostrofy (např. `S'`, `a''`),
* sekvencí malých a velkých písmen, čísel nebo znaku `_` uzavřenou do lomených závorek `<>` (např. `<abAB>`, `<S_0>`).


Terminálem může být jedno malé písmeno anglické abecedy nebo číslo `0-9`.
* jedním velkým písmenem anglické abecedy (např. `S`, `A`),
* jedním malým nebo velkým písmenem anglické abecedy s jedním nebo více apostrofy (např. `S'`, `a''`),
* sekvencí malých a velkých písmen anglické abecedy, číslic nebo znaku `_` uzavřenou do lomených závorek `<>` (např. `<abAB>`, `<S_0>`).

Terminálem může být jedno malé písmeno anglické abecedy nebo číslice `0-9`.


Regulární gramatika může také generovat prázdné slovo, pak lze v pravidle použít symbol `ε` nebo `\e` (ovšem pouze u iniciálního neterminálu, který se v tomto případě nesmí objevit v pravé straně žádného z pravidel).
Regulární gramatika může také generovat prázdné slovo, pak lze v pravidle použít symbol `ε` nebo `\e` (ovšem pouze u iniciálního neterminálu, který se v tomto případě nesmí objevit v pravé straně žádného z pravidel).


### Příklady
### Příklady
* `S -> aS | aA | a; A -> bA | aS`
* `S -> aS | aA | a; A -> bA | aS` <br></br>
* `A -> aB` <br> `A -> bA` <br> `B -> aB` <br> `B -> a`
* `A -> aB` <br></br> `A -> bA` <br></br> `B -> aB` <br></br> `B -> a` <br></br>
* `<init> -> a<00X> | a<ab> | ε; <ab> -> b`
* `<init> -> a<00X> | a<ab> | ε` <br></br> `<ab> -> b`

## Bezkontextové gramatiky


Pro zápis CFG platí všechna pravidla jako pro regulární gramatiky kromě omezení tvaru pravidel. Pravé strany pravidel nemusí být jen typu samotný terminál nebo dvojice terminál a neterminál, ale mohou obsahovat terminály i neterminály v libovolné kombinaci.
### Příklad
* `S -> aAa | bBb | ε; A -> aAa | bab | bbb; B-> bBaBb | A | a`
+1 −0
Original line number Original line Diff line number Diff line
init=A (A,a)=B (A,b)=A (A,c)=A (B,b)=C (B,c)=F (C,c)=D (C,b)=J (F,b)=G (F,c)=H (D,a)=B (D,b)=J (D,c)=E (J,b)=J (J,c)=J (E,c)=D (E,b)=J (G,a)=B (G,b)=J (G,c)=I (H,c)=F (H,b)=J (I,c)=G (I,b)=J final={A,B,C,F,D,J,E,G,H,I}
+1 −0
Original line number Original line Diff line number Diff line
DFA-DFA:(A,a)=B(A,b)=A(A,c)=A(B,a)=C(B,b)=D(B,c)=E(C,a)=C(C,b)=C(C,c)=C(D,a)=C(D,b)=F(D,c)=G(E,a)=C(E,b)=G(E,c)=B(F,a)=C(F,b)=F(F,c)=F(G,a)=B(G,b)=F(G,c)=D final={A,B,D,E,F,G}