import sys import subprocess #TODO: dodać parentices class AbstractInterpreter: def __init__(self): pass def isValid(self,formula:str)->bool: raise NotImplementedError class SimpleInterpreter(AbstractInterpreter): def __init__(self): pass def isValid(self,formula)->bool: variables = {} f=[] def isBlacklisted(char): return char in ['\n', '\t', ' '] def isSign(char): logic_signs = ['=', '>', '&', '|', '!', '(', ')'] return char in logic_signs def isParentice(char): return char in ('(', ')') def isVariable(char): return not isSign(char) def isNegation(char): return char == '!' #print(vars(formula)) for i,char in enumerate(formula.s): if isBlacklisted(char): return False prev = formula.s[i-1] if i>0 else None #None, gdy jesteśmy na pierwszym znaku if (char=='(' and isVariable(prev) and prev is not None): #a(b|c) return False if isSign(char): if (not isNegation(char)): if isSign(prev) and not isNegation(prev): # tylko negacje mogą się powtarzać po innym znaku return False else: if isVariable(prev) and prev is not None: # obrona przed a!>b return False else: #if current char is a variable if isVariable(prev) and prev is not None: #Obrona abc>d print("previous is also a variable"); return False return True class RegexInterpreter(AbstractInterpreter): def __init__(self): #check if grep is available import subprocess # r=subprocess.run("grep") def isValid(self,f)->bool: formula = "({0})".format(f.s.replace("!", "\\!")) make_reg = lambda formula,pattern: 'echo "{0}" | grep -P "{1}"'.format(formula,pattern) def check_assertion(formula, pattern): cmd = make_reg(formula,pattern) #print("EXECUTING... ",cmd) result = subprocess.run([cmd], shell=True, stdout=subprocess.PIPE) return not len(result.stdout)>0 cmd =make_reg(formula,'^(\((?:[^()]++|(?1))*\))$') #print("EXECUTING... ",cmd) result = subprocess.run([cmd], shell=True, stdout=subprocess.PIPE) isValid = len(result.stdout)>0 if not isValid: return False #assertions assertions = ['(?:[>|&|\|=][\(\)]*){2,}','\((?:[>|&|\|=][\(\)]*)','[a-z]{2,}','\((?:[>|&|\|=|!])?\)'] for assertion in assertions: if not check_assertion(formula,assertion): return False return True # (?:[>|&|\|=][\(\)]*){2,} - czy powtarzają się jakieś operatory obok siebie? # echo "formuła" | grep -P "regex" - to jeżeli coś zwróci to znaczy, że mamy dopasowanie #najpierw sprawdzamy, czy parentices są ok #^(\((?:[^()]++|(?1))*\))$ - powinno zwrócić cały nasz string #potem sprawdzamy czy dopasuje cokolwiek co może być nie tak # \((?:[>|&|\|=][\(\)]*) - (>b) # [a-z]{2,} - czy powtarzają się jakieś lierki obok siebie? # \((?:[>|&|\|=|!])?\) - czy istnieją puste nawiasy, bądź nawiasy z samym operatorem? class ProperInterpreter(AbstractInterpreter): class Expression: def __init__(self,operator,left,right): self.right=right self.left = left self.operator = operator def __init__(self): pass def isValid(self,formula)->bool: try: self.parse(formula.s) except Exception as e: print(e) return False else: return True def check_simple_formula(self,simple_formula:str)->bool: #używamy SimpleInterpretera n = SimpleInterpreter() return Formula(simple_formula,n).isValid() def parse(self,formula:str): #przypisywanie głębi do każdego znaku if len(formula)==0: # print("Empty subformula") return None x=[0 for u in formula] current_depth=0 for i,char in enumerate(formula): if current_depth<0: break if char == '(': current_depth+=1 x[i] = current_depth elif char == ')': x[i] = current_depth current_depth-=1 else: x[i] = current_depth if current_depth!=0: raise Exception("Nawiasy źle umieszczone w podformule: {0}".format(formula)) #print(formula) min_depth = min(x) slice_point = 0 #czy formuła jest prosta? is_simple = True for i in x: if i != x[0]: is_simple=False; break #Szukanie najbardziej znaczącego spójnika for i,char in enumerate(formula): if char in ('>', '&', '|', '=') and x[i] == min_depth: slice_point = i break if is_simple: # print(formula, " is simple") if not self.check_simple_formula(formula): raise Exception("Błąd na poziomie formuły bez zagnieżdzeń: {0}".format(formula)) return False else: s=0 e=len(formula) if min_depth>0: # print("There are useless parentices... Deleting") s=1 e=-1 # print("Slice point: ", slice_point) # print("min depth: ", min_depth) if (s==slice_point): #print("Nie ma spójnika - formuła jest jednak prosta") if not self.check_simple_formula(formula): raise Exception("Błąd na poziomie formuły bez zagnieżdzeń: {0}".format(formula)) return False self.parse(formula[s:slice_point]) self.parse(formula[slice_point+1:e]) class Formula: def __init__(self, formula_string:str, interpreter:AbstractInterpreter=None): self.s = formula_string self.__i = interpreter def isValid(self, interpreter=None)->bool: i = self.__i if interpreter is None else interpreter return i.isValid(self) if len(sys.argv) > 1 : i = ProperInterpreter() if '-g' in sys.argv: i = RegexInterpreter() #print(sys.argv) if '-f' in sys.argv: #open from file print("opening from file") g = open(sys.argv[sys.argv.index('-f')+1], 'r') u = g.readlines() for l in u: print(Formula(l,i).isValid()) else: print(Formula( sys.argv[1] if sys.argv[1] != '-g' else sys.argv[2],i).isValid()) else: print("help?")