import Mathlib.Computability.Language import Mathlib.Logic.Relation /-! # Unrestricted Grammar Definitions This file defines unrestricted grammars and their derivations. ## Main declarations - `symbol` - `grammar` - `grammar_derives` - `grammar_language` -/ open Relation /-- The type of symbols is the disjoint union of terminals and nonterminals. -/ inductive symbol (T : Type) (N : Type) where | terminal : T → symbol T N | nonterminal : N → symbol T N deriving DecidableEq /-- Transformation rule for a grammar without any restrictions. -/ structure grule (T : Type) (N : Type) where input_L : List (symbol T N) input_N : N input_R : List (symbol T N) output_string : List (symbol T N) /-- Grammar (unrestricted) that generates words over the alphabet `T` (a type of terminals). -/ structure grammar (T : Type) where nt : Type -- type of nonterminals initial : nt -- initial symbol rules : List (grule T nt) -- rewrite rules variable {T : Type} /-- One step of grammatical transformation. -/ def grammar_transforms (g : grammar T) (w₁ w₂ : List (symbol T g.nt)) : Prop := ∃ r : grule T g.nt, r ∈ g.rules ∧ ∃ u v : List (symbol T g.nt), (w₁ = u ++ r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R ++ v) ∧ (w₂ = u ++ r.output_string ++ v) /-- Any number of steps of grammatical transformation; reflexive+transitive closure of `grammar_transforms`. -/ def grammar_derives (g : grammar T) : List (symbol T g.nt) → List (symbol T g.nt) → Prop := Relation.ReflTransGen (grammar_transforms g) /-- Accepts a word (a list of terminals) iff it can be derived from the initial nonterminal. -/ def grammar_generates (g : grammar T) (w : List T) : Prop := grammar_derives g [symbol.nonterminal g.initial] (List.map symbol.terminal w) /-- The set of words that can be derived from the initial nonterminal. -/ def grammar_language (g : grammar T) : Language T := setOf (grammar_generates g)