我的任务是在python中创建一个程序,解释用post-fix表示法编写的Scheme。现在我正试图解释“反向计划”程序
(abs ((n) (0 n ((n 0 >) + - if)) lambda) define)
(f ((n) (n 2 *) lambda) define)
((2 f) abs)
是
(define abs (lambda (n) ((if (> n 0) + - ) 0 n )))
(define f (lambda (n) (* n 2 )))
(abs (f 2))
在“常规”计划中。
为了处理代码中的lambda函数,我首先解析parseLambda函数中的代码,如果找到任何代码,我将函数打包成一个对象并将其放回输入字符串中,其中整个程序在evaluateExpression中进行评估。
该程序似乎正在将“abs”函数和“f”函数正确地放在它们各自的单个对象中,而evaluateExpression似乎正确地定义了f和abs,但是第一次调用f时,它执行反而是abs功能。我几乎可以肯定这个问题与行
有关inputList.insert(i - j, lambda *x: evaluateExpression(lambdaFunctionList, functionList, localVariableList, *x))
行,问题与指针有某种关系。
知道可能导致这个问题的原因是什么?
import fileinput
import re
import string
def parseLambda (inputList, functionList): # position is the spot in inputList right before 'lambda', takes the lambda function out and replaces it with a named version of itself.
i = -1
while (i < len(inputList) - 1 ): # i will stop at the point where the lambda function is, remove the lambda keyword, the lambda function, and all its variables, and replace with an object that's a lambda function.
i = i + 1
if inputList[i] == 'lambda':
lambdaFunctionList = []
j = -1
balancedParen = 0
inputToken = ""
while (inputToken != '(' or balancedParen != 0):
j = j + 1
inputToken = inputList.pop(i - j)
if (inputToken == ')'):
balancedParen = balancedParen + 1
if (inputToken == '('):
balancedParen = balancedParen - 1
if (inputToken != 'lambda'):
lambdaFunctionList.insert(0, inputToken)
inputList.pop(i - j) # gets extra parentheses out
inputToken = ""
localVariableList = []
while (inputToken != '('):
j = j + 1
inputToken = inputList.pop(i - j)
if (inputToken != '(' and inputToken != ')' and inputToken != ','):
localVariableList.append(inputToken)
j = j + 1 # gets extra parentheses out
inputList.pop(i - j)
inputList.insert(i - j, lambda *x: evaluateExpression(lambdaFunctionList, functionList, localVariableList, *x))
i = i - j
def evaluateExpression(inputList, functionList, localVariableList, localVariableValues):
counter = 0
for i in localVariableList:
if (isinstance(localVariableValues, list)):
functionList['define'](localVariableValues[counter],i)
else:
functionList['define'](localVariableValues,i)
counter = counter + 1
parameterList = []
while (len(inputList) != 0):
inputValue = inputList.pop()
if inputValue == '(':
break
elif inputValue == ')':
valueToAdd = evaluateExpression(inputList, functionList, localVariableList, localVariableValues)
if valueToAdd != None:
parameterList.append(valueToAdd)
else:
parameterList.append(inputValue)
functionName = ""
functionName = parameterList.pop(0)
parameterList2 = []
for i in parameterList:
if not (isinstance(i, list)) and functionName != 'if' and i in functionList:
parameterList2.append(functionList[i])
else:
parameterList2.append(i)
else:
if functionName in functionList:
return functionList[functionName](*parameterList2)
elif len(parameterList2) > 1:
return parameterList2
else:
return functionName
#main method
schemeProgram = ""
for line in open("SchemeProgram.txt"):#Open input from a file
schemeProgram = line + schemeProgram
schemeProgram = re.sub('\(', ' ( ', schemeProgram)# replace all ( and ) with " ( " and " ) " to make space-delimited parsing possible.
schemeProgram = re.sub('\)', ' ) ', schemeProgram)
# Construct the dictionary of base functions, which will be passed into the program evaluator.
functionList = {}
functionList['+'] = lambda x, y: int(y) + int(x) # + function
functionList['-'] = lambda x, y: int(y) - int(x) # - function
functionList['*'] = lambda x, y: int(y) * int(x) # * function
functionList['/'] = lambda x, y: int(y) / int(x) # / function
functionList['define'] = lambda x, y: defineCallBack(y, x)
def defineCallBack (x, y):
functionList[str(x)] = y
functionList['if'] = lambda x, y, z: y if z else x
functionList['<'] = lambda x, y: True if (y < x) else False
functionList['>'] = lambda x, y: True if (y > x) else False
inputList = schemeProgram.split()
parseLambda(inputList, functionList)# Remove all lambda functions and replace them with the value in functionList.
print evaluateExpression(inputList, functionList, [], [])
fileinput.close()