khushpatel2002's picture
Upload 22 files
e4806d5
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",)