def execute_banana_string(banana, driver=None, emitter=emit.PrintEmitter()): """ Execute the provided banana string. It will run the parse phase, and the typechecker. :type banana: str :param banana: The string to parse and type check. :type driver: monasca_analytics.spark.driver.DriverExecutor | None :param driver: Driver that will manage the created components and connect them together. :type emitter: emit.Emitter :param emitter: Emitter for reporting errors/warning. """ try: # Convert the grammar into an AST parser = grammar.banana_grammar(emitter) ast = parser.parse(banana) # Compute the type table for the given AST type_table = typeck.typeck(ast) # Remove from the tree path that are "dead" deadpathck.deadpathck(ast, type_table, emitter) # Check that there's at least one path to be executed deadpathck.contains_at_least_one_path_to_a_sink(ast, type_table) # Evaluate the script if driver is not None: ev.eval_ast(ast, type_table, driver) except exception.BananaException as err: emitter.emit_error(err.get_span(), str(err)) except p.ParseSyntaxException as err: emitter.emit_error(span_util.from_pyparsing_exception(err), err.msg) except p.ParseFatalException as err: emitter.emit_error(span_util.from_pyparsing_exception(err), err.msg) except p.ParseException as err: emitter.emit_error(span_util.from_pyparsing_exception(err), err.msg)
def compute_type_table(banana): """ Compute the type table for the provided banana string if possible. :type banana: str :param banana: The string to parse and type check. """ # Convert the grammar into an AST parser = grammar.banana_grammar() ast = parser.parse(banana) # Compute the type table for the given AST return typeck.typeck(ast)
def compute_evaluation_context(banana, cb=lambda *a, **k: None): """ Compute the evaluation context for the provided banana string. :type banana_str: str :param banana_str: The string to parse and type check. :param cb: Callback called after each statement """ parser = grammar.banana_grammar() ast = parser.parse(banana) type_table = typeck.typeck(ast) context = ctx.EvaluationContext() def custom_cb(_type, lhs, value): cb(context, _type, lhs, value) ev.eval_statements_generic(ast.statements, type_table, context, custom_cb)
def test_banana_should_pass_when_more_source_sink(self): banana_str = "" +\ "a = CloudMarkovChainSource()\n" +\ "b = StdoutSink()\n" +\ "c = CloudIngestor()\n" +\ "d = LiNGAM()\n" +\ "a -> c -> d -> b" # Convert the grammar into an AST parser = grammar.banana_grammar() ast = parser.parse(banana_str) # Compute the type table for the given AST type_table = typeck.typeck(ast) # Remove from the tree path that are "dead" deadpathck.deadpathck(ast, type_table) deadpathck.contains_at_least_one_path_to_a_sink(ast, type_table) # We should reach this line. self.assertTrue(True)
def test_banana_should_fail_when_no_sink(self): banana_str = "" +\ "a = CloudMarkovChainSource()\n" +\ "b = StdoutSink()\n" +\ "c = CloudIngestor()\n" +\ "d = LiNGAM()\n" +\ "a -> c -> d" # Convert the grammar into an AST parser = grammar.banana_grammar() ast = parser.parse(banana_str) # Compute the type table for the given AST type_table = typeck.typeck(ast) # Remove from the tree path that are "dead" deadpathck.deadpathck(ast, type_table) self.assertRaises(exception.BananaNoFullPath, deadpathck.contains_at_least_one_path_to_a_sink, ast, type_table)
def test_banana_should_not_remove_anything(self): banana_str = "" +\ "a = CloudMarkovChainSource()\n" +\ "b = StdoutSink()\n" +\ "c = CloudIngestor()\n" +\ "d = LiNGAM()\n" +\ "a -> c -> d -> b" emitter = CustomEmitter() # Convert the grammar into an AST parser = grammar.banana_grammar(emitter) ast = parser.parse(banana_str) # Compute the type table for the given AST type_table = typeck.typeck(ast) # Remove from the tree path that are "dead" deadpathck.deadpathck(ast, type_table, emitter) self.assertEqual(emitter.nb_errors, 0) self.assertEqual(emitter.nb_warnings, 0) self.assertEqual(len(ast.components), 4) self.assertEqual(len(list(ast.connections.connections)), 3)
def test_banana_should_not_remove_anything(self): banana_str = "" +\ "a = CloudMarkovChainSource()\n" +\ "b = StdoutSink()\n" +\ "c = CloudIngestor()\n" +\ "d = LiNGAM()\n" +\ "a -> c -> d -> b" emitter = CustomEmitter() # Convert the grammar into an AST parser = grammar.banana_grammar(emitter) ast = parser.parse(banana_str) # Compute the type table for the given AST type_table = typeck.typeck(ast) # Remove from the tree path that are "dead" deadpathck.deadpathck(ast, type_table, emitter) self.assertEqual(emitter.nb_errors, 0) self.assertEqual(emitter.nb_warnings, 0) self.assertEqual(len(ast.components), 4) self.assertEqual(len(list(ast.connections.connections)), 3)
def try_compute_type_table(banana): """ Compute the type table for the provided banana string if possible. Does not throw any exception if it fails. :type banana: str :param banana: The string to parse and type check. """ try: # Convert the grammar into an AST parser = grammar.banana_grammar() ast = parser.parse(banana) # Compute the type table for the given AST return typeck.typeck(ast) except exception.BananaException: return None except p.ParseSyntaxException: return None except p.ParseFatalException: return None except p.ParseException: return None