1.思路要点

    (1)Lisp语法采用嵌套表达式,总共的命令只有两类,数值操作(add和mult)和赋值操作(let),很容易想到递归的方法解决。

    (2)假设只有数值操作,思路其实很简单,将表达式按括号一层层分开,判断当前命令是add还是mult后,直接对进行数值操作的值采用递归即可。即ans_add=add(值1)+add(值2)。分开的方式可采用标记计数,对一个按空格分开的表达式逐个字符读取,遇到一个左括号标记+1,遇到一个右括号标记-1,标记为0时返回当前读取过的所有字符。

    (3)加入赋值操作后,我们依旧将表达式分开,但在判断出当前命令是let后,我们先对当前所有变量赋值,并将赋值内容以字典形式保存在一个栈中。接着对赋值剩余的表达式进行递归即可。

    (4)由于子函数evaluate负责进行递归过程,那么在以上所有操作之前,我们需要在函数开始阶段对输入的内容进行判断,如果输入内容不是一串表达式而是一个数值或者变量,那么此时迭代已进行至底层,对数值我们直接返回,对变量,我们返回(3)中栈所储存的变量的值

2.代码分析

#生成栈,栈由字典构成,每个字典代表一个作用域
def implicit_scope(func):         
    def wrapper(*args):
        args[0].scope.append({})
        ans=func(*args)
        args[0].scope.pop()
        return ans
    return wrapper

class Solution:
    def __init__(self):
        self.scope=[{}]

    #函数装饰器,每次执行evaluate时先由implicit_scope生成对应作用域
    @implicit_scope          
    def evaluate(self, expression):
        #判断当前爹迭代是否进入底层
        if not expression.startswith('('):
            #是底层,判断是数值(-是负号)还是变量
            if expression.isdigit() or expression[0]=='-':
                #若为数值便直接输出,我们将输出统一为int方便计算
                return int(expression)
            else:
                #由于是栈,我们将scope倒着读取
                for local in reversed(self.scope):
                    if expression in local:
                        #若为变量,我们找出栈中优先级最高的value并返回
                        return local[expression]
        #将表达式分开,每次输入不包含命令,将分开的表达式转为list方便处理
        tokens =  list(self.sparse(expression[5+(expression[1]=='m'):-1]))
        if expression.startswith('(add'):
            return self.evaluate(tokens[0])+self.evaluate(tokens[1])
        elif expression.startswith('(mult'):
            return self.evaluate(tokens[0])*self.evaluate(tokens[1])
        #命令为let,假设此时token为[‘x’,‘2’,‘y’,‘3’,‘XXX’],令x=2,y=3作为字典入栈
        else:
            lentoken = len(tokens)
            for index in range(0, lentoken-1, 2):
                self.scope[-1][tokens[index]]=self.evaluate(tokens[index+1])
            return self.evaluate(tokens[-1])
    def sparse(self,expression):
        tokens=expression.split()
        mark=0
        buffer=[]
        for token in tokens:
            buffer.append(token)
            mark+=token.count('(')-token.count(')')
            if mark==0:
                #标记为0返回,我们采用生成器的方法将当前级别表达式(或者说当前括号内)的结果返回
                yield " ".join(buffer)
                #记得将buffer清空
                buffer=[]
expression="(let x 7 -12)"
test=Solution()
ans=test.evaluate(expression)
print(ans)

    代码参考:

Leetcode

    链接:


https://leetcode-cn.com/problems/parse-lisp-expression/solution/lisp-yu-fa-jie-xi-by-leetcode/