commit 9b1ff4c361a94f21848f40ac32d96f95cbb5b04e Author: Micke Nordin Date: Tue Jun 7 12:01:39 2022 +0200 Start of minion programming language The lexer can tokenize: * variable declarations * assignment to variables * function declarations * function calls * while loop * if statement minion is strongly typed and all variables MUST have a type declarations diff --git a/lexer.py b/lexer.py new file mode 100755 index 0000000..57496a2 --- /dev/null +++ b/lexer.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +import json + +def find(needle: str, haystack: str) -> bool: + return haystack.find(needle) != -1 + +source: list = list() +with open('./prog.mn', '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): + 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() + 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): + 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): + split_on_lparen = line.split('(') + name = split_on_lparen[0].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) + else: + loop = {"variant": "loop", "value": name, "condition": ','.join(params), "line_number": lineno} + tokens.append(loop) + else: + if line.strip() == '{': + expression = {"variant": "start_block", "value": '{', "line_number": lineno} + tokens.append(expression) + elif line != "": + error = {"variant": "syntax_error", "line": line, "line_number": lineno} + tokens.append(error) +print(json.dumps(tokens)) + + + diff --git a/prog.mn b/prog.mn new file mode 100644 index 0000000..3211eb7 --- /dev/null +++ b/prog.mn @@ -0,0 +1,27 @@ +float: x = 10.1 + +func: hello(float: x) = { + stdout: out = x * 10 +} + +{ + str: name + int: var = 1 + name = hej hopp +} + + +hello(x) + +func: good_bye(void: none) = int: getout = 0 + +good_bye() + +if (x ? 1) { + hello(x) +} + +while (x < 1) { + x = x -1 + hello(x) +}