Source code for cfpq_data.grammars.readwrite.cfg

"""Read (and write) a context-free grammar from (and to) different sources."""
import logging
import pathlib
from typing import Union

from pyformlang.cfg import Variable, CFG

__all__ = [
    "cfg_from_text",
    "cfg_to_text",
    "cfg_from_txt",
    "cfg_to_txt",
]


[docs] def cfg_from_text(text: str, *, start_symbol: Variable = Variable("S")) -> CFG: """Create a context-free grammar [1]_ from text. Parameters ---------- text : str The text with which the context-free grammar will be created. start_symbol : Variable Start symbol of a context-free grammar. Examples -------- >>> from cfpq_data import * >>> cfg = cfg_from_text("S -> a S b S") >>> cfg_to_text(cfg) 'S -> a S b S' Returns ------- cfg : CFG Context-free grammar. References ---------- .. [1] https://en.wikipedia.org/wiki/Context-free_grammar#Formal_definitions """ cfg = CFG.from_text(text=text, start_symbol=start_symbol) logging.info(f"Create {cfg=} from {text=}, {start_symbol=}") return cfg
[docs] def cfg_to_text(cfg: CFG) -> str: """Turns a context-free grammar [1]_ into its text representation. Parameters ---------- cfg : CFG Context-free grammar. Examples -------- >>> from cfpq_data import * >>> cfg = cfg_from_text("S -> a S b S | epsilon") >>> cfg_to_text(cfg) 'S -> \\nS -> a S b S' Returns ------- text : str Context-free grammar text representation. References ---------- .. [1] https://en.wikipedia.org/wiki/Context-free_grammar#Formal_definitions """ productions = [ f"{p.head.value} -> " + " ".join(map(lambda x: x.value, p.body)) for p in cfg.productions ] productions.sort( key=lambda s: (s.split(" -> ")[0] != cfg.start_symbol.value, s), ) text = "\n".join(productions) logging.info(f"Turn {cfg=} into {text=}") return text
[docs] def cfg_from_txt( path: Union[pathlib.Path, str], *, start_symbol: Variable = Variable("S") ) -> CFG: """Create a context-free grammar [1]_ from TXT file. Parameters ---------- path : Union[Path, str] The path to the TXT file with which the context-free grammar will be created. start_symbol : Variable Start symbol of a context-free grammar. Examples -------- >>> from cfpq_data import * >>> cfg_1 = cfg_from_text("S -> a S b S | epsilon") >>> path = cfg_to_txt(cfg_1, "test.txt") >>> cfg = cfg_from_txt(path) >>> cfg_to_text(cfg) 'S -> \\nS -> a S b S' Returns ------- cfg : CFG Context-free grammar. References ---------- .. [1] https://en.wikipedia.org/wiki/Context-free_grammar#Formal_definitions """ with open(path, "r") as f: productions = f.read() cfg = cfg_from_text(productions, start_symbol=start_symbol) logging.info(f"Create {cfg=} from {path=}, {start_symbol=}") return cfg
[docs] def cfg_to_txt(cfg: CFG, path: Union[pathlib.Path, str]) -> pathlib.Path: """Saves a context-free grammar [1]_ text representation into TXT file. Parameters ---------- cfg : CFG Context-free grammar. path : Union[Path, str] The path to the TXT file where context-free grammar text representation will be saved. Examples -------- >>> from cfpq_data import * >>> cfg = cfg_from_text("S -> a S b S") >>> path = cfg_to_txt(cfg, "test.txt") Returns ------- path : Path The path to the TXT file where context-free grammar text representation will be saved. References ---------- .. [1] https://en.wikipedia.org/wiki/Context-free_grammar#Formal_definitions """ with open(path, "w") as f: f.write(cfg_to_text(cfg)) dest = pathlib.Path(path).resolve() logging.info(f"Save {cfg=} to {dest=}") return dest