def test_first_nt(self): cfg = CFG.create( initial_symbol='S', productions={ 'S': {'A b', 'A B c'}, 'B': {'b B', 'A d', '&'}, 'A': {'a A', '&'}, }, ) self.assertSetEqual({'A', 'B'}, cfg.first_nonterminal('S')) self.assertSetEqual({'&'}, cfg.first_nonterminal('A')) self.assertSetEqual({'A', '&'}, cfg.first_nonterminal('B')) cfg = CFG.create( initial_symbol='S', productions={ 'S': {'A B C'}, 'A': {'a A', '&'}, 'B': {'b B', 'A C d'}, 'C': {'c C', '&'}, }, ) self.assertSetEqual({'A', 'B', 'C'}, cfg.first_nonterminal('S')) self.assertSetEqual({'&'}, cfg.first_nonterminal('A')) self.assertSetEqual({'A', 'C'}, cfg.first_nonterminal('B')) self.assertSetEqual({'&'}, cfg.first_nonterminal('C'))
def test_without_infertile(self): cfg = CFG.create( initial_symbol='S', productions={ 'S': {'a A', 'a'}, 'A': {'a A'}, }, ) fertile = cfg.without_infertile() self.assertEqual('S', fertile.initial_symbol) self.assertDictEqual({ 'S': {'a'} }, fertile.productions) cfg = CFG.create( initial_symbol='S', productions={ 'S': {'A a A b'}, 'A': {'c', '&'}, }, ) fertile = cfg.without_infertile() self.assertEqual({ 'S': {'A a A b'}, 'A': {'c', '&'}, }, fertile.productions)
def test_epsilon_free(self): cfg = CFG.create( initial_symbol='S', productions={ 'S': {'A a A b'}, 'A': {'c', '&'}, }, ) epsilon_free = cfg.epsilon_free() self.assertEqual('S', epsilon_free.initial_symbol) self.assertDictEqual({ 'S': {'a A b', 'A a b', 'a b', 'A a A b'}, 'A': {'c'}, }, epsilon_free.productions) cfg = CFG.create( initial_symbol='S', productions={ 'S': {'&'}, }, ) epsilon_free = cfg.epsilon_free() self.assertEqual("S'", epsilon_free.initial_symbol) self.assertDictEqual({ "S'": {'S', '&'}, }, epsilon_free.productions)
def test_parse(self): cfg = CFG.create( initial_symbol='E', productions={ 'E': {"T E'"}, "E'": {"+ T E'", '&'}, 'T': {"F T'"}, "T'": {"* F T'", '&'}, 'F': {'( E )', 'id'} }, ) parse = cfg.parse('id + id') self.assertTupleEqual((['id', '+', 'id'], ['E']), next(parse)) self.assertTupleEqual((['id', '+', 'id'], ["E'", 'T']), next(parse)) self.assertTupleEqual((['id', '+', 'id'], ["E'", "T'", 'F']), next(parse)) self.assertTupleEqual((['id', '+', 'id'], ["E'", "T'", 'id']), next(parse)) self.assertTupleEqual((['+', 'id'], ["E'", "T'"]), next(parse)) self.assertTupleEqual((['+', 'id'], ["E'"]), next(parse)) self.assertTupleEqual((['+', 'id'], ["E'", 'T', '+']), next(parse)) self.assertTupleEqual((['id'], ["E'", 'T']), next(parse)) self.assertTupleEqual((['id'], ["E'", "T'", 'F']), next(parse)) self.assertTupleEqual((['id'], ["E'", "T'", 'id']), next(parse)) self.assertTupleEqual(([], ["E'", "T'"]), next(parse)) self.assertTupleEqual(([], ["E'"]), next(parse)) self.assertTupleEqual(([], []), next(parse)) with self.assertRaises(StopIteration): next(parse)
def test_parse_table(self): cfg = CFG.create( initial_symbol='E', productions={ 'E': {"T E'"}, "E'": {"+ T E'", '&'}, 'T': {"F T'"}, "T'": {"* F T'", '&'}, 'F': {'( E )', 'id'} }, ) self.assertDictEqual({ ('E', 'id'): "T E'", ('E', '('): "T E'", ("E'", ')'): '&', ("E'", '+'): "+ T E'", ("E'", '$'): '&', ('T', 'id'): "F T'", ('T', '('): "F T'", ("T'", ')'): '&', ("T'", '+'): '&', ("T'", '*'): "* F T'", ("T'", '$'): '&', ('F', 'id'): 'id', ('F', '('): '( E )', }, cfg.parse_table())
def test_is_ll1(self): cfg = CFG.create( initial_symbol='S', productions={ 'S': {'a S a', 'b S b', 'a', 'b'} } ) self.assertFalse(cfg.is_ll1())
def test_nonterminals(self): cfg = CFG.create( initial_symbol='S', productions={ 'S': {'a A', '&'}, 'A': {'b S'}, }, ) self.assertSetEqual({'S', 'A'}, cfg.nonterminals)
def test_follow(self): cfg = CFG.create( initial_symbol='S', productions={ 'S': {'A B C'}, 'A': {'a A', '&'}, 'B': {'b B', 'A C d'}, 'C': {'c C', '&'}, }, ) self.assertSetEqual({'$'}, cfg.follow('S')) self.assertSetEqual({'a', 'b', 'c', 'd'}, cfg.follow('A')) self.assertSetEqual({'c', '$'}, cfg.follow('B')) self.assertSetEqual({'d', '$'}, cfg.follow('C')) cfg = CFG.create( initial_symbol='E', productions={ 'E': {"T E'"}, "E'": {"+ T E'", '&'}, 'T': {"F T'"}, "T'": {"* F T'", '&'}, 'F': {'( E )', 'id'} }, ) self.assertSetEqual({')', '$'}, cfg.follow('E')) self.assertSetEqual({')', '$'}, cfg.follow("E'")) self.assertSetEqual({'+', ')', '$'}, cfg.follow('T')) self.assertSetEqual({'+', ')', '$'}, cfg.follow("T'")) self.assertSetEqual({'*', '+', ')', '$'}, cfg.follow("F")) cfg = CFG.create( initial_symbol='S', productions={ 'S': {'a S a', 'b S b', 'a', 'b'}, }, ) self.assertEqual({'a', 'b', '$'}, cfg.follow('S')) cfg = CFG.create( initial_symbol='S', productions={ 'S': {'A a A b', 'B b B a'}, 'A': {'&'}, 'B': {'&'}, }, ) self.assertEqual({'a', 'b'}, cfg.follow('A')) self.assertEqual({'a', 'b'}, cfg.follow('B')) cfg = CFG.create( initial_symbol='S', productions={ 'S': {'a B S', 'b A S', '&'}, 'A': {'a', 'b A A'}, 'B': {'b', 'a B B'}, }, ) self.assertSetEqual({'$'}, cfg.follow('S')) self.assertSetEqual({'$', 'a', 'b'}, cfg.follow('A')) self.assertSetEqual({'$', 'a', 'b'}, cfg.follow('B'))
import os import sys sys.path.insert(0, os.path.abspath('../pyt')) from cfg import CFG, print_CFG, generate_ast ast = generate_ast('example_inputs/example.py') cfg = CFG() cfg.create(ast) print_CFG(cfg)
"""Analyse a list of control flow graphs with a given analysis type.""" for cfg in cfg_list: analysis = FixedPointAnalysis(cfg, analysis_type) analysis.fixpoint_runner() if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('filename', help='Filename of the file that should be analysed.', type=str) parser.add_argument('-l', '--liveness', help='Toggle liveness analysis.', action='store_true') parser.add_argument('-r', '--reaching', help='Toggle reaching definitions analysis', action='store_true') args = parser.parse_args() tree = generate_ast(args.filename) cfg = CFG() cfg.create(tree) def run_analysis(cfg, analysis_type): analysis = fixed_point_analysis(cfg, analysis_type) analysis.fixpoint_runner() for cfg_node in cfg.nodes: print(cfg_node) print(cfg_node.new_constraint) if args.liveness: run_analysis(cfg, LivenessAnalysis) if args.reaching: run_analysis(cfg, ReachingDefinitionsAnalysis)