如何将命令行传入的S-expression字符串转为Python元组
如何将命令行传入的S-expression字符串转换为运算符元组
你的代码主要有两个问题导致解析失败:
- Token分割错误:直接用
split()会把(add、3)这类字符串当成单个token,没有把括号和内容分开,导致程序无法正确识别括号的位置。 - 括号处理逻辑错误:遇到
)时只固定弹出两个元素,这不符合S-expression的规则(运算符可以有多个参数),而且元组构造的顺序也不对。
正确实现步骤
- 先做正确的Token化:遍历输入字符串,把括号、运算符、数字拆分成独立的token,比如把"(add (multiply 2 3) 2)"拆成
['(', 'add', '(', 'multiply', '2', '3', ')', '2', ')']。 - 用栈处理Token流:
- 遇到
(就压入栈,标记新表达式的开始。 - 遇到数字或运算符直接压入栈。
- 遇到
)时,从栈中弹出元素,直到遇到对应的(,把弹出的元素(除了()反转后,第一个元素是运算符,后面是参数,组成元组压回栈。
- 遇到
完整代码实现
import sys def tokenize(expression_str): tokens = [] current = [] for char in expression_str: if char in '()': if current: tokens.append(''.join(current)) current = [] tokens.append(char) elif char.isspace(): if current: tokens.append(''.join(current)) current = [] else: current.append(char) if current: tokens.append(''.join(current)) return tokens def parse_sexp(tokens): stack = [] for token in tokens: if token == '(': stack.append(token) elif token == ')': # 弹出元素直到左括号 elements = [] while stack[-1] != '(': elements.append(stack.pop()) stack.pop() # 弹出左括号 # 反转元素,第一个是运算符,后面是参数 elements.reverse() if not elements: raise ValueError("空表达式无效") operator = elements[0] args = elements[1:] # 把参数转成整数(如果是数字的话) parsed_args = [] for arg in args: try: parsed_args.append(int(arg)) except ValueError: parsed_args.append(arg) stack.append((operator, *parsed_args)) else: stack.append(token) if len(stack) != 1: raise ValueError("表达式格式错误") return stack[0] def from_expression_string(expression_string): tokens = tokenize(expression_string) return parse_sexp(tokens) if __name__ == "__main__": if len(sys.argv) != 2: print("用法: python calc.py \"(add (multiply 2 3) 2)\"") sys.exit(1) expr_str = sys.argv[1] result = from_expression_string(expr_str) print(result)
测试示例
运行命令:
python calc.py "(add (multiply 2 3) 2)"
输出结果:
('add', ('multiply', 2, 3), 2)
内容的提问来源于stack exchange,提问作者Reactoo
相关产品推荐
相关产品推荐

