- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在用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()
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()
dup
和
swap
是两个非常有用的内置运算符。
dup
采用顶部堆栈元素并将其复制。
swap
交换前两个堆栈元素。
dup
,则可以实现
square
函数,如下所示:
star> "dup *" square func
dup
和
swap
的程序:
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()
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)
if
和
ifelse
语句。通过this和function调用,可以用该语言实现
fib
和
fact
函数。稍后我将添加您如何定义它们。
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/
至少在某些 ML 系列语言中,您可以定义可以执行模式匹配的记录,例如http://learnyouahaskell.com/making-our-own-types-and-typeclasses -
这可能是其他人已经看到的一个问题,但我正在尝试寻找一种专为(或支持)并发编程而设计的语言,该语言可以在 .net 平台上运行。 我一直在 erlang 中进行辅助开发,以了解该语言,并且喜欢建立一个稳
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be
我正在寻找一种进程间通信工具,可以在相同或不同系统上运行的语言和/或环境之间使用。例如,它应该允许在 Java、C# 和/或 C++ 组件之间发送信号,并且还应该支持某种排队机制。唯一明显与环境和语言
我有一些以不同语言返回的文本。现在,客户端返回的文本格式为(en-us,又名美国英语): Stuff here to keep. -- Delete Here -- all of this below
问题:我希望在 R 中找到类似 findInterval 的函数,它为输入提供一个标量和一个表示区间起点的向量,并返回标量落入的区间的索引。例如在 R 中: findInterval(x = 2.6,
我是安卓新手。我正在尝试进行简单的登录 Activity ,但当我单击“登录”按钮时出现运行时错误。我认为我没有正确获取数据。我已经检查过,SQLite 中有一个与该 PK 相对应的数据。 日志猫。
大家好,感谢您帮助我。 我用 C# 制作了这个计算器,但遇到了一个问题。 当我添加像 5+5+5 这样的东西时,它给了我正确的结果,但是当我想减去两个以上的数字并且还想除或乘以两个以上的数字时,我没有
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 4 年前。 Improve th
这就是我所拥有的 #include #include void print(int a[], int size); void sort (int a[], int size); v
你好,我正在寻找我哪里做错了? #include #include int main(int argc, char *argv[]) { int account_on_the_ban
嘿,当我开始向数组输入数据时,我的代码崩溃了。该程序应该将数字读入数组,然后将新数字插入数组中,最后按升序排列所有内容。我不确定它出了什么问题。有人有建议吗? 这是我的代码 #include #in
我已经盯着这个问题好几个星期了,但我一无所获!它不起作用,我知道那么多,但我不知道为什么或出了什么问题。我确实知道开发人员针对我突出显示的行吐出了“错误:预期表达式”,但这实际上只是冰山一角。如果有人
我正在编写一个点对点聊天程序。在此程序中,客户端和服务器功能写入一个唯一的文件中。首先我想问一下我程序中的机制是否正确? I fork() two processes, one for client
基本上我需要找到一种方法来发现段落是否以句点 (.) 结束。 此时我已经可以计算给定文本的段落数,但我没有想出任何东西来检查它是否在句点内结束。 任何帮助都会帮助我,谢谢 char ch; FI
我的函数 save_words 接收 Armazena 和大小。 Armazena 是一个包含段落的动态数组,size 是数组的大小。在这个函数中,我想将单词放入其他称为单词的动态数组中。当我运行它时
我有一个结构 struct Human { char *name; struct location *location; int
我正在尝试缩进以下代码的字符串输出,但由于某种原因,我的变量不断从文件中提取,并且具有不同长度的噪声或空间(我不确定)。 这是我的代码: #include #include int main (v
我想让用户选择一个选项。所以我声明了一个名为 Choice 的变量,我希望它输入一个只能是 'M' 的 char 、'C'、'O' 或 'P'。 这是我的代码: char Choice; printf
我正在寻找一种解决方案,将定义和变量的值连接到数组中。我已经尝试过像这样使用 memcpy 但它不起作用: #define ADDRESS {0x00, 0x00, 0x00, 0x00, 0x0
我是一名优秀的程序员,十分优秀!