Spaces:
Runtime error
Runtime error
| from ast_parser.errors import LinterException | |
| from ast_parser.token import ( | |
| Token, | |
| TokenKind, | |
| is_binary_operator, | |
| is_relational_operator, | |
| ) | |
| class Linter: | |
| """Linter enables real-time validation of the token chain. | |
| Args: | |
| source (str): The source string being tokenized. | |
| """ | |
| _source: str | |
| _variable_provided: bool | |
| _relation_provided: bool | |
| def __init__(self, source: str) -> None: | |
| self._source = source | |
| self._variable_provided = False | |
| self._relation_provided = False | |
| def lint(self, token: Token) -> None: | |
| """The lint method checks the token for integrity, validity and | |
| relevance. It raises a LinterException if the token is invalid | |
| or unexpected. | |
| Args: | |
| token (Token): The starting token. | |
| source (str): The source string being tokenized. Used for | |
| exception messages. | |
| Raises: | |
| LinterException: Unexpected binary operator, term missed. | |
| LinterException: Equation must contain only one relational | |
| operator. | |
| LinterException: Term must contain no more than one | |
| variable. | |
| LinterException: Unexpected comma at the beginning of the | |
| equation. | |
| LinterException: Unexpected comma, equation missed. | |
| LinterException: Unexpected comma at the end of the | |
| equation. | |
| LinterException: Equation must contain a relational | |
| operator. | |
| """ | |
| if token.kind != TokenKind.SOF and ( | |
| token.prev_token is None or token.prev_token.next_token is not token | |
| ): | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Crude modification of the token chain is detected", | |
| ) | |
| if token.kind == TokenKind.EOF: | |
| self._lint_eof(token) | |
| if is_binary_operator(token): | |
| self._lint_binary_operator(token) | |
| self._variable_provided = False | |
| if token.kind == TokenKind.MUL: | |
| self._lint_multiplication_operator(token) | |
| if is_relational_operator(token): | |
| self._lint_relational_operator(token) | |
| self._variable_provided = False | |
| self._relation_provided = True | |
| if token.kind == TokenKind.VARIABLE: | |
| self._lint_variable(token) | |
| self._variable_provided = True | |
| if token.kind == TokenKind.COMMA: | |
| self._lint_comma(token) | |
| self._variable_provided = False | |
| self._relation_provided = False | |
| def _lint_eof(self, token: Token) -> None: | |
| """Lint the EOF Token. | |
| Args: | |
| token (Token): The EOF Token. | |
| Raises: | |
| LinterException: Equation must contain a relational | |
| operator. | |
| LinterException: Unexpected binary operator at the end of | |
| the equation. | |
| LinterException: Unexpected EOF, right side of the equation | |
| is missed. | |
| LinterException: Unexpected comma at the end of the | |
| equation. | |
| """ | |
| if token.prev_token.kind != TokenKind.SOF and not self._relation_provided: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Equation must contain a relational operator", | |
| ) | |
| if is_binary_operator(token.prev_token): | |
| raise LinterException( | |
| self._source, | |
| token.prev_token.location, | |
| "Unexpected binary operator at the end of the equation", | |
| ) | |
| if token.prev_token.kind == TokenKind.MUL: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected EOF, multiplier missed", | |
| ) | |
| if is_relational_operator(token.prev_token): | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected EOF, right side of the equation is missed", | |
| ) | |
| if token.prev_token.kind == TokenKind.COMMA: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected comma at the end of the equation", | |
| ) | |
| def _lint_binary_operator(self, token: Token) -> None: | |
| """Lint the binary operator Token. | |
| Args: | |
| token (Token): The binary operator Token. | |
| Raises: | |
| LinterException: Unexpected binary operator, term missed. | |
| """ | |
| if is_binary_operator(token.prev_token): | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected binary operator, term missed", | |
| ) | |
| if token.prev_token.kind == TokenKind.MUL: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected binary operator, multiplier missed", | |
| ) | |
| def _lint_multiplication_operator(self, token: Token) -> None: | |
| """Lint the multiplication operator Token. | |
| Args: | |
| token (Token): The multiplication operator Token. | |
| Raises: | |
| LinterException: Unexpected multiplication operator, term | |
| missed. | |
| """ | |
| if ( | |
| is_binary_operator(token.prev_token) | |
| or is_relational_operator(token.prev_token) | |
| or token.prev_token.kind == TokenKind.COMMA | |
| ): | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected multiplication operator, term missed", | |
| ) | |
| if token.prev_token.kind == TokenKind.MUL: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected multiplication operator, multiplier missed", | |
| ) | |
| def _lint_relational_operator(self, token: Token) -> None: | |
| """Lint the relational operator Token. | |
| Args: | |
| token (Token): The relational operator Token. | |
| Raises: | |
| LinterException: Equation must contain only one relational | |
| operator. | |
| LinterException: Unexpected binary operator, term missed. | |
| LinterException: Unexpected relational operator, left side | |
| of the equation is missed. | |
| """ | |
| if token.prev_token.kind in (TokenKind.SOF, TokenKind.COMMA): | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected relational operator, left side of the equation is missed", | |
| ) | |
| if self._relation_provided: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Equation must contain only one relational operator", | |
| ) | |
| if is_binary_operator(token.prev_token): | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected binary operator, term missed", | |
| ) | |
| if token.prev_token.kind == TokenKind.MUL: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected relational operator, multiplier missed", | |
| ) | |
| def _lint_variable(self, token: Token) -> None: | |
| """Lint the variable Token. | |
| Args: | |
| token (Token): The variable Token. | |
| Raises: | |
| LinterException: Term must contain no more than one | |
| variable. | |
| """ | |
| if self._variable_provided: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Term must contain no more than one variable", | |
| ) | |
| def _lint_comma(self, token: Token) -> None: | |
| """Lint the comma Token. | |
| Args: | |
| token (Token): The comma Token. | |
| Raises: | |
| LinterException: Unexpected comma at the beginning of the | |
| equation. | |
| LinterException: Unexpected comma, equation missed. | |
| LinterException: Unexpected comma at the end of the | |
| equation. | |
| """ | |
| if token.prev_token.kind == TokenKind.SOF: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected comma at the beginning of the equation", | |
| ) | |
| if not self._relation_provided: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Equation must contain a relational operator", | |
| ) | |
| if is_binary_operator(token.prev_token): | |
| raise LinterException( | |
| self._source, | |
| token.prev_token, | |
| "Unexpected binary operator at the end of the equation", | |
| ) | |
| if token.prev_token.kind == TokenKind.MUL: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected comma, multiplier missed", | |
| ) | |
| if is_relational_operator(token.prev_token): | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected comma, right side of the equation is missed", | |
| ) | |
| if token.prev_token.kind == TokenKind.COMMA: | |
| raise LinterException( | |
| self._source, | |
| token.location, | |
| "Unexpected comma, equation missed", | |
| ) | |
| __all__ = ("Linter",) | |