Python 解释器编写

class Token:
    def __init__(self, type_, value=None):
        self.type = type_
        self.value = value

    def __repr__(self):
        return f'{self.type}:{self.value}' if self.value else f'{self.type}'

class Lexer:
    def __init__(self, text):
        self.text = text
        self.pos = 0
        self.current_char = self.text[self.pos] if 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 get_word(self):
        word = ''
        while self.current_char and (self.current_char.isalnum() or self.current_char == '_'):
            word += self.current_char
            self.advance()
        return word
    
    def get_string(self):
        string = ''
        self.advance()  # Skip first quote
        while self.current_char and self.current_char != '"':
            string += self.current_char
            self.advance()
        self.advance()  # Skip closing quote
        return string

    def tokenize(self):
        tokens = []
        
        while self.current_char:
            if self.current_char.isspace():
                self.skip_whitespace()
                continue
                
            if self.current_char.isalpha():
                word = self.get_word()
                if word.lower() == 'dim':
                    tokens.append(Token('DIM'))
                elif word.lower() == 'as':
                    tokens.append(Token('AS'))
                elif word.lower() == 'print':
                    tokens.append(Token('PRINT'))
                else:
                    tokens.append(Token('IDENTIFIER', word))
                continue

            if self.current_char == '=':
                tokens.append(Token('EQUALS'))
                self.advance()
                continue

            if self.current_char == '"':
                string = self.get_string()
                tokens.append(Token('STRING', string))
                continue

            self.advance()
            
        return tokens

class Parser:
    def __init__(self, tokens):
        self.tokens = tokens
        self.pos = 0
        self.current_token = tokens[0] if tokens else None

    def advance(self):
        self.pos += 1
        self.current_token = self.tokens[self.pos] if self.pos < len(self.tokens) else None

    def parse(self):
        if not self.current_token:
            return None

        if self.current_token.type == 'DIM':
            return self.parse_variable_declaration()
        elif self.current_token.type == 'IDENTIFIER':
            return self.parse_assignment()
        elif self.current_token.type == 'PRINT':
            return self.parse_print()

        return None

    def parse_variable_declaration(self):
        self.advance()  # Skip 'DIM'
        if self.current_token and self.current_token.type == 'IDENTIFIER':
            var_name = self.current_token.value
            self.advance()
            if self.current_token and self.current_token.type == 'AS':
                self.advance()
                if self.current_token and self.current_token.type == 'IDENTIFIER':
                    var_type = self.current_token.value
                    return {'type': 'variable_declaration', 'name': var_name, 'var_type': var_type}

    def parse_assignment(self):
        var_name = self.current_token.value
        self.advance()
        if self.current_token and self.current_token.type == 'EQUALS':
            self.advance()
            if self.current_token and self.current_token.type == 'STRING':
                value = self.current_token.value
                return {'type': 'assignment', 'name': var_name, 'value': value}

    def parse_print(self):
        self.advance()  # Skip 'PRINT'
        if self.current_token and self.current_token.type == 'IDENTIFIER':
            var_name = self.current_token.value
            return {'type': 'print', 'name': var_name}

class Interpreter:
    def __init__(self):
        self.variables = {}

    def run(self, text):
        lexer = Lexer(text)
        tokens = lexer.tokenize()
        parser = Parser(tokens)
        result = parser.parse()
        
        if result:
            if result['type'] == 'variable_declaration':
                self.variables[result['name']] = {'type': result['var_type'], 'value': None}
                print(f"声明变量: {result['name']} (类型: {result['var_type']})")
            elif result['type'] == 'assignment':
                if result['name'] in self.variables:
                    self.variables[result['name']]['value'] = result['value']
                    print(f"赋值: {result['name']} = {result['value']}")
                else:
                    print(f"错误: 变量 {result['name']} 未声明")
            elif result['type'] == 'print':
                if result['name'] in self.variables:
                    print(f"输出: {self.variables[result['name']]['value']}")
                else:
                    print(f"错误: 变量 {result['name']} 未声明")
        else:
            print("语法错误")

def run_file(filename):
    try:
        with open(filename, 'r') as file:
            interpreter = Interpreter()
            for line in file:
                line = line.strip()
                if line:
                    interpreter.run(line)
    except FileNotFoundError:
        print(f"错误: 文件 {filename} 不存在")

def run_shell():
    interpreter = Interpreter()
    while True:
        try:
            text = input('SimpleScript > ')
            if text.lower() == 'exit':
                break
            if text.startswith('run '):
                filename = text[4:].strip()
                if filename.endswith('.ss'):
                    run_file(filename)
                else:
                    print("错误: 只能运行 .ss 文件")
            elif text.strip():
                interpreter.run(text)
        except KeyboardInterrupt:
            break
        except Exception as e:
            print(f"错误: {str(e)}")

if __name__ == "__main__":
    run_shell()
posted @ 2024-11-29 21:13  eva1024  阅读(11)  评论(0)    收藏  举报