Skip to content

Commit

Permalink
correcly parse complex embeddings of atoms with or without predicate
Browse files Browse the repository at this point in the history
  • Loading branch information
Aluriak committed Oct 30, 2019
1 parent ffd4ffb commit c0c090c
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 13 deletions.
17 changes: 12 additions & 5 deletions clyngor/parsing.py
Expand Up @@ -33,8 +33,12 @@ def visit_number(self, node, children):
def visit_args(self, node, children):
return children

def visit_aloneargs(self, node, children):
return self.visit_term(node, ('', *children))
def visit_single_value(self, node, children):
return self.visit_subterm(node, children)
def visit_one_uplet(self, node, children):
return self.visit_term(node, ('', children))
def visit_n_uplet(self, node, children):
return self.visit_term(node, ('', children))

def visit_text(self, node, children):
text = tuple(children)[0] if children else ''
Expand Down Expand Up @@ -70,9 +74,12 @@ def ident(): return ap.RegExMatch(r'[a-z][a-zA-Z0-9_]*')
def number(): return ap.RegExMatch(r'-?[0-9]+')
def text(): return '"', ap.RegExMatch(r'((\\")|([^"]))*'), '"'
def litteral(): return [text, number]
def subterm(): return [(ident, ap.Optional("(", args, ")")), litteral, aloneargs]
def args(): return subterm, ap.ZeroOrMore(',', subterm)
def aloneargs(): return '(', args, ')'
def subterm(): return [(ident, ap.Optional('(', args, ')')), litteral, aloneargs]
def args(): return subterm, ap.ZeroOrMore(',', subterm), ap.Optional(',')
def aloneargs(): return [single_value, one_uplet, n_uplet]
def single_value(): return '(', subterm, ')'
def one_uplet(): return '(', subterm, ',', ')'
def n_uplet(): return '(', subterm, ap.OneOrMore(',', subterm), ')'
# NB: litteral outputed by #show are not handled.
def term(): return ident, ap.Optional("(", args, ")")
def terms(): return ap.ZeroOrMore(term)
Expand Down
7 changes: 7 additions & 0 deletions clyngor/test/test_parsing.py
Expand Up @@ -34,6 +34,13 @@ def test_parse_termset_default():
}
assert Parser().parse_terms(string) == expected

def test_parse_tuple():
string = 'a(b,(2,3,(a,b)))'
expected = {
('a', ('b', ('', (2, 3, ('', ('a', 'b')))))),
}
assert Parser().parse_terms(string) == expected

def test_parse_args_without_predicat():
string = 'a((b,10)) c("",("",""))'
expected = {
Expand Down
7 changes: 4 additions & 3 deletions clyngor/test/test_utils.py
Expand Up @@ -60,15 +60,16 @@ def test_answer_set_to_str():
assert '.'.join(generate_answer_set_as_str((('a', (1, 2)), ('b', ())))) == 'a(1,2).b'
assert ''.join(generate_answer_set_as_str((('a', (1, 2)), ('b', ())), atom_end='.')) == 'a(1,2).b.'
assert '1'.join(generate_answer_set_as_str((('a', (1, 2)), ('b', ())), atom_end='2')) == 'a(1,2)21b2'
assert ' '.join(generate_answer_set_as_str((('', ('v', 2)), ('b', (['v', 3],))), atom_end='.')) == '(v,2). b((v,3)).'
assert ' '.join(generate_answer_set_as_str((('', ('v', 2)), ('b', (('', ['v', 3]),))), atom_end='.')) == '(v,2). b((v,3)).'
assert ' '.join(generate_answer_set_as_str((('', ('', ('', (2,)))),))) == '("",(2,))'
assert '.'.join(generate_answer_set_as_str((('a', (('', ('1', '2')),)),))) == 'a((1,2))'

def test_answer_set_to_str_complex():
generate_answer_set_as_str = utils.generate_answer_set_as_str
asp = 'a(a(2,3),(2,),b(c((d,),(e,f)))).'
models = tuple(ASP(asp).careful_parsing)
models = tuple(ASP(asp).parse_args)
print('CAREFUL:', models)
answerset = models[0]
models = tuple(ASP(asp))
print('NORMAL :', models)
answerset = models[0]
assert ' '.join(generate_answer_set_as_str(answerset, atom_end='.')) == asp
10 changes: 5 additions & 5 deletions clyngor/utils.py
Expand Up @@ -112,7 +112,7 @@ def clingo_value_to_python(value:object) -> int or str or tuple:
"".format(value, type(value)))


def python_value_to_asp(val:str or int or list or tuple, *, first_order:bool=True) -> str or tuple:
def python_value_to_asp(val:str or int or list or tuple, *, args_of_predicate:bool=False) -> str or tuple:
"""Convert given python value in an ASP format"""
if isinstance(val, (str, int)):
return str(val) or '""'
Expand All @@ -122,14 +122,14 @@ def python_value_to_asp(val:str or int or list or tuple, *, first_order:bool=Tru
assert len(val) == 2, "tuple value should be of size 2: (predicate, args))"
predicate, args = val
if args:
return predicate + python_value_to_asp(list(args), first_order=first_order)
return predicate + '(' + python_value_to_asp(list(args), args_of_predicate=bool(predicate)) + ')'
else: # no args
return predicate
elif isinstance(val, list):
ender = ',)' if len(val) == 1 and not first_order else ')'
return '(' + ','.join(map(python_value_to_asp.second_order, val)) + ender
ender = ',' if len(val) == 1 and not args_of_predicate else ''
return ','.join(map(python_value_to_asp, val)) + ender
raise ValueError(f"Python value '{repr(val)}' of type {type(val)} is not convertible in ASP.")
python_value_to_asp.second_order = lambda x: python_value_to_asp(x, first_order=False)
# python_value_to_asp.in_predicate = lambda x: python_value_to_asp(x, args_of_predicate=True)


def answer_set_to_str(answer_set:iter, atom_end:str='', atom_sep:str=' ') -> str:
Expand Down

0 comments on commit c0c090c

Please sign in to comment.