用 Python 实现一门脚本语言
最近利用业余的时间实践了下编译原理,约 4200 行 python 实现了一个简单的脚本语言(类 C )。含括了数组、字典、闭包、模块等常用的功能,奉上 github https://github.com/roy2220/oyc,有兴趣的小伙伴一起讨论交流!
用 Python 实现一门脚本语言
3 回复
要实现一门脚本语言,核心是构建解释器。这里提供一个最简示例,实现支持四则运算和变量的脚本语言。
import re
class Token:
def __init__(self, type, value):
self.type = type
self.value = value
class Lexer:
def __init__(self, text):
self.text = text
self.pos = 0
self.current_char = self.text[self.pos] if self.text else None
def advance(self):
self.pos += 1
self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
def skip_whitespace(self):
while self.current_char and self.current_char.isspace():
self.advance()
def integer(self):
result = ''
while self.current_char and self.current_char.isdigit():
result += self.current_char
self.advance()
return int(result)
def get_next_token(self):
while self.current_char:
if self.current_char.isspace():
self.skip_whitespace()
continue
if self.current_char.isdigit():
return Token('INTEGER', self.integer())
if self.current_char.isalpha():
identifier = ''
while self.current_char and (self.current_char.isalnum() or self.current_char == '_'):
identifier += self.current_char
self.advance()
return Token('IDENTIFIER', identifier)
if self.current_char == '=':
self.advance()
return Token('ASSIGN', '=')
if self.current_char in '+-*/':
op = self.current_char
self.advance()
return Token('OPERATOR', op)
if self.current_char == '(':
self.advance()
return Token('LPAREN', '(')
if self.current_char == ')':
self.advance()
return Token('RPAREN', ')')
raise Exception(f'Invalid character: {self.current_char}')
return Token('EOF', None)
class Parser:
def __init__(self, lexer):
self.lexer = lexer
self.current_token = self.lexer.get_next_token()
self.variables = {}
def eat(self, token_type):
if self.current_token.type == token_type:
self.current_token = self.lexer.get_next_token()
else:
raise Exception(f'Expected {token_type}, got {self.current_token.type}')
def factor(self):
token = self.current_token
if token.type == 'INTEGER':
self.eat('INTEGER')
return token.value
if token.type == 'IDENTIFIER':
var_name = token.value
self.eat('IDENTIFIER')
if var_name not in self.variables:
raise Exception(f'Undefined variable: {var_name}')
return self.variables[var_name]
if token.type == 'LPAREN':
self.eat('LPAREN')
result = self.expr()
self.eat('RPAREN')
return result
raise Exception(f'Unexpected token: {token.type}')
def term(self):
result = self.factor()
while self.current_token.type == 'OPERATOR' and self.current_token.value in '*/':
token = self.current_token
self.eat('OPERATOR')
if token.value == '*':
result *= self.factor()
else:
result /= self.factor()
return result
def expr(self):
result = self.term()
while self.current_token.type == 'OPERATOR' and self.current_token.value in '+-':
token = self.current_token
self.eat('OPERATOR')
if token.value == '+':
result += self.term()
else:
result -= self.term()
return result
def assignment(self):
var_name = self.current_token.value
self.eat('IDENTIFIER')
self.eat('ASSIGN')
value = self.expr()
self.variables[var_name] = value
return value
def parse(self):
if self.current_token.type == 'IDENTIFIER' and self.lexer.current_char == '=':
return self.assignment()
return self.expr()
def interpret(code):
lexer = Lexer(code)
parser = Parser(lexer)
return parser.parse()
# 测试示例
if __name__ == '__main__':
# 基本运算
print(interpret("2 + 3 * 4")) # 输出: 14
# 带括号
print(interpret("(2 + 3) * 4")) # 输出: 20
# 变量赋值和使用
interpret("x = 10")
interpret("y = 20")
print(interpret("x + y")) # 输出: 30
# 复杂表达式
interpret("a = 5")
interpret("b = 3")
print(interpret("(a + b) * 2 - b / 1")) # 输出: 13.0
这个实现包含了词法分析器(Lexer)、语法分析器(Parser)和解释器。词法分析器将源代码转换为token流,语法分析器构建抽象语法树并执行计算。支持整数、四则运算、括号和变量赋值。
要扩展功能,可以添加:1)更多数据类型(字符串、布尔值);2)控制结构(if/while);3)函数定义;4)错误处理。
总结:从词法分析和语法分析开始构建。
大佬…
花点时间撸一撸,你也是大佬:)

