def tree(text): lexer = Lexer(text) parser = Parser(lexer) tree = parser.parse() sem_an = SemanticAnalyzer(tree) sem_an.analyse() return tree
def test_parser_expr_assign(): text = 'a: int = (12 + 2) * 2;' lexer = Lexer(text) parser = Parser(lexer) node1 = parser.parse() assert isinstance(node1, Block) assert len(node1.children) == 2 node2 = node1.children[0] assert isinstance(node2, Assign) assert isinstance(node2.name, Variable) assert node2.type.type == 'TYPE' # TYPE Token as type assert node2.type.value == 'int' assert isinstance(node2.value, BinOp) node3 = node2.value assert isinstance(node3.left, BinOp) assert node3.op.value == '*' assert isinstance(node3.right, Number) node4 = node3.left assert isinstance(node4.left, Number) assert node4.op.value == '+' assert isinstance(node4.right, Number)
def test_parser_func_decl3(): text = """ function function_name(a: int, b: int) { return (b + a); } """ lexer = Lexer(text) parser = Parser(lexer) block = parser.parse() func_decl = block.children[0] assert isinstance(func_decl, FuncDecl) # Params params = func_decl.formal_params assert isinstance(params, list) assert len(params) == 2 first_param = params[0] assert isinstance(first_param, Param) assert first_param.var_node.value == 'a' assert first_param.type_node.value == 'int' second_param = params[1] assert isinstance(second_param, Param) assert second_param.var_node.value == 'b' assert second_param.type_node.value == 'int' # Block func_block = func_decl.block_node assert isinstance(func_block, Block)
def evaluate(code: str, tape_size: int = 1000) -> str: """ Helper function which combines the process of lexing, syntax analysis, and parsing/evaluation to return either the finaly output or an error message. Parameters: code : str the brainfxck code to be evaluated. Returns: str """ # Pass the input code to the lexer, then to the syntax analyser # where if the is_faulty parameter is true, then the error messages # generated by the analyser method are returned, otherwise the # token stream is passed to the parser and the output generated # is returned # Lexical analysis to generate a token stream lexer = Lexer(code) token_stream = lexer.lex() syntax_analyser = SyntaxAnalyser(token_stream) error_dic = syntax_analyser.analyse() if error_dic["is_faulty"]: # Adding a newline character to the beginning of the error message op_string = "\n" # Traversing throught the faulty tokens in the token list for token in error_dic["faulty_token_list"]: op_string += ( f"Error for {token.op_name} at :: line : {token.line_number} position : {token.posn_number}\n" ) return op_string # Parsing the token stream to generate output parser = Parser(token_stream, tape_size) parser.parse() output = parser.output_string return output
def interpret(expression): try: parser = Parser(expression) node = parser.parse() result = node.traverse() namespace.set("_", result) return result except KeyError as key_error: print("Error: name {} is not defined".format(key_error)) except Exception as exception: print("{}: {}".format(type(exception).__name__, str(exception)))
def test_parser_function_call1(): text = """ some_function(); """ lexer = Lexer(text) parser = Parser(lexer) block = parser.parse() func_call = block.children[0] assert isinstance(func_call, FuncCall) assert func_call.params == [] assert func_call.func_name == 'some_function' assert func_call.token.value == 'some_function'
def test_parser_statement_after_if(): text = """ if (a > 2) { print('yo'); } b: int = 4; """ lexer = Lexer(text) parser = Parser(lexer) main_block = parser.parse() if_node = main_block.children[0] assert isinstance(if_node, IfStatement) assgn_node = main_block.children[1] assert isinstance(assgn_node, Assign)
def test_parser_statement_before_if(): text = """ a: str = "hey"; if (a == 2) { print('yes'); } """ lexer = Lexer(text) parser = Parser(lexer) main_block = parser.parse() assign_node = main_block.children[0] assert isinstance(assign_node, Assign) if_node = main_block.children[1] assert isinstance(if_node, IfStatement)
def test_parser_print_str(): text = 'print("Hello");' lexer = Lexer(text) parser = Parser(lexer) node1 = parser.parse() # First node should be Block assert isinstance(node1, Block) assert len(node1.children) == 2 # Print node and Empty node node2 = node1.children[0] assert isinstance(node2, Print) assert len(node2.args) == 1 node3 = node2.args[0] assert isinstance(node3, String) assert node3.value == 'Hello'
def test_parser_print_bool(): text = 'print(True);' lexer = Lexer(text) parser = Parser(lexer) node1 = parser.parse() # First node should be Block assert isinstance(node1, Block) assert len(node1.children) == 2 # Print node and Empty node node2 = node1.children[0] assert isinstance(node2, Print) assert len(node2.args) == 1 node3 = node2.args[0] assert isinstance(node3, Boolean) assert node3.value == True
def test_parser_str_assign(): text = 'a: str = "string";' lexer = Lexer(text) parser = Parser(lexer) node1 = parser.parse() assert isinstance(node1, Block) assert len(node1.children) == 2 node2 = node1.children[0] assert isinstance(node2, Assign) assert isinstance(node2.name, Variable) assert node2.type.type == 'TYPE' # TYPE Token as type assert node2.type.value == 'str' assert isinstance(node2.value, String) node3 = node2.value assert node3.value == 'string'
def test_parser_int_assign(): text = 'a: int = 46;' lexer = Lexer(text) parser = Parser(lexer) node1 = parser.parse() assert isinstance(node1, Block) assert len(node1.children) == 2 node2 = node1.children[0] assert isinstance(node2, Assign) assert isinstance(node2.name, Variable) assert node2.type.type == 'TYPE' # TYPE Token as type assert node2.type.value == 'int' assert isinstance(node2.value, Number) node3 = node2.value assert node3.value == 46
def test_parser_nested_func_call(): text = """ function some_function(a: int) { b: int = a + 1; return (b); } print(some_function(2)); """ lexer = Lexer(text) parser = Parser(lexer) block = parser.parse() func_decl = block.children[0] assert isinstance(func_decl, FuncDecl) assert len(func_decl.formal_params) == 1 assert func_decl.func_name.value == 'some_function' print_statement = block.children[1] assert isinstance(print_statement, Print)
def test_parser_bool_assign(): text = 'variable: bool = True;' lexer = Lexer(text) parser = Parser(lexer) node1 = parser.parse() assert isinstance(node1, Block) assert len(node1.children) == 2 node2 = node1.children[0] assert isinstance(node2, Assign) assert isinstance(node2.name, Variable) assert node2.type.type == 'TYPE' # TYPE Token as type assert node2.type.value == 'bool' assert isinstance(node2.value, Boolean) node3 = node2.value assert node3.value == True
def run_interpreter(text): result = {} result['output'] = [] with Capturing() as output: try: lexer = Lexer(text) parser = Parser(lexer) tree = parser.parse() sem_an = SemanticAnalyzer(tree) sem_an.analyse() interpreter = Interpreter(tree) result['final_result'] = interpreter.interpret() except Exception as exc: result['exception'] = str(exc) if output: result['output'] = output return result
def test_parser_if_comparison2(): text = """ if (a <= 2) { print('yo'); } """ lexer = Lexer(text) parser = Parser(lexer) block = parser.parse() if_node = block.children[0] assert isinstance(if_node, IfStatement) assert isinstance(if_node.value, Comparison) assert isinstance(if_node.block, Block) assert if_node.elseblock is None comp_node = if_node.value assert isinstance(comp_node.left, Variable) assert comp_node.op.value == '<=' assert isinstance(comp_node.right, Number)
def test_parser_function_call_with_params(): text = """ some_function(12 + 4, 'string', 78); """ lexer = Lexer(text) parser = Parser(lexer) block = parser.parse() func_call = block.children[0] assert isinstance(func_call, FuncCall) assert len(func_call.params) == 3 assert func_call.func_name == 'some_function' assert func_call.token.value == 'some_function' first_param = func_call.params[0] assert isinstance(first_param, BinOp) second_param = func_call.params[1] assert isinstance(second_param, String) third_param = func_call.params[2] assert isinstance(third_param, Number)
def test_parser_if_true(): text = """ if (True) { print('yo'); } """ lexer = Lexer(text) parser = Parser(lexer) block = parser.parse() if_node = block.children[0] assert isinstance(if_node, IfStatement) assert isinstance(if_node.value, Comparison) comparison = if_node.value assert comparison.left.value == True assert comparison.op is None assert comparison.right is None assert isinstance(if_node.block, Block) assert if_node.elseblock is None block_node = if_node.block assert isinstance(block_node.children[0], Print)
def main(): arg = sys.argv[1] processtime_in_ms = time.time() * 1000 with open(arg) as fs: # Generate Tokens lexer = Lexer(fs.read()) tokens = lexer.generate_tokens() # Generate AST parser = Parser(tokens) ast = parser.parse() # Global conductor instance conductor = Conductor() # Interpret AST interpreter = Interpreter(ast, conductor) interpreter.interpret() print(f"\nPROCESS TIME: {time.time() * 1000 - processtime_in_ms}ms")
def tree(text): lexer = Lexer(text) parser = Parser(lexer) tree = parser.parse() return tree
class Interpreter(QObject): interpreted = pyqtSignal(str) def __init__(self): super(Interpreter, self).__init__() self.scanner = Scanner() self.parser = Parser() self.was_retry = False def interpret(self, text: str): text = text.replace('<', '<').replace('>', '>') try: tokens, had_error = self.scanner.scan(text) except Error as err: self.print(err.__str__()) return # for token in tokens: print(token) exprs = self.parser.parse(tokens) if exprs is not None: for expr in exprs: if isinstance(expr, Expr): # print(expr.__str__()) try: ans = expr.evaluate() # TODO loaded script compatible with 'ans' self.parser.environment.vars['ans'] = ans if type(ans) is bool and not expr.mute: if ans is True: self.print("true") else: self.print("false") else: trimmed = self.trim_trailing_zero(ans) if not expr.mute: self.print(trimmed) except Error as err: self.print(err.__str__()) elif isinstance(expr, Error): print(expr.__str__()) # flexibility about unmatched ')' : allow "a = log(10" by adding a ')' at the end of the text if (expr.__str__() == "ParseError - Expect ')' after arguments." or expr.__str__() == "ParseError - Expect ')' after expression.") \ and not self.was_retry: try: self.was_retry = True self.interpret(text + ')') except Error: self.print(expr) else: self.print(expr) elif isinstance(expr, Files): loaded = expr.exec() if loaded is not None: self.interpret(loaded) # TODO correct history for loaded scripts self.was_retry = False def print(self, res): self.interpreted.emit(res.__str__()) # print(res) @staticmethod def trim_trailing_zero(text): text = str(text) if text.endswith('.0'): text = text[:text.index('.0')] return text