#!/usr/bin/env python3 import json import sys def find(needle: str, haystack: str) -> bool: return haystack.find(needle) != -1 def parse_lparen(line: str) -> list: tokens = list() split_on_lparen = line.split('(') name = split_on_lparen[0].strip() if find('=', line): name = name.split('=')[1].strip() without_name = '('.join(split_on_lparen[1:]) split_on_rparen = without_name.split(')') params_str = ')'.join(split_on_rparen[:-1]) params = list(map(str.strip,params_str.split(','))) if name not in ['if', 'while']: function_call = {"variant": "function_call", "value": name, "params": params, "line_number": lineno} tokens.append(function_call) elif name == "if": conditional = {"variant": "conditional", "value": name, "condition": ','.join(params), "line_number": lineno} tokens.append(conditional) expression = {"variant": "start_block", "value": "{", "line_number": lineno} tokens.append(expression) else: loop = {"variant": "loop", "value": name, "condition": ','.join(params), "line_number": lineno} tokens.append(loop) expression = {"variant": "start_block", "value": "{", "line_number": lineno} tokens.append(expression) return tokens source: list = list() program = './prog.mn' if len(sys.argv) > 1: program = sys.argv[1] with open(program, 'r') as prog: source = prog.readlines() num_lines = len(source) tokens = list() for lineno in range(1, num_lines + 1): line = source[lineno - 1].strip('\n') split_on_colon = line.split(':') colon_lhs = split_on_colon[0] split_on_equals = line.split('=') equals_lhs = split_on_equals[0] if find(':', line): colon_rhs = ':'.join(split_on_colon[1:]) colon_rhs_split_on_equals = colon_rhs.split('=') colon_equals_lhs = colon_rhs_split_on_equals[0] type = {"variant": "type", "value": colon_lhs.strip(), "line_number": lineno} tokens.append(type) operator = {"variant": "operator", "value": ':', "line_number": lineno} tokens.append(operator) signifier = {"variant": "signifier", "value": colon_equals_lhs.strip(), "line_number": lineno} if colon_lhs.strip() == 'func': split_on_lparen = colon_equals_lhs.strip().split('(') name = split_on_lparen[0] raw_params = list(map(str.strip,'('.join(split_on_lparen[1:]).split(','))) params = list() for raw in raw_params: raw_split_on_colon = raw.split(':') raw_split_on_rparen = raw_split_on_colon[1].split(')') ptype = raw_split_on_colon[0].strip() pname = raw_split_on_rparen[0].strip() params.append({"type": ptype, "name": pname}) signifier = {"variant": "function_declaration", "value": name, "params": params, "line_number": lineno} tokens.append(signifier) if find('=', line): expressions = list() colon_equals_rhs = '='.join(colon_rhs_split_on_equals[1:]) operator = {"variant": "operator", "value": '=', "line_number": lineno} tokens.append(operator) expr = colon_equals_rhs.strip() expressions.append({"variant": "expression", "value": expr, "line_number": lineno}) if expr == '{': expressions[0] = {"variant": "start_block", "value": expr, "line_number": lineno} elif find('(', line) and find(')', line): expressions = parse_lparen(line) for expression in expressions: tokens.append(expression) elif find('=', line): equals_rhs = '='.join(split_on_equals[1:]) signifier = {"variant": "signifier", "value": equals_lhs.strip(), "line_number": lineno} tokens.append(signifier) operator = {"variant": "operator", "value": '=', "line_number": lineno} tokens.append(operator) expr = equals_rhs.strip() expression = {"variant": "expression", "value": expr, "line_number": lineno} if expr == '{': expression = {"variant": "start_block", "value": expr, "line_number": lineno} tokens.append(expression) elif find('}',line): expression = {"variant": "end_block", "value": '}', "line_number": lineno} tokens.append(expression) elif find('(', line): for expression in parse_lparen(line): tokens.append(expression) elif find('return', line): rhs = line.strip().split()[1] expression = {"variant": "return", "value": rhs, "line_number": lineno} tokens.append(expression) else: if line.strip() == '{': expression = {"variant": "start_block", "value": '{', "line_number": lineno} tokens.append(expression) elif line != "": error = {"variant": "syntax_error", "value": line, "line_number": lineno} tokens.append(error) print(json.dumps(tokens))