python プログラミング言語

import re

# トークナイザー
def tokenize(code):
    token_specification = [
        ('NUMBER',   r'\d+'),          # 整数
        ('ID',       r'[A-Za-z_]\w*'), # 識別子
        ('ASSIGN',   r'='),            # 代入演算子
        ('END',      r';'),            # 文の終わり
        ('OP',       r'[+\-*/]'),      # 演算子
        ('NEWLINE',  r'\n'),           # 改行
        ('SKIP',     r'[ \t]'),        # 空白とタブ
        ('MISMATCH', r'.'),            # 一致しない文字
    ]
    tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
    get_token = re.compile(tok_regex).finditer
    tokens = []
    for mo in get_token(code):
        kind = mo.lastgroup
        value = mo.group()
        if kind == 'NUMBER':
            value = int(value)
        elif kind == 'ID' and value in {'if', 'while', 'def'}:
            kind = value.upper()
        elif kind == 'SKIP':
            continue
        elif kind == 'NEWLINE':
            value = '\n'
        elif kind == 'MISMATCH':
            raise RuntimeError(f'{value} unexpected on line {code}')
        tokens.append((kind, value))
    return tokens

# パーサークラス
class Parser:
    def __init__(self, tokens):
        self.tokens = tokens
        self.pos = 0

    def parse(self):
        statements = []
        while self.pos < len(self.tokens):
            statement = self.statement()
            if statement:
                statements.append(statement)
        return statements

    def statement(self):
        if self.pos >= len(self.tokens):
            return None
        token = self.tokens[self.pos]
        if token[0] == 'ID' and self.pos + 1 < len(self.tokens) and self.tokens[self.pos + 1][0] == 'ASSIGN':
            return self.assignment()
        elif token[0] in {'ID', 'NUMBER'} or (token[0] == 'OP' and token[1] == '-'):
            return self.expression()
        else:
            raise SyntaxError(f'Unexpected token: {token}')

    def assignment(self):
        id_token = self.tokens[self.pos]
        self.pos += 1  # skip ID
        self.pos += 1  # skip ASSIGN
        expr = self.expression()
        self.expect('END')
        return ('assign', id_token[1], expr)

    def expression(self):
        term = self.term()
        while self.pos < len(self.tokens) and self.tokens[self.pos][0] == 'OP':
            op = self.tokens[self.pos]
            self.pos += 1
            term = (op[1], term, self.term())
        return term

    def term(self):
        token = self.tokens[self.pos]
        if token[0] == 'NUMBER':
            self.pos += 1
            return token[1]
        elif token[0] == 'ID':
            self.pos += 1
            return ('var', token[1])
        else:
            raise SyntaxError(f'Unexpected token: {token}')

    def expect(self, kind):
        if self.pos < len(self.tokens) and self.tokens[self.pos][0] == kind:
            self.pos += 1
        else:
            raise SyntaxError(f'Expected {kind}')

# インタプリタクラス
class Interpreter:
    def __init__(self):
        self.variables = {}

    def evaluate(self, node):
        if isinstance(node, int):
            return node
        elif isinstance(node, tuple):
            if node[0] == 'assign':
                self.variables[node[1]] = self.evaluate(node[2])
                return self.variables[node[1]]
            elif node[0] == 'var':
                if node[1] in self.variables:
                    return self.variables[node[1]]
                else:
                    raise NameError(f"Variable '{node[1]}' is not defined")
            else:
                left = self.evaluate(node[1])
                right = self.evaluate(node[2])
                if node[0] == '+':
                    return left + right
                elif node[0] == '-':
                    return left - right
                elif node[0] == '*':
                    return left * right
                elif node[0] == '/':
                    return left / right
        return None

# REPL (Read-Eval-Print Loop)
def repl():
    interpreter = Interpreter()
    while True:
        try:
            code = input('>>> ')
            if code == 'exit':
                break
            tokens = tokenize(code)
            parser = Parser(tokens)
            tree = parser.parse()
            for statement in tree:
                result = interpreter.evaluate(statement)
                if result is not None:
                    print(result)
        except Exception as e:
            print(f"Error: {e}")

if __name__ == "__main__":
    repl()

投稿者: chosuke

趣味はゲームやアニメや漫画などです

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です