From 85ce2ab0eef76b82ac0a5c2a916d4f5b5a86b3a3 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Thu, 4 Aug 2022 19:11:28 +0100 Subject: [PATCH 1/2] fix: tidy up assignments to clarify values --- src/representation/grammar.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/representation/grammar.py b/src/representation/grammar.py index 787988a5..95810077 100755 --- a/src/representation/grammar.py +++ b/src/representation/grammar.py @@ -316,7 +316,6 @@ def check_recursion(self, cur_symbol, seen): # Get choices of current symbol. choices = self.rules[cur_symbol]['choices'] - nt = self.non_terminals[cur_symbol] recursive = False for choice in choices: @@ -326,10 +325,10 @@ def check_recursion(self, cur_symbol, seen): recursive = recursive or recursive_symbol # Set recursive properties. - nt['recursive'] = recursive + self.non_terminals[cur_symbol]['recursive'] = recursive seen.remove(cur_symbol) - return nt['recursive'] + return recursive def set_arity(self): """ From bca9eb710006de12c8005fec97ebf453774a78f2 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Thu, 4 Aug 2022 19:23:11 +0100 Subject: [PATCH 2/2] feat: store teh result of subtrees in ``check_recursion`` to not re traverse them. --- src/representation/grammar.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/representation/grammar.py b/src/representation/grammar.py index 95810077..5b66851b 100755 --- a/src/representation/grammar.py +++ b/src/representation/grammar.py @@ -43,6 +43,9 @@ def __init__(self, file_name): self.productionregex = '(?=\#)(?:\#.*$)|(?!\#)\s*(?P(?:[^\'\"\|\#]+|\'.*?\'|".*?")+)' self.productionpartsregex = '\ *([\r\n]+)\ *|([^\'"<\r\n]+)|\'(.*?)\'|"(.*?)"|(?P<[^>|\s]+>)|([<]+)' + # to speed up the recursion step + self.recursion_cache = {} + # Read in BNF grammar, set production rules, terminals and # non-terminals. self.read_bnf_file(file_name) @@ -320,9 +323,19 @@ def check_recursion(self, cur_symbol, seen): recursive = False for choice in choices: for sym in choice['choice']: - # Recurse over choices. - recursive_symbol = self.check_recursion(sym["symbol"], seen) - recursive = recursive or recursive_symbol + # T is always non-recursive so no need to care about them + if sym["type"] == "NT": + # Check the cache, no need to traverse the same subtree multiple times + if sym["symbol"] in self.recursion_cache: + # Grab previously calculated value + recursion_result = self.recursion_cache[sym["symbol"]] + else: + # Traverse subtree + recursion_result = self.check_recursion(sym["symbol"], seen) + # Add result to cache for future runs + self.recursion_cache[sym["symbol"]] = recursion_result + + recursive = recursive or recursion_result # Set recursive properties. self.non_terminals[cur_symbol]['recursive'] = recursive