Tests and conclusions are conjunctions of terms (“,” means “and”). Each term is a
list of words or variables separated by spaces; variables start with ?. To use a rule, it is
translated to an internal form—a dictionary with nested lists. To display a rule, it is
translated back to the string form. For instance, given the call:
rules.internal_rule('rule x if a ?x, b then c, d ?x')
the conversion in function internal_rule proceeds as follows:
string = 'rule x if a ?x, b then c, d ?x'
i = ['rule x', 'a ?x, b then c, d ?x']
t = ['a ?x, b', 'c, d ?x']
r = ['', 'x']
result = {'rule':'x', 'if':[['a','?x'], ['b']], 'then':[['c'], ['d','?x']]}
We first split around the if, then around the then, and finally around rule. The result
is the three substrings that were separated by the keywords. Test and conclusion sub-
strings are split around “,” first and spaces last. join is used later to convert back (un-
parse) to the original string for display. Example 19-2 is the concrete implementation
of this scheme.
Example 19-2. PP4E\Lang\rules.py
def internal_rule(string):
i = string.split(' if ')
t = i[1].split(' then ')
r = i[0].split('rule ')
return {'rule': r[1].strip(), 'if':internal(t[0]), 'then':internal(t[1])}
def external_rule(rule):
return ('rule ' + rule['rule'] +
' if ' + external(rule['if']) +
' then ' + external(rule['then']) + '.')
def internal(conjunct):
res = [] # 'a b, c d'
for clause in conjunct.split(','): # -> ['a b', ' c d']
res.append(clause.split()) # -> [['a','b'], ['c','d']]
return res
def external(conjunct):
strs = []
for clause in conjunct: # [['a','b'], ['c','d']]
strs.append(' '.join(clause)) # -> ['a b', 'c d']
return ', '.join(strs) # -> 'a b, c d'
Today we could use list comprehensions and generator expressions to gain some con-
ciseness here. The internal and external functions, for instance, could be recoded to
simply (see file rules2.py):
def internal(conjunct):
return [clause.split() for clause in conjunct.split(',')]
String Method Utilities | 1413