def test_repeated_productions_are_shrunk(self): """ If two or more productions has the same alpha, they're shrunk. This implies that if two or more productions has the same alpha, they're transformed in a single production with all the beta parts of the productions separated by Or's. """ start_symbol = 'expr' productions = [ grammar.Production( 'expr', grammar.SingleTerm(str(i)) ) for i in range(10) ] a_grammar = grammar.Grammar(start_symbol, productions) # The ten productions are transformed in One self.assertEquals(len(a_grammar.productions), 1) # The only term of the productions is an Or instance production = a_grammar.productions[0] self.assertEquals(start_symbol, production.variable) self.assertIsInstance(production.term, grammar.Or) # The Or term contains all the terms in initial productions. value = production.term.value for t in value: self.assertIn(t, [p.term for p in productions]) for t in [p.term for p in productions]: self.assertIn(t, value)
def test_start_symbol_should_exists_as_variable_in_productions(self): """ The start symbol must lead at least one of the productions. """ existent_start_symbol = 'existent' non_existent_start_symbol = 'non_existent' productions = [ grammar.Production( existent_start_symbol, grammar.EpsilonTerminal ) for _ in range(4) ] # Test OK if start_symbol exists. grammar.Grammar( start_symbol=existent_start_symbol, productions=productions ) # Test KO if start_symbol_does_not_exists with self.assertRaises(ValueError): grammar.Grammar( start_symbol=non_existent_start_symbol, productions=productions )
def test_correct_construction(self): """ Correct start_symbol and productions lead to a correct grammar. """ base_symbol = 't' start_symbol = base_symbol + '0' productions = [ grammar.Production( base_symbol + str(i), grammar.EpsilonTerminal ) for i in range(4) ] a_grammar = grammar.Grammar( start_symbol=start_symbol, productions=productions ) self.assertEquals(start_symbol, a_grammar.start_symbol) for production in productions: self.assertIn(production, a_grammar.productions) for production in a_grammar.productions: self.assertIn(production, productions)
def test_productions_should_be_an_list_of_production_instances(self): """ Productions should be a list of Production instances. """ all_but_one = [ grammar.Production( 't', grammar.EpsilonTerminal ) for _ in range(4) ] all_but_one.append(grammar.EpsilonTerminal) for invalid_productions in ( (), {}, None, 'terminal', ['terminal'], grammar.EpsilonTerminal, [grammar.EpsilonTerminal], all_but_one, ): with self.assertRaises(ValueError): grammar.Grammar('terminal', invalid_productions)
awesome_grammar = grammar.Grammar( start_symbol='frase', productions=[ grammar.Production( 'frase', grammar.And( grammar.Multiplier('sujeto', upper=1), 'predicado', grammar.Multiplier( grammar.And('conjuncion', grammar.Multiplier('sujeto', upper=1), 'predicado'), )), ), grammar.Production('conjuncion', grammar.Or(('y', 4), ('o', 6))), grammar.Production('sujeto', grammar.Or('sujeto_masc', 'sujeto_fem')), grammar.Production( 'sujeto_masc', grammar.Or( grammar.And('el', 'nombre_comun_masc'), grammar.And(grammar.Multiplier('el', upper=1), 'nombre_propio_masc'), )), grammar.Production( 'sujeto_fem', grammar.Or( grammar.And('la', 'nombre_comun_fem'), grammar.And(grammar.Multiplier('la', upper=1), 'nombre_propio_fem'), )), grammar.Production( 'nombre_comun_masc', grammar.Or('chico', 'chatarrero', 'profesor', 'mutante', 'zombie'), ), grammar.Production( 'nombre_propio_masc', grammar.Or('Pepe', 'Paco Pil', 'Richal'), ), grammar.Production( 'nombre_comun_fem', grammar.Or('camionera', 'guitarrista', 'prestituta', 'tabernera'), ), grammar.Production( 'nombre_propio_fem', grammar.Or('Juani', 'Pepi', 'Lili'), ), grammar.Production( 'predicado', grammar.And('verbo', grammar.Multiplier('complemento', upper=1))), grammar.Production( 'verbo', grammar.Or( 'corre', 'habla', 'ríe', 'tiene', 'va', 'come', 'dice', 'canta', 'caga', 'mea', 'micciona', 'excreta', 'evacúa', )), grammar.Production( 'complemento', grammar.Or( 'la comida', 'como puede', 'que se las pela', 'soy una rumbera', 'abriendo puertas', 'a las barricadas', 'algo', 'siempre', 'a dos manos', )), ])