Signed-off-by: Jiří Župka <jzupka@xxxxxxxxxx> --- virttest/cartesian_config.py | 72 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/virttest/cartesian_config.py b/virttest/cartesian_config.py index 318b635..092e88d 100755 --- a/virttest/cartesian_config.py +++ b/virttest/cartesian_config.py @@ -30,6 +30,7 @@ Cartesian configuration format file parser. import re, os, optparse, collections, string + class ParserError: def __init__(self, msg, line=None, filename=None, linenum=None): self.msg = msg @@ -73,25 +74,39 @@ class Node(object): self.failed_cases = collections.deque() + def dump(self, indent, recurse=False): + print("%s%s" % (" " * indent, self.name)) + print("%s%s" % (" " * indent, self)) + print("%s%s" % (" " * indent, self.content)) + print("%s%s" % (" " * indent, self.failed_cases)) + if recurse: + for child in self.children: + child.dump(indent + 3, recurse) + + def _match_adjacent(block, ctx, ctx_set): - # TODO: explain what this function does + """ + It try to match as much block as possible from ctx. + + @return: Count of matched blocks. + """ if block[0] not in ctx_set: return 0 if len(block) == 1: - return 1 + return 1 # First match and length is 1. if block[1] not in ctx_set: - return int(ctx[-1] == block[0]) + return int(ctx[-1] == block[0]) # Check match with last from ctx. k = 0 i = ctx.index(block[0]) - while i < len(ctx): - if k > 0 and ctx[i] != block[k]: + while i < len(ctx): # Try to match all of blocks. + if k > 0 and ctx[i] != block[k]: # Block not match i -= k - 1 - k = 0 + k = 0 # Start from first block in next ctx. if ctx[i] == block[k]: k += 1 - if k >= len(block): + if k >= len(block): # match all of blocks break - if block[k] not in ctx_set: + if block[k] not in ctx_set: # block in not in whole ctx. break i += 1 return k @@ -99,7 +114,7 @@ def _match_adjacent(block, ctx, ctx_set): def _might_match_adjacent(block, ctx, ctx_set, descendant_labels): matched = _match_adjacent(block, ctx, ctx_set) - for elem in block[matched:]: + for elem in block[matched:]: # Try to find rest of blocks in subtree if elem not in descendant_labels: return False return True @@ -114,9 +129,12 @@ class Filter(object): for char in s: if not (char.isalnum() or char.isspace() or char in ".,_-"): raise ParserError("Illegal characters in filter") + for word in s.replace(",", " ").split(): # OR + word = [block.split(".") for block in word.split("..")] # AND for word in s.replace(",", " ").split(): word = [block.split(".") for block in word.split("..")] for block in word: + for block in word: # . for elem in block: if not elem: raise ParserError("Syntax error") @@ -124,16 +142,17 @@ class Filter(object): def match(self, ctx, ctx_set): - for word in self.filter: - for block in word: + for word in self.filter: # Go through , + for block in word: # Go through .. if _match_adjacent(block, ctx, ctx_set) != len(block): break else: - return True + return True # All match return False def might_match(self, ctx, ctx_set, descendant_labels): + # There is some posibility to match in children blocks. for word in self.filter: for block in word: if not _might_match_adjacent(block, ctx, ctx_set, @@ -154,10 +173,12 @@ class NoOnlyFilter(Filter): class OnlyFilter(NoOnlyFilter): def is_irrelevant(self, ctx, ctx_set, descendant_labels): + # Matched in this tree. return self.match(ctx, ctx_set) def requires_action(self, ctx, ctx_set, descendant_labels): + # Impossible to match in this tree. return not self.might_match(ctx, ctx_set, descendant_labels) @@ -171,6 +192,14 @@ class OnlyFilter(NoOnlyFilter): return False + def __str__(self): + return "Only %s" % (self.filter) + + + def __repr__(self): + return "Only %s" % (self.filter) + + class NoFilter(NoOnlyFilter): def is_irrelevant(self, ctx, ctx_set, descendant_labels): return not self.might_match(ctx, ctx_set, descendant_labels) @@ -190,6 +219,14 @@ class NoFilter(NoOnlyFilter): return False + def __str__(self): + return "No %s" % (self.filter) + + + def __repr__(self): + return "No %s" % (self.filter) + + class Condition(NoFilter): __slots__ = ["content"] @@ -380,6 +417,8 @@ class Parser(object): node.failed_cases.pop() node = node or self.node + #if self.debug: #Print dict on which is working now. + # node.dump(0) # Update dep for d in node.dep: dep = dep + [".".join(ctx + [d])] @@ -394,7 +433,10 @@ class Parser(object): # Check previously failed filters for i, failed_case in enumerate(node.failed_cases): if not might_pass(*failed_case): - self._debug(" this subtree has failed before") + self._debug("\n* this subtree has failed before %s\n" + " content: %s\n" + " failcase:%s\n", + name, content + node.content, failed_case) del node.failed_cases[i] node.failed_cases.appendleft(failed_case) return @@ -405,6 +447,7 @@ class Parser(object): if (not process_content(node.content, new_internal_filters) or not process_content(content, new_external_filters)): add_failed_case() + self._debug("Failed_cases %s", node.failed_cases) return # Update shortname if node.append_to_shortname: @@ -811,5 +854,8 @@ if __name__ == "__main__": for s in args[1:]: c.parse_string(s) + if options.debug: + c.node.dump(0, True) + dicts = c.get_dicts() print_dicts(options, dicts) -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html