Skip to content

Commit

Permalink
Merge pull request #587 from hed-standard/dev_update_search
Browse files Browse the repository at this point in the history
Add a 'not in line' symbol to search
  • Loading branch information
VisLab committed Feb 2, 2023
2 parents b38c773 + 6218526 commit 8bbd978
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 11 deletions.
19 changes: 15 additions & 4 deletions hed/models/expression_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ def __init__(self, group, tag):
self.group = group
# todo: rename tag: children
if not isinstance(tag, list):
from hed import HedString
if isinstance(tag, HedString):
breakHere = 3
new_tags = [tag]
else:
new_tags = tag.copy()
Expand Down Expand Up @@ -68,6 +65,7 @@ class Token:
Wildcard = 10
ExactMatch = 11
ExactMatchEnd = 12
NotInLine = 13 # Not currently a token. In development and may become one.

def __init__(self, text):
tokens = {
Expand All @@ -86,6 +84,7 @@ def __init__(self, text):
"???": Token.Wildcard, # Any Group
"{": Token.ExactMatch, # Nothing else
"}": Token.ExactMatchEnd, # Nothing else
"@": Token.NotInLine
}
self.kind = tokens.get(text, Token.Tag)
self.text = text
Expand All @@ -105,6 +104,10 @@ def __init__(self, token, left=None, right=None):
self.right = right
self.token = token
self._match_mode = "/" in token.text
self._must_not_be_in_line = False
if token.text.startswith("@"):
self._must_not_be_in_line = True
token.text = token.text[1:]
if token.text.startswith('"') and token.text.endswith('"') and len(token.text) > 2:
self._match_mode = 1
token.text = token.text[1:-1]
Expand All @@ -129,6 +132,13 @@ def handle_expr(self, hed_group, exact=False):
else:
groups_found = hed_group.find_tags_with_term(self.token.text, recursive=True, include_groups=2)

if self._must_not_be_in_line:
# If we found this, and it cannot be in the line.
if groups_found:
groups_found = []
else:
groups_found = [(None, group) for group in hed_group.get_all_groups()]

# If we're checking for all groups, also need to add parents.
if exact:
all_found_groups = [search_result(group, tag) for tag, group in groups_found]
Expand Down Expand Up @@ -172,6 +182,7 @@ def handle_expr(self, hed_group, exact=False):
# finally simplify the list and remove duplicates.

return return_list

def __str__(self):
output_str = "("
if self.left:
Expand Down Expand Up @@ -398,7 +409,7 @@ def _parse(self, expression_string):
def _tokenize(self, expression_string):
grouping_re = r"\[\[|\[|\]\]|\]|}|{"
paren_re = r"\)|\(|~"
word_re = r"\?+|@|\band\b|\bor\b|,|[\"_\-a-zA-Z0-9/.^#\*]+"
word_re = r"\?+|\band\b|\bor\b|,|[\"_\-a-zA-Z0-9/.^#\*@]+"
re_string = fr"({grouping_re}|{paren_re}|{word_re})"
token_re = re.compile(re_string)

Expand Down
49 changes: 42 additions & 7 deletions tests/models/test_expression_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,18 +651,53 @@ def test_logical_negation(self):
hed_string = HedString("A, C")
self.assertEqual(bool(expression.search_hed_string(hed_string)), False)

def test_kay(self):
def test_not_in_line(self):
test_strings = {
"Event, (Event, Sensory-event)": True,
"A": True,
"B": False,
"C": True,
"A, B": False,
"A, C": True,
"B, C": False,
"A, B, C": False,
"D, A, B": False,
"A, B, (C)": False,
"(A, B, (C))": False,
"(A, B, (C)), D": False,
"(A, B, (C)), (D), E": False,
}
self.base_test("Event", test_strings)
self.base_test("@B", test_strings)

def test_not_in_line2(self):
test_strings = {
"Event, (Event, Sensory-event), Event": True,
"A": False,
"B": False,
"C": True,
"A, B": False,
"A, C": True,
"B, C": False,
"A, B, C": False,
"D, A, B": False,
"A, B, (C)": False,
"(A, B, (C))": False,
"(A, B, (C)), D": False,
"(A, B, (C)), (D), E": False,
}
self.base_test("Event and Sensory-event", test_strings)
self.base_test("@B and C", test_strings)

def test_not_in_line3(self):
test_strings = {
"Sensory-event, (Event, Sensory-event), Event": True,
"A": True,
"B": True,
"C": False,
"A, B": True,
"A, C": False,
"B, C": True,
"A, B, C": True,
"D, A, B": True,
"A, B, (C)": True,
"(A, B, (C))": True,
"(A, B, (C)), D": True,
"(A, B, (C)), (D), E": True,
}
self.base_test("[Sensory-event]", test_strings)
self.base_test("@C or B", test_strings)

0 comments on commit 8bbd978

Please sign in to comment.