def check(formula): """Parse formula string and create abstract syntax tree (AST). """ ast = lexyacc.parse(formula) dfa = trs.automata.FiniteWordAutomaton(atomic_proposition_based=False, deterministic=True) dfa.alphabet |= {'!', 'W', 'U', 'G', 'F', 'U_left', 'U_right', 'W_left', 'W_right'} dfa.states.add_from({'gf', 'fg', 'g', 'f'}) dfa.states.initial.add('gf') dfa.transitions.add('gf', 'fg', letter='!') dfa.transitions.add('fg', 'gf', letter='!') dfa.transitions.add('g', 'f', letter='!') dfa.transitions.add('f', 'g', letter='!') dfa.transitions.add('gf', 'gf', letter='W') dfa.transitions.add('gf', 'gf', letter='U_left') dfa.transitions.add('gf', 'gf', letter='G') dfa.transitions.add('fg', 'fg', letter='U') dfa.transitions.add('fg', 'fg', letter='F') dfa.transitions.add('fg', 'fg', letter='W_right') dfa.transitions.add('gf', 'f', letter='U_right') dfa.transitions.add('gf', 'f', letter='F') dfa.transitions.add('fg', 'g', letter='W_left') dfa.transitions.add('fg', 'g', letter='G') dfa.transitions.add('g', 'g', letter='W') dfa.transitions.add('g', 'g', letter='G') dfa.transitions.add('f', 'f', letter='U') dfa.transitions.add('f', 'f', letter='F') # plot tree automaton # dfa.save('dfa.pdf') # plot parse tree sast.dump_dot(ast, 'ast.dot') # sync product of AST with DFA, # to check acceptance Q = [(ast, 'gf')] while Q: s, q = Q.pop() logger.info('visiting: ' + str(s) + ', ' + str(q)) if isinstance(s, sast.Unary): op = s.operator if op in {'!', 'G', 'F'}: t = dfa.transitions.find(q, letter=op) if not t: raise Exception('not in fragment') qi, qj, w = t[0] Q.append((s.operand, qj)) else: # ignore Q.append((s.operand, q)) elif isinstance(s, sast.Binary): op = s.operator if op in {'W', 'U'}: t = dfa.transitions.find(q, letter=op) if t: qi, qj, w = t[0] Q.append((s.op_l, qj)) Q.append((s.op_r, qj)) else: t = dfa.transitions.find(q, letter=op + '_left') if not t: raise Exception('not in fragment') qi, qj, w = t[0] Q.append((s.op_l, qj)) t = dfa.transitions.find(q, letter=op + '_right') if not t: raise Exception('not in fragment') qi, qj, w = t[0] Q.append((s.op_r, qj)) else: # ignore Q.append((s.op_l, q)) Q.append((s.op_r, q)) elif isinstance(s, sast.Var): print('reached var') return ast
def check(formula): """Parse formula string and create abstract syntax tree (AST). """ ast = lexyacc.parse(formula) dfa = trs.automata.FiniteWordAutomaton(atomic_proposition_based=False, deterministic=True) dfa.alphabet |= { '!', 'W', 'U', 'G', 'F', 'U_left', 'U_right', 'W_left', 'W_right' } dfa.states.add_from({'gf', 'fg', 'g', 'f'}) dfa.states.initial.add('gf') dfa.transitions.add('gf', 'fg', letter='!') dfa.transitions.add('fg', 'gf', letter='!') dfa.transitions.add('g', 'f', letter='!') dfa.transitions.add('f', 'g', letter='!') dfa.transitions.add('gf', 'gf', letter='W') dfa.transitions.add('gf', 'gf', letter='U_left') dfa.transitions.add('gf', 'gf', letter='G') dfa.transitions.add('fg', 'fg', letter='U') dfa.transitions.add('fg', 'fg', letter='F') dfa.transitions.add('fg', 'fg', letter='W_right') dfa.transitions.add('gf', 'f', letter='U_right') dfa.transitions.add('gf', 'f', letter='F') dfa.transitions.add('fg', 'g', letter='W_left') dfa.transitions.add('fg', 'g', letter='G') dfa.transitions.add('g', 'g', letter='W') dfa.transitions.add('g', 'g', letter='G') dfa.transitions.add('f', 'f', letter='U') dfa.transitions.add('f', 'f', letter='F') # plot tree automaton # dfa.save('dfa.pdf') # plot parse tree sast.dump_dot(ast, 'ast.dot') # sync product of AST with DFA, # to check acceptance Q = [(ast, 'gf')] while Q: s, q = Q.pop() logger.info('visiting: ' + str(s) + ', ' + str(q)) if isinstance(s, sast.Unary): op = s.operator if op in {'!', 'G', 'F'}: t = dfa.transitions.find(q, letter=op) if not t: raise Exception('not in fragment') qi, qj, w = t[0] Q.append((s.operand, qj)) else: # ignore Q.append((s.operand, q)) elif isinstance(s, sast.Binary): op = s.operator if op in {'W', 'U'}: t = dfa.transitions.find(q, letter=op) if t: qi, qj, w = t[0] Q.append((s.op_l, qj)) Q.append((s.op_r, qj)) else: t = dfa.transitions.find(q, letter=op + '_left') if not t: raise Exception('not in fragment') qi, qj, w = t[0] Q.append((s.op_l, qj)) t = dfa.transitions.find(q, letter=op + '_right') if not t: raise Exception('not in fragment') qi, qj, w = t[0] Q.append((s.op_r, qj)) else: # ignore Q.append((s.op_l, q)) Q.append((s.op_r, q)) elif isinstance(s, sast.Var): print('reached var') return ast