"""与えられた文法からランダムな文を生成するモジュール。文法は S = 'NP VP | S and S' のような形式のエントリで構成される。各エントリは {'S': [['NP', 'VP'], ['S', 'and', 'S']]} のような形式に変換され、 これはそれぞれの外側の大きなリスト (top-level lists) からどれか ひとつの書き換え候補がランダムに選ばれることを示す。そして、選ばれた リストの内側にある各要素 (each element of the second-level list) が 書き換えられる。その要素が文法中になければ、各要素はそれ自身に書き 換えられる。関数 rewrite および rewrite_tree はそれぞれ単語のリストと、 結果が追加されるアキュムレータ (空リスト) を引数としてとるようになっている。 関数 generate および generate_tree は、rewrite と rewrite_tree への 簡便なインタフェイスを提供しており、これは文字列 (デフォルトは 'S') を 入力として受けとる。""" import random def make_grammar(**grammar): "シンボルから各書き換え候補へのマッピングをおこなう辞書を作成する。" for k in grammar.keys(): grammar[k] = [alt.strip().split() for alt in grammar[k].split('|')] return grammar grammar = make_grammar( S = 'NP VP', NP = 'Art N', VP = 'V NP', Art = 'the | a', N = 'man | ball | woman | table', V = 'hit | took | saw | liked' ) def rewrite(words, into): "リスト中の各単語を文法中のランダムなエントリで (再帰的に) 置き換える。" for word in words: if word in grammar: rewrite(random.choice(grammar[word]), into) else: into.append(word) return into def rewrite_tree(words, into): "単語のリストを、文法から選ばれたランダムな木で置き換える。" for word in words: if word in grammar: into.append({word: rewrite_tree(random.choice(grammar[word]), [])}) else: into.append(word) return into def generate(str='S'): "str に含まれている各単語を文法中のランダムなエントリで (再帰的に) 置き換える。" return ' '.join(rewrite(str.split(), [])) def generate_tree(cat='S'): "文法を使ってカテゴリ cat を書き換える。" return rewrite_tree([cat], [])