Last active
May 5, 2023 01:10
-
-
Save coolcoder613eb/334df5f130b831c601d17fd829e28640 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| QUOTES = '"' | |
| import operator | |
| import readline | |
| class func(str): | |
| def __init__(self, value): | |
| super().__init__() | |
| def __repr__(self): | |
| return f"func({super().__repr__()})" | |
| class lit(list): | |
| def __init__(self, value): | |
| super().__init__() | |
| def __repr__(self): | |
| return f"lit({super().__repr__()})" | |
| class Lsp: | |
| def __init__(self): | |
| self.lspvars = {} | |
| self.funcs = { | |
| "+": operator.add, | |
| "-": operator.sub, | |
| "*": operator.mul, | |
| "/": operator.truediv, | |
| "get": self.getvar, | |
| "set": self.setvar, | |
| "print": self.lspprint, | |
| "println": print, | |
| "str": str, | |
| "val": self.val, | |
| "if": self.lspif, | |
| "def": self.lspdef, | |
| "input": input, | |
| } | |
| def parse(self, expression): | |
| tokens = self.tokenize(expression) | |
| return self.parse_tokens(tokens) | |
| def tokenize(self, expression): | |
| tokens = [] | |
| current_token = "" | |
| in_string = False | |
| escaped = False | |
| quote = False | |
| for char in expression: | |
| if in_string: | |
| current_token += char | |
| if escaped: | |
| escaped = False | |
| current_token = current_token[:-1] | |
| if char == "n": | |
| current_token += "\n" | |
| elif char == "t": | |
| current_token += "\t" | |
| elif char == "a": | |
| current_token += "\a" | |
| else: | |
| current_token += char | |
| elif char == "\\": | |
| escaped = True | |
| current_token = current_token[:-1] | |
| elif char in QUOTES: | |
| in_string = False | |
| elif char in "() ": | |
| if current_token: | |
| tokens.append(current_token) | |
| current_token = "" | |
| if char != " ": | |
| if quote: | |
| quote = False | |
| tokens.append("'" + char) | |
| else: | |
| tokens.append(char) | |
| elif char == "'": | |
| quote = True | |
| elif char in QUOTES: | |
| in_string = True | |
| current_token += char | |
| else: | |
| current_token += char | |
| if current_token: | |
| tokens.append(current_token) | |
| return tokens | |
| def parse_tokens(self, tokens): | |
| stack = [[]] | |
| for token in tokens: | |
| if token == "(": | |
| stack.append([]) | |
| elif token == "'(": | |
| stack.append(lit([])) | |
| elif token == ")": | |
| sublist = stack.pop() | |
| stack[-1].append(sublist) | |
| elif token[0] == '"' and token[-1] == '"': | |
| stack[-1].append(token[1:-1].replace("\\(", "(").replace("\\)", ")")) | |
| else: | |
| try: | |
| value = int(token) | |
| except ValueError: | |
| try: | |
| value = float(token) | |
| except ValueError: | |
| if token in self.funcs: | |
| value = func(token) | |
| else: | |
| raise SyntaxError("Invalid token!") | |
| stack[-1].append(value) | |
| return stack[0][0] | |
| def lspeval(self, code, iscode=False): | |
| rtnnxt = iscode | |
| for x in code: | |
| if rtnnxt: | |
| rtnnxt = False | |
| return x | |
| elif type(x) == list: | |
| rtn = self.lspeval(x[1:]) | |
| # print(*rtn) | |
| yield self.funcs[x[0]](*rtn) | |
| else: | |
| # print(repr(x)) | |
| yield x | |
| def runtree(self, code): | |
| return self.funcs[code[0]](*self.lspeval(code[1:])) | |
| def run(self, code): | |
| return self.runtree(self.parse(code)) | |
| def setvar(self, name, value): | |
| self.lspvars.update({name: value}) | |
| def getvar(self, name): | |
| return self.lspvars[name] | |
| def lspprint(self, *args): | |
| print(*args, end="") | |
| def val(self, thing): | |
| return thing | |
| def lspif(self, cond, code): | |
| if cond: | |
| return self.runtree(code) | |
| def lspdef(self, name, *args): | |
| print(name, args) | |
| params = args[:-1] | |
| code = args[-1] | |
| def lspfunc(*args): | |
| olds = {} | |
| for x, item in enumerate(params): | |
| if item in self.lspvars: | |
| olds.update({item: self.lspvars[item]}) | |
| self.lspvars.update({item: args[x]}) | |
| rtn = self.runtree(code) | |
| for x in params: | |
| self.lspvars.pop(x) | |
| for x in olds: | |
| self.lspvars.update({x: olds[x]}) | |
| return rtn | |
| self.funcs.update({name: lspfunc}) | |
| def repl(self): | |
| try: | |
| print("lsp.py repl") | |
| while True: | |
| code = input(">") | |
| if code: | |
| result = self.run(code) | |
| if result != None: | |
| print(repr(result)) | |
| except KeyboardInterrupt: | |
| print("Exiting.") | |
| lsp = Lsp() | |
| code1 = '(print "hello\\" world")' | |
| code2 = "(print(+ (- 2 3) (* 1 7)))" | |
| test1 = lsp.parse(code1) | |
| test2 = lsp.parse(code2) | |
| # print(test1) | |
| # print(test2) | |
| # print(lsp.parse(input())) | |
| lsp.repl() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@pratikbhumkar check this out