Skip to content

Instantly share code, notes, and snippets.

@coolcoder613eb
Last active May 5, 2023 01:10
Show Gist options
  • Save coolcoder613eb/334df5f130b831c601d17fd829e28640 to your computer and use it in GitHub Desktop.
Save coolcoder613eb/334df5f130b831c601d17fd829e28640 to your computer and use it in GitHub Desktop.
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()
@coolcoder613eb
Copy link
Author

@pratikbhumkar check this out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment