76 lines
1.8 KiB
Python
76 lines
1.8 KiB
Python
from dataclasses import dataclass
|
|
from enum import Enum, auto
|
|
|
|
from lsprotocol.types import Location, Position, Range
|
|
|
|
from skillls.types import URI
|
|
|
|
|
|
class SyntaxError(Exception):
|
|
pass
|
|
|
|
|
|
class ParenMismatchErrorKind(Enum):
|
|
TooManyClosed = "Found too many closing parens"
|
|
TooManyOpened = "Found too many open parens"
|
|
|
|
|
|
@dataclass
|
|
class ParenMismatchError(SyntaxError):
|
|
kind: ParenMismatchErrorKind
|
|
loc: Range
|
|
|
|
|
|
def _check_for_matching_parens(content: str) -> list[Exception]:
|
|
excs: list[Exception] = []
|
|
|
|
opened = 0
|
|
line = 0
|
|
col = 0
|
|
last_open: Position = Position(0, 0)
|
|
last_close: Position = Position(0, 0)
|
|
for char in content:
|
|
match char:
|
|
case "(":
|
|
opened += 1
|
|
last_open = Position(line, col)
|
|
|
|
case ")":
|
|
opened -= 1
|
|
if opened < 0:
|
|
excs.append(
|
|
ParenMismatchError(
|
|
ParenMismatchErrorKind.TooManyClosed,
|
|
Range(Position(line, col), Position(line, col + 1)),
|
|
)
|
|
)
|
|
opened = 0
|
|
last_close = Position(line, col)
|
|
case "\n":
|
|
line += 1
|
|
col = -1
|
|
|
|
case _:
|
|
pass
|
|
|
|
col += 1
|
|
|
|
if opened > 0:
|
|
excs.append(
|
|
ParenMismatchError(
|
|
ParenMismatchErrorKind.TooManyOpened,
|
|
Range(last_open, Position(last_open.line, last_open.character + 1)),
|
|
)
|
|
)
|
|
|
|
return excs
|
|
|
|
|
|
def check_content_for_errors(clean_content: str) -> None:
|
|
excs: list[Exception] = []
|
|
|
|
excs.extend(_check_for_matching_parens(clean_content))
|
|
|
|
if excs:
|
|
raise ExceptionGroup("", excs)
|