如何为面向Scratch转码初学者的自制迷你语言实现if()函数
为Scratch转文本编程的迷你语言实现无lambda的if()函数
针对这个需求,我们可以设计类Scratch风格的if()语法,让用户通过if(条件, 执行语句)的形式调用,完全不需要lambda。下面是具体的修改方案和代码:
1. 扩展词法分析器(lex函数)
首先要让词法分析器能识别if关键字、括号()和逗号,,才能解析if(...)结构:
operators = ['+', '-', '*', '/'] var_assign = '=' variables = {} def lex(line): idx = 0 line = line.replace(" ", "") num = "" isNum = False tokens = [] n = len(line) while idx < n: char = line[idx] if char.isdigit(): isNum = True num += char idx += 1 elif char in operators: if isNum: tokens.append(f"NUM:{num}") num = "" isNum = False tokens.append(f"OP:{char}") idx += 1 elif char == "=": try: if line[:idx].isdigit(): return None else: tokens.append(f"VAR_ASSIGN:{line[:idx]}={line[idx+1:]}") except: return "" idx += 1 elif char == "(": # 识别if关键字 if idx > 0 and line[idx-3:idx] == "if": if tokens and tokens[-1] == "VAR_CALL:if": tokens.pop() tokens.append("IF:") tokens.append("LPAREN:(") idx += 1 elif char == ")": tokens.append("RPAREN:)") idx += 1 elif char == ",": tokens.append("COMMA:,") idx += 1 elif char.isalpha(): # 优先识别if关键字 if idx + 2 < n and line[idx:idx+3] == "if": tokens.append("VAR_CALL:if") idx += 3 continue try: if any(op in line for op in operators): tokens.append(f"VAR_USE:{char}") else: tokens.append(f"VAR_CALL:{line[idx:]}") idx = n except: return "" idx += 1 else: return None idx += 1 if isNum: tokens.append(f"NUM:{num}") return tokens
2. 修改语法分析器(parse函数)
新增if()的处理逻辑:先解析条件,判断真假后执行对应语句,同时优化变量赋值的表达式解析:
def parse(tokens): if not tokens: return "Syntax error" # 处理if语句逻辑 if tokens[0] == "IF:": # 校验语法结构:if(条件, 语句) if len(tokens) < 6 or tokens[1] != "LPAREN:(" or tokens[-1] != "RPAREN:)": return "Invalid if() syntax. Use: if(condition, statement)" # 找到逗号分割条件和语句 comma_idx = None for i, tok in enumerate(tokens): if tok == "COMMA:,": comma_idx = i break if not comma_idx: return "Missing comma in if()" # 解析条件并判断真假 condition_result = parse(tokens[2:comma_idx]) try: is_true = bool(float(condition_result)) except: is_true = bool(condition_result) if not is_true: return "Condition false, no execution" # 执行条件为真时的语句 return parse(tokens[comma_idx+1:-1]) # 原有逻辑保留并优化赋值解析 equation = "" for tok in tokens: if "NUM" in tok: equation += tok[4:] elif "OP" in tok: equation += tok[3:] elif "VAR_ASSIGN" in tok: tok = tok[11:] var_name = tok[:tok.index('=')] var_value = tok[tok.index('=')+1:] # 先解析赋值的表达式再存储 parsed_value = parse(lex(var_value)) variables[var_name] = str(parsed_value) return parsed_value elif "VAR_CALL" in tok: try: return variables[tok[9:]] except: return "Variable not defined" elif "VAR_USE" in tok: try: equation += variables[tok[8:]] except: return "Variable not defined" try: return eval(equation) except: return f"Invalid equation {equation}"
3. 使用示例
现在用户可以这样操作:
KPP>x=10 10 KPP>if(x>5, y=x+2) 12 KPP>y 12 KPP>if(x<5, z=0) Condition false, no execution KPP>z Variable not defined
可选优化
- 扩展支持
else分支:if(条件, 真语句, 假语句) - 支持多行代码块(用
{}包裹,修改词法分析器识别大括号) - 新增直观的比较运算符(比如单独识别
>,<作为标记,避免依赖eval)
内容的提问来源于stack exchange,提问作者AmongusDev
相关产品推荐
相关产品推荐

