整段源码跑出什么
按模型,compile_run(["set x = 1 + 2", "print x * 10"]) 交回什么?
贯穿本节的小语言(判题机没 gcc,这是它的确定模型,见 spine.py):每行一条语句——set 名 = 表达式 或 print 表达式;表达式是空格分隔的 token,从左到右求值(无优先级),数字 token 当值、名字到环境里查(没有当 0)。
parse 把一行变成 AST 元组:set 行 ("set", 名, 表达式tokens),print 行 ("print", None, 表达式tokens);prog 是这些元组的列表。
端到端:parse_all 逐行 parse,valid 查语义是否 OK,compile_run 从源码跑到输出(不合法交回 ["ERROR"]),result=最后一次 print 的值。
def parse(line):
t = line.split()
if t[0] == "set":
return ("set", t[1], t[3:])
return ("print", None, t[1:])
def val(tok, env):
if tok.lstrip("-").isdigit():
return int(tok)
return env.get(tok, 0)
def eval_expr(tokens, env):
acc = val(tokens[0], env)
i = 1
while i + 1 < len(tokens):
op = tokens[i]
rhs = val(tokens[i + 1], env)
acc = acc + rhs if op == "+" else (acc - rhs if op == "-" else acc * rhs)
i += 2
return acc
def parse_all(lines):
"""把每行源码都 parse 成 AST。"""
return [parse(l) for l in lines]
def n_stmts(lines):
"""源码一共几条语句(几行)。"""
return len(lines)
def valid(lines):
"""整段源码语义 OK 吗:用到的变量都先 set 定义过。"""
prog = parse_all(lines)
d = set(n[1] for n in prog if n[0] == "set")
for n in prog:
for t in n[2]:
if not t.lstrip("-").isdigit() and t not in ("+", "-", "*") and t not in d:
return False
return True
def compile_run(lines):
"""从源码到运行:不合法交回 ["ERROR"],否则交回 print 输出列表。"""
if not valid(lines):
return ["ERROR"]
env = {}
out = []
for n in parse_all(lines):
if n[0] == "set":
env[n[1]] = eval_expr(n[2], env)
else:
out.append(eval_expr(n[2], env))
return out
def result(lines):
"""端到端跑完,最后一次 print 的值。"""
o = compile_run(lines)
return o[-1] if o else None
print(compile_run(["set x = 1 + 2", "print x * 10"]))
全部评论