{ "cells": [ { "cell_type": "code", "execution_count": 177, "metadata": {}, "outputs": [], "source": [ "from rply import LexerGenerator\n", "\n", "\n", "class Lexer():\n", " def __init__(self):\n", " self.lexer = LexerGenerator()\n", "\n", " def _add_tokens(self):\n", " # Print\n", " self.lexer.add('PRINT', r'print')\n", " \n", " self.lexer.add('SQRT', r'sqrt')\n", " \n", " \n", " # Parenthesis\n", " self.lexer.add('OPEN_PAREN', r'\\(')\n", " self.lexer.add('CLOSE_PAREN', r'\\)')\n", " \n", " # Semi Colon\n", " self.lexer.add('SEMI_COLON', r'\\;')\n", " \n", " # Operators\n", " self.lexer.add('SUM', r'\\+')\n", " self.lexer.add('SUB', r'\\-')\n", " self.lexer.add('MUL', r'\\*')\n", " self.lexer.add('DIV', r'\\/')\n", " \n", " # Number\n", " self.lexer.add('NUMBER', r'\\d+')\n", " \n", " # Ignore spaces\n", " self.lexer.ignore('\\s+')\n", "\n", " def get_lexer(self):\n", " self._add_tokens()\n", " return self.lexer.build()" ] }, { "cell_type": "code", "execution_count": 178, "metadata": {}, "outputs": [], "source": [ "# !pip install rply\n", "# !pip install ast" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## AST" ] }, { "cell_type": "code", "execution_count": 179, "metadata": {}, "outputs": [], "source": [ "class Number():\n", " def __init__(self, value):\n", " self.value = value\n", "\n", " def eval(self):\n", " return int(self.value)\n", "\n", "\n", "class BinaryOp():\n", " def __init__(self, left, right):\n", " self.left = left\n", " self.right = right\n", "\n", "\n", "class Sum(BinaryOp):\n", " def eval(self):\n", " return self.left.eval() + self.right.eval()\n", "\n", "\n", "class Sub(BinaryOp):\n", " def eval(self):\n", " return self.left.eval() - self.right.eval()\n", "\n", "class Mul(BinaryOp):\n", " def eval(self):\n", " return self.left.eval() * self.right.eval()\n", "\n", "class Div(BinaryOp):\n", " def eval(self):\n", " return self.left.eval() / self.right.eval()\n", "\n", "\n", "class Print():\n", " def __init__(self, value):\n", " self.value = value\n", "\n", " def eval(self):\n", " print(self.value.eval())\n", " " ] }, { "cell_type": "code", "execution_count": 205, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 205, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import fastnumbers\n", "fastnumbers.isreal(\"d\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parser" ] }, { "cell_type": "code", "execution_count": 199, "metadata": {}, "outputs": [], "source": [ "from rply import ParserGenerator\n", "# from ast import Number, Sum, Sub, Print\n", "\n", "\n", "class Parser():\n", " def __init__(self):\n", " self.pg = ParserGenerator(\n", " # A list of all token names accepted by the parser.\n", " ['NUMBER', 'SQRT','PRINT', 'OPEN_PAREN', 'CLOSE_PAREN',\n", " 'SEMI_COLON', 'SUM', 'SUB', 'MUL', 'DIV'], precedence=[\n", " ('left',['SUM','SUB']),\n", " ('left',['DIV','MUL'])\n", " ]\n", " )\n", "\n", " def parse(self):\n", "# @self.pg.production('function : SQRT OPEN_PAREN expression CLOSE_PAREN')\n", "# def func(p):\n", "# # print(p)\n", "# return (p[2])\n", "\n", " \n", " @self.pg.production('program : PRINT OPEN_PAREN expression CLOSE_PAREN SEMI_COLON')\n", " def program(p):\n", " return Print(p[2])\n", "\n", " @self.pg.production('expression : expression SUM expression')\n", " @self.pg.production('expression : expression SUB expression')\n", " @self.pg.production('expression : expression MUL expression')\n", " @self.pg.production('expression : expression DIV expression')\n", " def expression(p):\n", " left = p[0]\n", " right = p[2]\n", " operator = p[1]\n", " \n", " if operator.gettokentype() == 'SUM':\n", " return Sum(left, right)\n", " elif operator.gettokentype() == 'SUB':\n", " return Sub(left, right)\n", " elif operator.gettokentype() == 'MUL':\n", " return Mul(left, right)\n", " elif operator.gettokentype() == 'DIV':\n", " return Div(left, right)\n", " \n", "\n", " @self.pg.production('expression : NUMBER')\n", " def number(p):\n", " return Number(p[0].value)\n", "\n", " @self.pg.error\n", " def error_handle(token):\n", " raise ValueError(token)\n", "\n", " def get_parser(self):\n", " return self.pg.build()" ] }, { "cell_type": "code", "execution_count": 200, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\argenisleon\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:55: ParserGeneratorWarning: Token 'SQRT' is unused\n" ] }, { "ename": "LexingError", "evalue": "(None, SourcePosition(idx=7, lineno=-1, colno=-1))", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mLexingError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n", "\u001b[1;32m~\\Anaconda3\\lib\\site-packages\\rply\\parser.py\u001b[0m in \u001b[0;36mparse\u001b[1;34m(self, tokenizer, state)\u001b[0m\n\u001b[0;32m 30\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 31\u001b[0m \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 32\u001b[1;33m \u001b[0mlookahead\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtokenizer\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 33\u001b[0m \u001b[1;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 34\u001b[0m \u001b[0mlookahead\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32m~\\Anaconda3\\lib\\site-packages\\rply\\lexer.py\u001b[0m in \u001b[0;36m__next__\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 58\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 59\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m__next__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 60\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32m~\\Anaconda3\\lib\\site-packages\\rply\\lexer.py\u001b[0m in \u001b[0;36mnext\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 55\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mtoken\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 56\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 57\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mLexingError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mSourcePosition\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0midx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 58\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 59\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m__next__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mLexingError\u001b[0m: (None, SourcePosition(idx=7, lineno=-1, colno=-1))" ] } ], "source": [ "%%time\n", "text_input = \"\"\"\n", "print(SQRT(4*3/2));\n", "\"\"\"\n", "\n", "lexer = Lexer().get_lexer()\n", "tokens = lexer.lex(text_input)\n", "\n", "pg = Parser()\n", "pg.parse()\n", "parser = pg.get_parser()\n", "# print(parser)\n", "parser.parse(tokens).eval()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" } }, "nbformat": 4, "nbformat_minor": 4 }