我在制作 lisp 方言,我有一个函数
compute
,例如 (+ 1 2 (- 2 1))
到 ('+', '1', '2', ('-', '2', '1'))
.
这是我目前的实现。
import shlex
def compute(expr):
expr = expr.replace('(', '( ').replace(')', ' )')
expr = shlex.split(expr)
new = ''
for index, i in enumerate(expr):
if i == '(': new += i
elif i == ')': new += i
elif (not(len(expr) == 1 or len(expr) == 0)) and expr[index+1] == ')':
new += ('"' + i + '"')
else:
new += ('"' + i + '",')
expr = eval(new)
return expr
这适用于所有表达式,除了使用字符串的表达式。
(
和 )
将变成 (
和 )
即使在字符串中shlex
来不拆分字符串内的空格,但我想要它以便包含引号。所以(println "Hello, world!")
应该变成('println', '"Hello, world!"')
而不是('println', 'Hello, world!')
。\"
彻底打破一切。你必须在
poxis=False
调用中使用 shlex.split()
标志,否则它会去掉双引号:
shlex.split(expr)
['(', 'println', 'Hello, world!', ')']
在哪里:
shlex.split(expr, posix=False)
['(', 'println', '"Hello, world!"', ')']
但是,这并不能完全解决问题。您将不得不修改将
"
附加到 i
的代码:
new = ''
for index, i in enumerate(expr):
if i == '(': new += i
elif i == ')': new += i
elif (not(len(expr) == 1 or len(expr) == 0)) and expr[index+1] == ')':
if i[0] == "\"" and i[-1] == "\"": # Check if i starts/ends with "
new += ('\'' + i + '\'') # Append single quote
else:
new += ('"' + i + '"') # Append double quote
else:
new += ('"' + i + '",')
现在有了所有的变化,
print(compute('(println "Hello, world!")'))
返回:
('println', '"Hello, world!"')
注意:
compute("(+ 1 2 (- 2 1))")
仍然按预期工作。