
一直在听大家说用ai自动写代码,也简单尝试使用vscode+阿里通义灵码自动生成代码,但效果一直不理想;最近又出了一个Trae.ai的IDE,自带Claude-3.5-Sonnet和GPT-4o,于是去下载来体验了一下,但由于字节跳动不允许国内用户使用,只能翻墙注册登录,不过还好,ide是支持中文的。
以下是我要求ai给写的一个使用python解析pascal语法,实现99乘法表的例子,代码如下,效果图附最后:
from enum import Enum, auto
import re
# 在 TokenType 中添加 WRITE
class TokenType(Enum):
INTEGER = auto()
STRING = auto() # 新增
PLUS = auto()
MINUS = auto()
MULTIPLY = auto()
DIVIDE = auto()
LPAREN = auto()
RPAREN = auto()
EOF = auto()
BEGIN = auto()
END = auto()
SEMICOLON = auto()
DOT = auto()
ID = auto()
ASSIGN = auto()
FOR = auto()
TO = auto()
DO = auto()
WRITELN = auto()
WRITE = auto()
# 在 Lexer 的 _id 方法中添加 WRITE 识别
# 在 TokenType 枚举后添加
class Token:
def __init__(self, type, value):
self.type = type
self.value = value
def __str__(self):
return f'Token({self.type}, {self.value})'
class Lexer:
def __init__(self, text):
self.text = text
self.pos = 0
self.current_char = self.text[self.pos] if text else None
def error(self):
raise Exception('Invalid character')
def advance(self):
self.pos += 1
if self.pos > len(self.text) - 1:
self.current_char = None
else:
self.current_char = self.text[self.pos]
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 string(self):
result = ''
self.advance() # 跳过开始的引号
while self.current_char and self.current_char != "'":
result += self.current_char
self.advance()
self.advance() # 跳过结束的引号
return result
def _id(self):
result = ''
while self.current_char and (self.current_char.isalnum() or self.current_char == '_'):
result += self.current_char
self.advance()
result = result.upper()
if result == 'BEGIN':
return Token(TokenType.BEGIN, 'BEGIN')
elif result == 'END':
return Token(TokenType.END, 'END')
elif result == 'FOR':
return Token(TokenType.FOR, 'FOR')
elif result == 'TO':
return Token(TokenType.TO, 'TO')
elif result == 'DO':
return Token(TokenType.DO, 'DO')
elif result == 'WRITELN':
return Token(TokenType.WRITELN, 'WRITELN')
elif result == 'WRITE':
return Token(TokenType.WRITE, 'WRITE')
else:
return Token(TokenType.ID, result)
def get_next_token(self):
while self.current_char:
if self.current_char.isspace():
self.skip_whitespace()
continue
if self.current_char == "'":
return Token(TokenType.STRING, self.string())
if self.current_char.isalpha():
return self._id()
if self.current_char.isdigit():
return Token(TokenType.INTEGER, self.integer())
if self.current_char == ':' and self.peek() == '=':
self.advance()
self.advance()
return Token(TokenType.ASSIGN, ':=')
if self.current_char == ';':
self.advance()
return Token(TokenType.SEMICOLON, ';')
if self.current_char == '.':
self.advance()
return Token(TokenType.DOT, '.')
if self.current_char == '+':
self.advance()
return Token(TokenType.PLUS, '+')
if self.current_char == '-':
self.advance()
return Token(TokenType.MINUS, '-')
if self.current_char == '*':
self.advance()
return Token(TokenType.MULTIPLY, '*')
if self.current_char == '/':
self.advance()
return Token(TokenType.DIVIDE, '/')
if self.current_char == '(':
self.advance()
return Token(TokenType.LPAREN, '(')
if self.current_char == ')':
self.advance()
return Token(TokenType.RPAREN, ')')
if self.current_char == '>':
self.advance()
return Token(TokenType.GREATER, '>')
if self.current_char == '<':
self.advance()
return Token(TokenType.LESS, '<')
if self.current_char == '=':
self.advance()
return Token(TokenType.EQUAL, '=')
self.error()
return Token(TokenType.EOF, None)
def peek(self):
peek_pos = self.pos + 1
if peek_pos > len(self.text) - 1:
return None
return self.text[peek_pos]
# TokenType 枚举定义后,添加所有 AST 相关的类定义
class AST:
pass
class String(AST):
def __init__(self, token):
self.token = token
self.value = token.value
class BinOp(AST):
def __init__(self, left, op, right):
self.left = left
self.token = self.op = op
self.right = right
class Num(AST):
def __init__(self, token):
self.token = token
self.value = token.value
class Var(AST):
def __init__(self, token):
self.token = token
self.value = token.value
class Assign(AST):
def __init__(self, left, op, right):
self.left = left
self.token = self.op = op
self.right = right
class For(AST):
def __init__(self, var, start, end, statements):
self.var = var
self.start = start
self.end = end
self.statements = statements
class Writeln(AST):
def __init__(self, expr):
self.expr = expr
class Write(AST):
def __init__(self, expr):
self.expr = expr
# 在 Interpreter 类中添加 write 支持
# 在 AST 类定义后添加完整的 Interpreter 类
class Interpreter:
def __init__(self, lexer):
self.lexer = lexer
self.current_token = self.lexer.get_next_token()
self.variables = {}
# 删除这里的 String 类定义
def error(self):
raise Exception('Invalid syntax')
def eat(self, token_type):
if self.current_token.type == token_type:
self.current_token = self.lexer.get_next_token()
else:
self.error()
# 添加 String AST 节点
# String AST 节点应该在 AST 相关类定义部分
# 在 AST 相关类定义部分添加
class String(AST):
def __init__(self, token):
self.token = token
self.value = token.value
def term(self):
node = self.factor()
while self.current_token.type in (TokenType.MULTIPLY, TokenType.DIVIDE):
token = self.current_token
if token.type == TokenType.MULTIPLY:
self.eat(TokenType.MULTIPLY)
elif token.type == TokenType.DIVIDE:
self.eat(TokenType.DIVIDE)
node = BinOp(left=node, op=token, right=self.factor())
return node
def expr(self):
node = self.term()
while self.current_token.type in (TokenType.PLUS, TokenType.MINUS):
token = self.current_token
if token.type == TokenType.PLUS:
self.eat(TokenType.PLUS)
elif token.type == TokenType.MINUS:
self.eat(TokenType.MINUS)
node = BinOp(left=node, op=token, right=self.term())
return node
def statement(self):
if self.current_token.type == TokenType.ID:
node = self.assignment_statement()
self.eat(TokenType.SEMICOLON)
return node
elif self.current_token.type == TokenType.FOR:
node = self.for_statement()
self.eat(TokenType.SEMICOLON)
return node
elif self.current_token.type == TokenType.WRITELN:
node = self.writeln_statement()
self.eat(TokenType.SEMICOLON)
return node
elif self.current_token.type == TokenType.WRITE:
node = self.write_statement()
self.eat(TokenType.SEMICOLON)
return node
def statements(self):
self.eat(TokenType.BEGIN)
statements = []
while self.current_token.type != TokenType.END:
statements.append(self.statement())
self.eat(TokenType.END)
self.eat(TokenType.DOT)
return statements
def visit(self, node):
if isinstance(node, String):
return node.value
if isinstance(node, Write):
value = self.visit(node.expr)
print(value, end='')
return None
if isinstance(node, Writeln):
value = self.visit(node.expr)
print(value)
return None
if isinstance(node, For):
var_name = node.var.value
start_val = self.visit(node.start)
end_val = self.visit(node.end)
for i in range(start_val, end_val + 1):
self.variables[var_name] = i
for stmt in node.statements:
self.visit(stmt)
return None
if isinstance(node, BinOp):
if node.op.type == TokenType.PLUS:
return self.visit(node.left) + self.visit(node.right)
elif node.op.type == TokenType.MINUS:
return self.visit(node.left) - self.visit(node.right)
elif node.op.type == TokenType.MULTIPLY:
return self.visit(node.left) * self.visit(node.right)
elif node.op.type == TokenType.DIVIDE:
return self.visit(node.left) / self.visit(node.right)
elif isinstance(node, Num):
return node.value
elif isinstance(node, Var):
return self.variables.get(node.value, 0)
elif isinstance(node, Assign):
var_name = node.left.value
self.variables[var_name] = self.visit(node.right)
return self.variables[var_name]
def interpret(self):
statements = self.statements()
for statement in statements:
self.visit(statement)
return self.variables
def assignment_statement(self):
var = Var(self.current_token)
self.eat(TokenType.ID)
token = self.current_token
self.eat(TokenType.ASSIGN)
return Assign(var, token, self.expr())
def for_statement(self):
self.eat(TokenType.FOR)
var = Var(self.current_token)
self.eat(TokenType.ID)
self.eat(TokenType.ASSIGN)
start = self.expr()
self.eat(TokenType.TO)
end = self.expr()
self.eat(TokenType.DO)
statements = []
if self.current_token.type == TokenType.BEGIN:
self.eat(TokenType.BEGIN)
while self.current_token.type != TokenType.END:
statements.append(self.statement())
self.eat(TokenType.END)
else:
statements.append(self.statement())
return For(var, start, end, statements)
def writeln_statement(self):
self.eat(TokenType.WRITELN)
self.eat(TokenType.LPAREN)
expr = self.expr()
self.eat(TokenType.RPAREN)
return Writeln(expr)
def write_statement(self):
self.eat(TokenType.WRITE)
self.eat(TokenType.LPAREN)
expr = self.expr()
self.eat(TokenType.RPAREN)
return Write(expr)
def factor(self):
token = self.current_token
if token.type == TokenType.INTEGER:
self.eat(TokenType.INTEGER)
return Num(token)
elif token.type == TokenType.STRING:
self.eat(TokenType.STRING)
return String(token)
elif token.type == TokenType.ID:
self.eat(TokenType.ID)
return Var(token)
elif token.type == TokenType.LPAREN:
self.eat(TokenType.LPAREN)
node = self.expr()
self.eat(TokenType.RPAREN)
return node
def main():
text = """
BEGIN
FOR i := 1 TO 9 DO
BEGIN
FOR j := 1 TO i DO
BEGIN
write(j);
write('*');
write(i);
write('=');
write(i * j);
write(' ');
END;
writeln('');
END;
for n:=1 to 100 do
begin
m:=m+n;
end;
writeln(m);
END.
"""
try:
lexer = Lexer(text)
interpreter = Interpreter(lexer)
result = interpreter.interpret()
print("最终变量值:", result)
except Exception as e:
print("错误:", str(e))
if __name__ == '__main__':
main()
代码全部由ai自动生成,但我花了大量的时间让ai重复修正错误,所以,目前的ai虽然能自动按要求生成代码,但还是需要懂代码的人去校验和辅助实现。