Olesya Ivanova 3 éve
szülő
commit
fc70acc8f1
4 módosított fájl, 81 hozzáadás és 22 törlés
  1. 51 18
      interpreter/interpreter.py
  2. 24 1
      interpreter/lexer.py
  3. 5 1
      interpreter/tokens.py
  4. 1 2
      main.py

+ 51 - 18
interpreter/interpreter.py

@@ -12,31 +12,64 @@ class Interpreter():
         self._lexer = Lexer()
 
     def _check_token_type(self, type_: TokenType):
+        print(type_)
         if self._current_token.type_ == type_:
             self._current_token = self._lexer.next()
         else:
             raise InterpreterException("invalid token order")
 
-    def _expr(self) -> float:
-        self._current_token = self._lexer.next()  # берём первый токен
-        left = self._current_token
-        self._check_token_type(TokenType.FLOAT)
-        op = self._current_token
-        if op.type_ == TokenType.PLUS:
-            self._check_token_type(TokenType.PLUS)
-        else:
+    def _factor(self) -> float:
+        token = self._current_token
+        if token.type_ == TokenType.MINUS:
             self._check_token_type(TokenType.MINUS)
-        right = self._current_token
-        self._check_token_type(TokenType.FLOAT)
-        if op.type_ == TokenType.PLUS:
-            return float(left.value) + float(right.value)
-        elif op.type_ == TokenType.MINUS:
-            return float(left.value) - float(right.value)
-        raise InterpreterException("bad operator")
-
-    def __call__(self, text: str):
+            val = self._factor()
+            return float(-val)
+        if token.type_ == TokenType.PLUS:
+            self._check_token_type(TokenType.PLUS)
+            val = self._factor()
+            return float(val)
+        if token.type_ == TokenType.INTEGER:
+            self._check_token_type(TokenType.INTEGER)
+            return float(token.value)
+        if token.type_ == TokenType.LPAREN:
+            self._check_token_type(TokenType.LPAREN)
+            result = self._expr()
+            self._check_token_type(TokenType.RPAREN)
+            return result
+        raise InterpreterException("invalid factor")
+
+    def _term(self) -> float:
+        result = self._factor()
+        ops = [TokenType.MUL, TokenType.DIV]
+        while self._current_token.type_ in ops:
+            token = self._current_token
+            if token.type_ == TokenType.MUL:
+                self._check_token_type(TokenType.MUL)
+                result *= self._factor()
+            elif token.type_ == TokenType.DIV:
+                self._check_token_type(TokenType.DIV)
+                result /= self._factor()
+        return result
+
+    def _expr(self) -> int:
+        ops = [TokenType.PLUS, TokenType.MINUS]
+        result = self._term()
+        while self._current_token.type_ in ops:
+            token = self._current_token
+            if token.type_ == TokenType.PLUS:
+                self._check_token_type(TokenType.PLUS)
+                result += self._term()
+            elif token.type_ == TokenType.MINUS:
+                self._check_token_type(TokenType.MINUS)
+                result -= self._term()
+            else:
+                raise InterpreterException("bad operator")
+        return result
+
+    def __call__(self, text: str) -> int:
         return self.interpret(text)
 
-    def interpret(self, text: str) -> float:
+    def interpret(self, text: str) -> int:
         self._lexer.init(text)
+        self._current_token = self._lexer.next()
         return self._expr()

+ 24 - 1
interpreter/lexer.py

@@ -20,7 +20,7 @@ class Lexer():
                 self._skip()
                 continue
             if self._current_char.isdigit():
-                return Token(TokenType.FLOAT, self._float())
+                return Token(TokenType.INTEGER, self._integer())
             if self._current_char == "+":
                 char = self._current_char
                 self._forward()
@@ -29,6 +29,22 @@ class Lexer():
                 char = self._current_char
                 self._forward()
                 return Token(TokenType.MINUS, char)
+            if self._current_char == "*":
+                char = self._current_char
+                self._forward()
+                return Token(TokenType.MUL, char)
+            if self._current_char == "/":
+                char = self._current_char
+                self._forward()
+                return Token(TokenType.DIV, char)
+            if self._current_char == "(":
+                char = self._current_char
+                self._forward()
+                return Token(TokenType.LPAREN, char)
+            if self._current_char == ")":
+                char = self._current_char
+                self._forward()
+                return Token(TokenType.RPAREN, char)
             raise LexerException(f"bad token {self._current_char}")
         return Token(TokenType.EOS, None)
 
@@ -50,6 +66,13 @@ class Lexer():
             self._forward()
         return "".join(result)
 
+    def _integer(self):
+        result: list = []
+        while self._current_char and self._current_char.isdigit():
+            result += self._current_char
+            self._forward()
+        return "".join(result)
+
     def init(self, text: str):
         self._text: text
         self._pos: -1

+ 5 - 1
interpreter/tokens.py

@@ -3,9 +3,13 @@ from enum import Enum, auto
 
 class TokenType(Enum):
     INTEGER = auto()
-    FLOAT = auto()
+    # FLOAT = auto()
     PLUS = auto()
     MINUS = auto()
+    MUL = auto()
+    DIV = auto()
+    LPAREN = auto()
+    RPAREN = auto()
     EOS = auto()  # конец строки
 
 

+ 1 - 2
main.py

@@ -2,5 +2,4 @@ from interpreter import Interpreter
 
 if __name__ == "__main__":
     interpreter = Interpreter()
-    print(interpreter("2.2+2"))
-    print(interpreter.interpret("23 - 4. "))
+    print(interpreter.interpret("3 - 3"))