{"id":25356,"date":"2024-06-07T16:52:49","date_gmt":"2024-06-07T07:52:49","guid":{"rendered":"http:\/\/www.tyosuke20xx.com\/blog\/?p=25356"},"modified":"2024-06-07T16:52:51","modified_gmt":"2024-06-07T07:52:51","slug":"python-%e3%83%97%e3%83%ad%e3%82%b0%e3%83%a9%e3%83%9f%e3%83%b3%e3%82%b0%e8%a8%80%e8%aa%9e","status":"publish","type":"post","link":"http:\/\/www.tyosuke20xx.com\/blog\/?p=25356","title":{"rendered":"python \u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u8a00\u8a9e"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>import re\n\n# \u30c8\u30fc\u30af\u30ca\u30a4\u30b6\u30fc\ndef tokenize(code):\n    token_specification = &#91;\n        ('NUMBER',   r'\\d+'),          # \u6574\u6570\n        ('ID',       r'&#91;A-Za-z_]\\w*'), # \u8b58\u5225\u5b50\n        ('ASSIGN',   r'='),            # \u4ee3\u5165\u6f14\u7b97\u5b50\n        ('END',      r';'),            # \u6587\u306e\u7d42\u308f\u308a\n        ('OP',       r'&#91;+\\-*\/]'),      # \u6f14\u7b97\u5b50\n        ('NEWLINE',  r'\\n'),           # \u6539\u884c\n        ('SKIP',     r'&#91; \\t]'),        # \u7a7a\u767d\u3068\u30bf\u30d6\n        ('MISMATCH', r'.'),            # \u4e00\u81f4\u3057\u306a\u3044\u6587\u5b57\n    ]\n    tok_regex = '|'.join('(?P&lt;%s>%s)' % pair for pair in token_specification)\n    get_token = re.compile(tok_regex).finditer\n    tokens = &#91;]\n    for mo in get_token(code):\n        kind = mo.lastgroup\n        value = mo.group()\n        if kind == 'NUMBER':\n            value = int(value)\n        elif kind == 'ID' and value in {'if', 'while', 'def'}:\n            kind = value.upper()\n        elif kind == 'SKIP':\n            continue\n        elif kind == 'NEWLINE':\n            value = '\\n'\n        elif kind == 'MISMATCH':\n            raise RuntimeError(f'{value} unexpected on line {code}')\n        tokens.append((kind, value))\n    return tokens\n\n# \u30d1\u30fc\u30b5\u30fc\u30af\u30e9\u30b9\nclass Parser:\n    def __init__(self, tokens):\n        self.tokens = tokens\n        self.pos = 0\n\n    def parse(self):\n        statements = &#91;]\n        while self.pos &lt; len(self.tokens):\n            statement = self.statement()\n            if statement:\n                statements.append(statement)\n        return statements\n\n    def statement(self):\n        if self.pos >= len(self.tokens):\n            return None\n        token = self.tokens&#91;self.pos]\n        if token&#91;0] == 'ID' and self.pos + 1 &lt; len(self.tokens) and self.tokens&#91;self.pos + 1]&#91;0] == 'ASSIGN':\n            return self.assignment()\n        elif token&#91;0] in {'ID', 'NUMBER'} or (token&#91;0] == 'OP' and token&#91;1] == '-'):\n            return self.expression()\n        else:\n            raise SyntaxError(f'Unexpected token: {token}')\n\n    def assignment(self):\n        id_token = self.tokens&#91;self.pos]\n        self.pos += 1  # skip ID\n        self.pos += 1  # skip ASSIGN\n        expr = self.expression()\n        self.expect('END')\n        return ('assign', id_token&#91;1], expr)\n\n    def expression(self):\n        term = self.term()\n        while self.pos &lt; len(self.tokens) and self.tokens&#91;self.pos]&#91;0] == 'OP':\n            op = self.tokens&#91;self.pos]\n            self.pos += 1\n            term = (op&#91;1], term, self.term())\n        return term\n\n    def term(self):\n        token = self.tokens&#91;self.pos]\n        if token&#91;0] == 'NUMBER':\n            self.pos += 1\n            return token&#91;1]\n        elif token&#91;0] == 'ID':\n            self.pos += 1\n            return ('var', token&#91;1])\n        else:\n            raise SyntaxError(f'Unexpected token: {token}')\n\n    def expect(self, kind):\n        if self.pos &lt; len(self.tokens) and self.tokens&#91;self.pos]&#91;0] == kind:\n            self.pos += 1\n        else:\n            raise SyntaxError(f'Expected {kind}')\n\n# \u30a4\u30f3\u30bf\u30d7\u30ea\u30bf\u30af\u30e9\u30b9\nclass Interpreter:\n    def __init__(self):\n        self.variables = {}\n\n    def evaluate(self, node):\n        if isinstance(node, int):\n            return node\n        elif isinstance(node, tuple):\n            if node&#91;0] == 'assign':\n                self.variables&#91;node&#91;1]] = self.evaluate(node&#91;2])\n                return self.variables&#91;node&#91;1]]\n            elif node&#91;0] == 'var':\n                if node&#91;1] in self.variables:\n                    return self.variables&#91;node&#91;1]]\n                else:\n                    raise NameError(f\"Variable '{node&#91;1]}' is not defined\")\n            else:\n                left = self.evaluate(node&#91;1])\n                right = self.evaluate(node&#91;2])\n                if node&#91;0] == '+':\n                    return left + right\n                elif node&#91;0] == '-':\n                    return left - right\n                elif node&#91;0] == '*':\n                    return left * right\n                elif node&#91;0] == '\/':\n                    return left \/ right\n        return None\n\n# REPL (Read-Eval-Print Loop)\ndef repl():\n    interpreter = Interpreter()\n    while True:\n        try:\n            code = input('>>> ')\n            if code == 'exit':\n                break\n            tokens = tokenize(code)\n            parser = Parser(tokens)\n            tree = parser.parse()\n            for statement in tree:\n                result = interpreter.evaluate(statement)\n                if result is not None:\n                    print(result)\n        except Exception as e:\n            print(f\"Error: {e}\")\n\nif __name__ == \"__main__\":\n    repl()\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[4,65],"tags":[3,39],"class_list":["post-25356","post","type-post","status-publish","format-standard","hentry","category-programming","category-python","tag-programming","tag-python"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=25356"}],"version-history":[{"count":1,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25356\/revisions"}],"predecessor-version":[{"id":25357,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25356\/revisions\/25357"}],"wp:attachment":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=25356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=25356"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=25356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}