gpt4 book ai didi

python - python中的小语言

转载 作者:太空狗 更新时间:2023-10-29 22:14:08 26 4
gpt4 key购买 nike

我正在用python编写甚至不被称为语言的内容。我目前有几个运算符:+-*^fac@!!fac计算阶乘,@返回变量的值,!!设置变量。代码如下。我将如何编写一种使用这种简单语言定义函数的方法?

编辑:我更新了代码!

import sys, shlex, readline, os, string
List, assign, call, add, sub, div, Pow, mul, mod, fac, duf, read,\
kill, clr, STO, RET, fib, curs = {}, "set", "get", "+", "-", "/", "^", "*",\
"%", "fact", "func", "read", "kill", "clear", ">", "@", "fib", "vars"
def fact(num):
if num == 1: return 1
else: return num*fact(num-1)
def Simp(op, num2, num1):
global List
try: num1, num2 = float(num1), float(num2)
except:
try: num1 = float(num1)
except:
try: num2 = float(num2)
except: pass
if op == mul: return num1*num2
elif op == div: return num1/num2
elif op == sub: return num1-num2
elif op == add: return num1+num2
elif op == Pow: return num1**num2
elif op == assign: List[num1] = num2; return "ok"
elif op == call: return List[num1]
elif op == fac: return fact(num1)
elif op == duf: return "%s %s %s"%(duf, num1, num2)
elif op == mod: return num1%num2
elif op == kill: del List[num1]; return "ok"
elif op == clr: os.system("clear")
elif op == STO: List[num2] = num1; return "ok"
elif op == RET: return List[num1]
elif op == curs: return List
elif op == read: List[num1] = Eval(raw_input("%s "%num1)); return "ok"
def Eval(expr):
ops = "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s"%(mul, add, sub, div, Pow, assign, call, fac, duf, mod, read, kill, clr, STO, RET, curs)
stack, expr, ops = [], shlex.split(string.lower(expr)), ops.split()
for i in expr:
if i[0] != ';':
if i not in ops: stack.append(i)
elif i in ops: stack.append(Simp(i, stack.pop(), stack.pop()))
else: stack.append("ok")
return stack[0]
def shell():
try:
x = ""
while x != "quit":
x = raw_input("star> ")
try: l = Eval(x)
except KeyError: l = "does not exist"
except: l = "parse error!"
if l != None: print " =>",l,"\n"
except (EOFError, KeyboardInterrupt): print
if len(sys.argv) > 1:
x = open(sys.argv[1], 'r'); l = x.readlines(); x.close()
for i in l:
if i[0] != ";":
i = ' '.join(i.split())
x = Eval(i)
if x != None: print i,"\n =>",x,"\n"
else: pass
shell()
else: shell()

最佳答案

您的程序非常困惑,需要对其进行修复,然后才能对其进行修改以支持定义函数。我将分几个步骤进行操作,并在完成操作后将它们添加到答案中。这个答案将变得很长。

另外,您显然还没有决定您的语言定义应该是什么。您已经决定使您的语言定义跟上您的实现技术,这有点破损,并且会带来很多痛苦。

首先,您的Simp函数的定义确实被破坏了。它要求所有东西都从栈中取出两个值,然后再放一个值。这已破了。阶乘函数无法以这种方式工作,Fibonacci函数也无法运行,因此您被迫拥有从未使用过的“虚拟”参数。同样,诸如分配给全局列表或字典中的元素之类的事情也没有理由将值压入堆栈,因此您只需要按“ok”即可。这是坏的,需要修复。

这是已解决此问题的版本。注意,我已经将Simp重命名为builtin_op,以更准确地反射(reflect)其目的:

import sys, shlex, readline, os, string
List, assign, call, add, sub, div, Pow, mul, mod, fac, duf, read,\
kill, clr, STO, RET, fib, curs = {}, "set", "get", "+", "-", "/", "^", "*",\
"%", "fact", "func", "read", "kill", "clear", ">", "@", "fib", "vars"
def fact(num):
if num == 1: return 1
else: return num*fact(num-1)
def builtin_op(op, stack):
global List
if op == mul: stack.append(float(stack.pop())*float(stack.pop()))
elif op == div: stack.append(float(stack.pop())/float(stack.pop()))
elif op == sub: stack.append(float(stack.pop())-float(stack.pop()))
elif op == add: stack.append(float(stack.pop())+float(stack.pop()))
elif op == Pow: stack.append(float(stack.pop())**float(stack.pop()))
elif op == assign: val = List[stack.pop()] = stack.pop(); stack.append(val)
elif op == call: stack.append(List[stack.pop()])
elif op == fac: stack.append(fact(stack.pop()))
elif op == duf: stack.append("%s %s %s" % (duf, stack.pop(), stack.pop()))
elif op == mod: stack.append(float(stack.pop())%float(stack.pop()))
elif op == kill: del List[stack.pop()]
elif op == clr: os.system("clear")
elif op == STO: val = List[stack.pop()] = stack.pop(); stack.append(val)
elif op == RET: stack.append(List[stack.pop()])
elif op == curs: stack.append(List)
elif op == read: prompt = stack.pop(); List[prompt] = Eval(raw_input("%s "%prompt)); stack.append(List[prompt])
def Eval(expr):
ops = "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s"%(mul, add, sub, div, Pow, assign, call, fac, duf, mod, read, kill, clr, STO, RET, curs)
stack, expr, ops = [], shlex.split(string.lower(expr)), ops.split()
for i in expr:
if i[0] != ';':
if i not in ops: stack.append(i)
elif i in ops: builtin_op(i, stack)
else: stack.append("ok")
return stack[0]
def shell():
try:
x = ""
while x != "quit":
x = raw_input("star> ")
try: l = Eval(x)
except KeyError: l = "does not exist"
except: l = "parse error!"
if l != None: print " =>",l,"\n"
except (EOFError, KeyboardInterrupt): print
if len(sys.argv) > 1:
x = open(sys.argv[1], 'r'); l = x.readlines(); x.close()
for i in l:
if i[0] != ";":
i = ' '.join(i.split())
x = Eval(i)
if x != None: print i,"\n =>",x,"\n"
else: pass
shell()
else: shell()

此处仍然存在许多 Unresolved 问题,我不会在任何将来的版本中修复。例如,有可能堆栈中的值不能解释为浮点数。这将导致异常,并且可能在从堆栈中读取另一个值之前引发此异常。这意味着,如果在堆栈上有错误的“类型”,则在“解析错误”之后,堆栈可能处于歧义状态。通常,您希望避免使用某种语言出现这种情况。

定义功能是一个有趣的问题。用您的语言,评估是立竿见影的。您没有将评估延迟到以后的机制。但是,您正在使用 shlex模块进行解析。它可以说一整组字符(包括空格等)是一个实体的一部分。这为我们提供了一种快速简便的方法来实现功能。您可以执行以下操作:
star>   "3 +" add3 func

创建您的函数,并:
star>   2 add3 get

称呼它。我使用了 get,因为这是您在程序中分配给 call的代码。

唯一的问题是该函数将需要访问堆栈的当前状态才能工作。您可以轻松地将函数的字符串反馈回 Eval,但是每次调用 Eval时,总会创建一个全新的堆栈。为了实现功能,需要对此进行修复。因此,我在 stack函数中添加了默认的 Eval参数。如果将此参数保留为其默认值,则 Eval仍将像以前一样创建一个新堆栈。但是,如果传入了现有堆栈,则 Eval将使用它。

这是修改后的代码:
import sys, shlex, readline, os, string
List, assign, call, add, sub, div, Pow, mul, mod, fac, duf, read,\
kill, clr, STO, RET, fib, curs = {}, "set", "get", "+", "-", "/", "^", "*",\
"%", "fact", "func", "read", "kill", "clear", ">", "@", "fib", "vars"
funcdict = {}
def fact(num):
if num == 1: return 1
else: return num*fact(num-1)
def builtin_op(op, stack):
global List
global funcdict
if op == mul: stack.append(float(stack.pop())*float(stack.pop()))
elif op == div: stack.append(float(stack.pop())/float(stack.pop()))
elif op == sub: stack.append(float(stack.pop())-float(stack.pop()))
elif op == add: stack.append(float(stack.pop())+float(stack.pop()))
elif op == Pow: stack.append(float(stack.pop())**float(stack.pop()))
elif op == assign: val = List[stack.pop()] = stack.pop(); stack.append(val)
elif op == call: Eval(funcdict[stack.pop()], stack)
elif op == fac: stack.append(fact(stack.pop()))
elif op == duf: name = stack.pop(); funcdict[name] = stack.pop(); stack.append(name)
elif op == mod: stack.append(float(stack.pop())%float(stack.pop()))
elif op == kill: del List[stack.pop()]
elif op == clr: os.system("clear")
elif op == STO: val = List[stack.pop()] = stack.pop(); stack.append(val)
elif op == RET: stack.append(List[stack.pop()])
elif op == curs: stack.append(List)
elif op == read: prompt = stack.pop(); List[prompt] = Eval(raw_input("%s "%prompt)); stack.append(List[prompt])
def Eval(expr, stack=None):
ops = "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s"%(mul, add, sub, div, Pow, assign, call, fac, duf, mod, read, kill, clr, STO, RET, curs)
if stack is None:
stack = []
expr, ops = shlex.split(string.lower(expr)), ops.split()
for i in expr:
if i[0] != ';':
if i not in ops: stack.append(i)
elif i in ops: builtin_op(i, stack)
else: stack.append("ok")
return stack[0]
def shell():
try:
x = ""
while x != "quit":
x = raw_input("star> ")
try: l = Eval(x)
except KeyError: l = "does not exist"
except: l = "parse error!"
if l != None: print " =>",l,"\n"
except (EOFError, KeyboardInterrupt): print
if len(sys.argv) > 1:
x = open(sys.argv[1], 'r'); l = x.readlines(); x.close()
for i in l:
if i[0] != ";":
i = ' '.join(i.split())
x = Eval(i)
if x != None: print i,"\n =>",x,"\n"
else: pass
shell()
else: shell()

在基于堆栈的语言中, dupswap是两个非常有用的内置运算符。 dup采用顶部堆栈元素并将其复制。 swap交换前两个堆栈元素。

如果您有 dup,则可以实现 square函数,如下所示:
star>   "dup *" square func

这是已实现 dupswap的程序:
import sys, shlex, readline, os, string
List, assign, call, add, sub, div, Pow, mul, mod, fac, duf, read,\
kill, clr, STO, RET, fib, curs, dup, swap = {}, "set", "get", "+", "-", "/", "^", "*",\
"%", "fact", "func", "read", "kill", "clear", ">", "@", "fib", "vars", "dup", "swap"
funcdict = {}
def fact(num):
if num == 1: return 1
else: return num*fact(num-1)
def builtin_op(op, stack):
global List
global funcdict
if op == mul: stack.append(float(stack.pop())*float(stack.pop()))
elif op == div: stack.append(float(stack.pop())/float(stack.pop()))
elif op == sub: stack.append(float(stack.pop())-float(stack.pop()))
elif op == add: stack.append(float(stack.pop())+float(stack.pop()))
elif op == Pow: stack.append(float(stack.pop())**float(stack.pop()))
elif op == assign: val = List[stack.pop()] = stack.pop(); stack.append(val)
elif op == call: Eval(funcdict[stack.pop()], stack)
elif op == fac: stack.append(fact(stack.pop()))
elif op == duf: name = stack.pop(); funcdict[name] = stack.pop(); stack.append(name)
elif op == mod: stack.append(float(stack.pop())%float(stack.pop()))
elif op == kill: del List[stack.pop()]
elif op == clr: os.system("clear")
elif op == STO: val = List[stack.pop()] = stack.pop(); stack.append(val)
elif op == RET: stack.append(List[stack.pop()])
elif op == curs: stack.append(List)
elif op == dup: val = stack.pop(); stack.append(val); stack.append(val)
elif op == swap: val1 = stack.pop(); val2 = stack.pop(); stack.append(val1); stack.append(val2)
elif op == read: prompt = stack.pop(); List[prompt] = Eval(raw_input("%s "%prompt)); stack.append(List[prompt])
def Eval(expr, stack=None):
ops = "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s"%(mul, add, sub, div, Pow, assign, call, fac, duf, mod, read, kill, clr, STO, RET, curs, dup, swap)
if stack is None:
stack = []
expr, ops = shlex.split(string.lower(expr)), ops.split()
for i in expr:
if i[0] != ';':
if i not in ops: stack.append(i)
elif i in ops: builtin_op(i, stack)
else: stack.append("ok")
return stack[0]
def shell():
try:
x = ""
while x != "quit":
x = raw_input("star> ")
try: l = Eval(x)
except KeyError: l = "does not exist"
except: l = "parse error!"
if l != None: print " =>",l,"\n"
except (EOFError, KeyboardInterrupt): print
if len(sys.argv) > 1:
x = open(sys.argv[1], 'r'); l = x.readlines(); x.close()
for i in l:
if i[0] != ";":
i = ' '.join(i.split())
x = Eval(i)
if x != None: print i,"\n =>",x,"\n"
else: pass
shell()
else: shell()

最后,这是我使用Python编写的版本,比我编写的Python还要清晰得多(无论如何,我认为):
import shlex, functools, sys, StringIO

def bin_numeric_op(func):
@functools.wraps(func)
def execute(self):
n2, n1 = self._stack.pop(), self._stack.pop()
n1 = float(n1)
n2 = float(n2)
self._stack.append(func(n1, n2))
return execute

def relational_op(func):
@functools.wraps(func)
def execute(self):
n2, n1 = self._stack.pop(), self._stack.pop()
self._stack.append(bool(func(n1, n2)))
return execute

def bin_bool_op(func):
@functools.wraps(func)
def execute(self):
n2, n1 = self._stack.pop(), self._stack.pop()
n1 = bool(n1)
n2 = bool(n2)
self._stack.append(bool(func(n1, n2)))
return execute

class Interpreter(object):
def __init__(self):
self._stack = []
self._vars = {}
self._squarestack = []

def processToken(self, token):
if token == '[':
self._squarestack.append(len(self._stack))
# Currently inside square brackets, don't execute
elif len(self._squarestack) > 0:
if token == ']':
startlist = self._squarestack.pop()
lst = self._stack[startlist:]
self._stack[startlist:] = [tuple(lst)]
else:
self._stack.append(token)
# Not current inside list and close square token, something's wrong.
elif token == ']':
raise ValueError("Unmatched ']'")
elif token in self.builtin_ops:
self.builtin_ops[token](self)
else:
self._stack.append(token)
def get_stack(self):
return self._stack
def get_vars(self):
return self._vars
@bin_numeric_op
def add(n1, n2):
return n1 + n2
@bin_numeric_op
def mul(n1, n2):
return n1 * n2
@bin_numeric_op
def div(n1, n2):
return n1 / n2
@bin_numeric_op
def sub(n1, n2):
return n1 - n2
@bin_numeric_op
def mod(n1, n2):
return n1 % n2
@bin_numeric_op
def Pow(n1, n2):
return n1**n2
@relational_op
def less(v1, v2):
return v1 < v2
@relational_op
def lesseq(v1, v2):
return v1 <= v2
@relational_op
def greater(v1, v2):
return v1 > v2
@relational_op
def greatereq(v1, v2):
return v1 > v2
@relational_op
def isequal(v1, v2):
return v1 == v2
@relational_op
def isnotequal(v1, v2):
return v1 != v2
@bin_bool_op
def bool_and(v1, v2):
return v1 and v2
@bin_bool_op
def bool_or(v1, v2):
return v1 or v2
def bool_not(self):
stack = self._stack
v1 = stack.pop()
stack.append(not v1)
def if_func(self):
stack = self._stack
pred = stack.pop()
code = stack.pop()
if pred:
self.run(code)
def ifelse_func(self):
stack = self._stack
pred = stack.pop()
nocode = stack.pop()
yescode = stack.pop()
code = yescode if pred else nocode
self.run(code)
def store(self):
stack = self._stack
value = stack.pop()
varname = stack.pop()
self._vars[varname] = value
def fetch(self):
stack = self._stack
varname = stack.pop()
stack.append(self._vars[varname])
def remove(self):
varname = self._stack.pop()
del self._vars[varname]
# The default argument is because this is used internally as well.
def run(self, code=None):
if code is None:
code = self._stack.pop()
for tok in code:
self.processToken(tok)
def dup(self):
self._stack.append(self._stack[-1])
def swap(self):
self._stack[-2:] = self._stack[-1:-3:-1]
def pop(self):
self._stack.pop()
def showstack(self):
print"%r" % (self._stack,)
def showvars(self):
print "%r" % (self._vars,)
builtin_ops = {
'+': add,
'*': mul,
'/': div,
'-': sub,
'%': mod,
'^': Pow,
'<': less,
'<=': lesseq,
'>': greater,
'>=': greatereq,
'==': isequal,
'!=': isnotequal,
'&&': bool_and,
'||': bool_or,
'not': bool_not,
'if': if_func,
'ifelse': ifelse_func,
'!': store,
'@': fetch,
'del': remove,
'call': run,
'dup': dup,
'swap': swap,
'pop': pop,
'stack': showstack,
'vars': showvars
}

def shell(interp):
try:
while True:
x = raw_input("star> ")
msg = None
try:
interp.run(shlex.split(x))
except KeyError:
msg = "does not exist"
except:
sys.excepthook(*sys.exc_info())
msg = "parse error!"
if msg != None:
print " =>",msg,"\n"
else:
print " => %r\n" % (interp.get_stack(),)
except (EOFError, KeyboardInterrupt):
print

interp = Interpreter()
if len(sys.argv) > 1:
lex = shlex.shlex(open(sys.argv[1], 'r'), sys.argv[1])
tok = shlex.get_token()
while tok is not None:
interp.processToken(tok)
tok = lex.get_token()
shell(interp)

此新版本支持 ififelse语句。通过this和function调用,可以用该语言实现 fibfact函数。稍后我将添加您如何定义它们。

这是定义 fib函数的方式:
star>   fib [ dup [ pop 1 0 + ] swap [ dup 1 - fib @ call swap 2 - fib @ call + ] swap 0 + 2 0 + < ifelse ] !
=> []

star> 15 fib @ call
=> [987.0]
0 + 2 0 +之前的 <序列将强制比较为数字比较。

还要注意 []单个字符是如何用引号引起来的。它们导致它们之间的所有内容都不会执行,而是作为单个项目列表存储在堆栈中。这是定义功能的关键。函数是可以使用 call运算符执行的一系列标记的序列。它们也可以用于“匿名块”,它们是 lambda表达式和标准Python块之间的交叉。这些在 fib函数中用于 ifelse语句的两个可能路径。

解析器非常简单。 shlex作为这种简单语言的词法分析器足够强大。其他项目将从列表中获取单个项目。创建仅由先前列表的一部分组成的新列表。 “列出”堆栈中的单个 token 。 while原语的实现。对整数进行运算的数值运算符(实际上,在Forth中,默认情况下,数值运算对整数进行运算,您需要指定诸如 +.之类的内容才能获取浮点版本)。还有一些对符号 token 的允许字符串操作的操作。也许将 token 转换为字符的单个 token 列表或将列表合并为单个 token 的“拆分”和“连接”操作就足够了。

关于python - python中的小语言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6338440/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com