Source code for cfpq_data.grammars.converters.cnf

"""Create a context-free grammar in Chomsky normal form from different formats."""
import logging

from pyformlang.cfg import CFG, Epsilon
from pyformlang.regular_expression import Regex
from pyformlang.rsa import RecursiveAutomaton as RSA

from cfpq_data.grammars.converters.cfg import cfg_from_rsa, cfg_from_regex

__all__ = [
    "cnf_from_cfg",
    "cnf_from_regex",
    "cnf_from_rsa",
]


[docs] def cnf_from_cfg(cfg: CFG) -> CFG: """Create a context-free grammar in Chomsky normal form [1]_ from given context-free grammar [2]_. Parameters ---------- cfg : CFG Context-free grammar. Examples -------- >>> from cfpq_data import * >>> gr = cfg_from_text("S -> a b") >>> cnf = cfpq_data.cnf_from_cfg(gr) >>> cfg_to_text(cnf) 'S -> a#CNF# b#CNF#\\na#CNF# -> a\\nb#CNF# -> b' Returns ------- cnf : CFG Context-free grammar in Chomsky normal form. References ---------- .. [1] https://en.wikipedia.org/wiki/Chomsky_normal_form .. [2] https://en.wikipedia.org/wiki/Context-free_grammar#Formal_definitions """ epsilon_productions = set() for production in cfg.productions: if production.body in ([], [Epsilon]): epsilon_productions.add(production) cnf = cfg.to_normal_form() cnf = CFG( variables=cnf.variables, terminals=cnf.terminals, start_symbol=cnf.start_symbol, productions=cnf.productions | epsilon_productions, ) logging.info(f"Create {cnf=} from {cfg=}") return cnf
[docs] def cnf_from_regex(regex: Regex) -> CFG: """Create a context-free grammar in Chomsky normal form [1]_ from given regular expression [2]_. Parameters ---------- regex : Regex Regular expression. Examples -------- >>> from cfpq_data import * >>> expr = regex_from_text("a*") >>> cnf = cfpq_data.cnf_from_regex(expr) >>> cfg_to_text(cnf) 'S -> \\nS -> S S\\nS -> a' Returns ------- cnf : CFG Context-free grammar in Chomsky normal form. References ---------- .. [1] https://en.wikipedia.org/wiki/Chomsky_normal_form .. [2] https://en.wikipedia.org/wiki/Regular_expression#Formal_definition """ cnf = cnf_from_cfg(cfg_from_regex(regex)) logging.info(f"Create {cnf=} from {regex=}") return cnf
[docs] def cnf_from_rsa(rsa: RSA) -> CFG: """Create a context-free grammar in Chomsky normal form [1]_ from Recursive State Automaton [2]_. Parameters ---------- rsa : RSA Recursive State Automaton. Examples -------- >>> from cfpq_data import * >>> gr = rsa_from_text("S -> a*") >>> cnf = cnf_from_rsa(gr) >>> cfg_to_text(cnf) 'S -> \\nS -> a\\nS -> a#CNF# S\\na#CNF# -> a' Returns ------- cnf : CFG Context-free grammar in Chomsky normal form. References ---------- .. [1] https://en.wikipedia.org/wiki/Chomsky_normal_form .. [2] Alur R., Etessami K., Yannakakis M. (2001) Analysis of Recursive State Machines. In: Berry G., Comon H., Finkel A. (eds) Computer Aided Verification. CAV 2001. Lecture Notes in Computer Science, vol 2102. Springer, Berlin, Heidelberg. https://doi.org/10.1007/3-540-44585-4_18 """ cnf = cnf_from_cfg(cfg_from_rsa(rsa=rsa)) logging.info(f"Create {cnf=} from {rsa=}") return cnf