def test_loop_nodes(self): syntax_tree = SyntaxTree() syntax_tree.add_node_to_current_level(SyntaxNode("raw", ["loop"])) syntax_tree.add_node_to_current_level(SyntaxNode("raw", [" over:"])) syntax_tree.branch_with_new_node( SyntaxNode("loop", ["fruits", "fruit"])) syntax_tree.add_node_to_current_level(SyntaxNode("raw", [" "])) syntax_tree.add_node_to_current_level(SyntaxNode("print", ["fruit"])) syntax_tree.add_node_to_current_level( SyntaxNode("print", ["separator"])) syntax_tree.return_to_upper_level() syntax_tree.add_node_to_current_level(SyntaxNode("raw", ["!"])) expected_result = "loop over: apples, bananas, pie,!" variables = {"fruits": ["apples", "bananas", "pie"], "separator": ","} throw_invalid_syntax = False actual_result = syntax_processor.process_syntax_tree( syntax_tree, variables, throw_invalid_syntax) self.assertEqual(expected_result, actual_result)
def test_error_node(self): syntax_tree = SyntaxTree() syntax_tree.add_node_to_current_level(SyntaxNode("raw", ["an"])) syntax_tree.add_node_to_current_level(SyntaxNode("raw", [" "])) syntax_tree.add_node_to_current_level(SyntaxNode( "error", ["{{error}"])) expected_result = "an {{error}" variables = {} throw_invalid_syntax = False actual_result = syntax_processor.process_syntax_tree( syntax_tree, variables, throw_invalid_syntax) self.assertEqual(expected_result, actual_result)
def test_flat_print_nodes(self): syntax_tree = SyntaxTree() syntax_tree.add_node_to_current_level(SyntaxNode("raw", ["a"])) syntax_tree.add_node_to_current_level(SyntaxNode("raw", [" "])) syntax_tree.add_node_to_current_level(SyntaxNode("print", ["var1"])) syntax_tree.add_node_to_current_level(SyntaxNode("print", ["var2"])) syntax_tree.add_node_to_current_level(SyntaxNode("print", ["var3"])) expected_result = "a test string" variables = {"var1": "test", "var2": " ", "var3": "string"} throw_invalid_syntax = False actual_result = syntax_processor.process_syntax_tree( syntax_tree, variables, throw_invalid_syntax) self.assertEqual(expected_result, actual_result)
def process(self, input_stream: TextIO, output_stream: TextIO): """ Start processing input stream and write the result into the output stream. :param input_stream: The text input. Make sure that proper buffering is used. :param output_stream: The output text stream. Make sure proper buffering is used. """ syntax_tree = SyntaxTree() supported_functions = [ FunctionSignature("raw", 1, False), FunctionSignature("error", 1, False), FunctionSignature("loop", 2, True), FunctionSignature("print", 1, False), ] syntax_analyser = SyntaxAnalyser(supported_functions) token = self.parser.parse_single_token(input_stream) while not token.function_name == "end": is_valid, analysed_token = syntax_analyser.analyse_token( syntax_tree.current_node, token) syntax_node = SyntaxNode(analysed_token.function_name, analysed_token.arguments) if analysed_token.scope is ScopeAction.NONE: syntax_tree.add_node_to_current_level(syntax_node) elif analysed_token.scope is ScopeAction.OPEN: syntax_tree.branch_with_new_node(syntax_node) elif analysed_token.scope is ScopeAction.CLOSE: syntax_tree.return_to_upper_level() # once we have flat structure (simple text or after loop exit) # we can process and output a result if syntax_tree.current_level == 1: result = process_syntax_tree( syntax_tree, self.global_variables, self.throw_invalid) output_stream.write(result) syntax_tree = SyntaxTree() token = self.parser.parse_single_token(input_stream)
def test_nested_loop_nodes(self): syntax_tree = SyntaxTree() syntax_tree.add_node_to_current_level(SyntaxNode("raw", ["loop"])) syntax_tree.add_node_to_current_level(SyntaxNode("raw", [" over: "])) syntax_tree.branch_with_new_node( SyntaxNode("loop", ["fruits", "fruit"])) syntax_tree.add_node_to_current_level(SyntaxNode("raw", ["combo:"])) syntax_tree.branch_with_new_node( SyntaxNode("loop", ["drinks", "drink"])) syntax_tree.add_node_to_current_level(SyntaxNode("raw", [" "])) syntax_tree.add_node_to_current_level(SyntaxNode("print", ["fruit"])) syntax_tree.add_node_to_current_level(SyntaxNode("print", ["colon"])) syntax_tree.add_node_to_current_level(SyntaxNode("print", ["drink"])) syntax_tree.add_node_to_current_level( SyntaxNode("print", ["separator"])) syntax_tree.return_to_upper_level() syntax_tree.add_node_to_current_level(SyntaxNode("raw", [" or "])) syntax_tree.return_to_upper_level() syntax_tree.add_node_to_current_level(SyntaxNode("raw", ["!"])) expected_result = "loop over: combo: apples-water, apples-beer, or combo: bananas-water, bananas-beer, or !" variables = { "drinks": ["water", "beer"], "fruits": ["apples", "bananas"], "separator": ",", "colon": "-" } throw_invalid_syntax = False actual_result = syntax_processor.process_syntax_tree( syntax_tree, variables, throw_invalid_syntax) self.assertEqual(expected_result, actual_result)