diff --git a/.gitignore b/.gitignore index 710a131..d5fc864 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,6 @@ tags .idea .ropeproject .cache +.mypy_cache /dist /build diff --git a/lark/exceptions.pyi b/lark/exceptions.pyi new file mode 100644 index 0000000..6c3c4ab --- /dev/null +++ b/lark/exceptions.pyi @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- + +from typing import Dict, Iterable, Callable +from .tree import Tree + + +class LarkError(Exception): + pass + + +class GrammarError(LarkError): + pass + + +class ParseError(LarkError): + pass + + +class LexError(LarkError): + pass + + +class UnexpectedInput(LarkError): + pos_in_stream: int + + def get_context(self, text: str, span: int = 40): + ... + + def match_examples( + self, + parse_fn: Callable[[str], Tree], + examples: Dict[str, Iterable[str]] + ): + ... + + +class UnexpectedToken(ParseError, UnexpectedInput): + pass + + +class UnexpectedCharacters(LexError, UnexpectedInput): + pass diff --git a/lark/lark.pyi b/lark/lark.pyi new file mode 100644 index 0000000..420cc59 --- /dev/null +++ b/lark/lark.pyi @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +from typing import List, Dict, IO, Callable, Union, Optional, Literal +from .visitors import Transformer +from .lexer import Lexer, Token +from .tree import Tree + +_Start = Union[None, str, List[str]] + + +class Lark: + + def __init__( + self, + grammar: Union[str, IO[str]], + *, + start: _Start = ..., + parser: Literal["earley", "lalr", "cyk"] = ..., + lexer: Optional[Lexer] = ..., + transformer: Optional[Transformer] = ..., + postlex: Optional[Literal["standard", "contextual"]] = ..., + ambiguity: Literal["explicit", "resolve"] = ..., + debug: bool = False, + keep_all_tokens: bool = False, + propagate_positions: bool = False, + maybe_placeholders: bool = False, + lexer_callbacks: Dict[str, Callable[[Token], Token]] + ): + ... + + def parse(self, text: str, start: _Start = None) -> Tree: + ... diff --git a/lark/lexer.pyi b/lark/lexer.pyi new file mode 100644 index 0000000..abe321b --- /dev/null +++ b/lark/lexer.pyi @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +from typing import Tuple, Iterator, Sized +from abc import abstractmethod, ABC + + +class Pattern(ABC): + + @abstractmethod + def to_regexp(self) -> str: + ... + + +class PatternStr(Pattern): + + def to_regexp(self) -> str: + ... + + +class PatternRE(Pattern): + + def to_regexp(self) -> str: + ... + + +class TerminalDef: + name: str + pattern: Pattern + priority: int + + +class Token(str): + type: str + pos_in_stream: int + line: int + column: int + end_line: int + end_column: int + end_pos: int + + +class Lexer(ABC): + + @abstractmethod + def lex(self, stream: Sized) -> Iterator[Token]: + ... + + +class TraditionalLexer(Lexer): + + def build(self) -> None: + ... + + def match(self, stream: str, pos: int) -> Tuple[str, str]: + ... + + def lex(self, stream: Sized) -> Iterator[Token]: + ... + + +class ContextualLexer(Lexer): + + def lex(self, stream: Sized) -> Iterator[Token]: + ... diff --git a/lark/py.typed b/lark/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/lark/reconstruct.pyi b/lark/reconstruct.pyi new file mode 100644 index 0000000..89e51d4 --- /dev/null +++ b/lark/reconstruct.pyi @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- + +from .lark import Lark +from .tree import Tree + + +class Reconstructor: + + def __init__(self, parser: Lark): + ... + + def reconstruct(self, tree: Tree) -> str: + ... diff --git a/lark/tree.pyi b/lark/tree.pyi new file mode 100644 index 0000000..b794f53 --- /dev/null +++ b/lark/tree.pyi @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +from typing import List, Callable, Iterator, Union, Optional +from .lexer import Token + + +class Tree: + + data: str + children: List[Union[str, Tree]] + meta: Token + + def __init__(self, data: str, children: List[Tree], meta: Optional[Token] = None): + ... + + def pretty(self, indent_str: str = ...) -> str: + ... + + def find_pred(self, pred: Callable[[Tree], bool]) -> Iterator[Tree]: + ... + + def find_data(self, data: str) -> Iterator[Tree]: + ... + + def iter_subtrees(self) -> Iterator[Tree]: + ... + + def iter_subtrees_topdown(self) -> Iterator[Tree]: + ... + + def __eq__(self, other: object) -> bool: + ... + + def __hash__(self) -> int: + ... + + +class SlottedTree(Tree): + pass diff --git a/lark/visitors.py b/lark/visitors.py index 30a2a65..12e296f 100644 --- a/lark/visitors.py +++ b/lark/visitors.py @@ -36,8 +36,12 @@ class _Decoratable: return cls +class _GenericMeta(type): + def __getitem__(self, _): + return self -class Transformer(_Decoratable): + +class Transformer(_Decoratable, metaclass=_GenericMeta): """Visits the tree recursively, starting with the leaves and finally the root (bottom-up) Calls its methods (provided by user via inheritance) according to tree.data @@ -171,7 +175,7 @@ class VisitorBase: return tree -class Visitor(VisitorBase): +class Visitor(VisitorBase, metaclass=_GenericMeta): """Bottom-up visitor, non-recursive Visits the tree, starting with the leaves and finally the root (bottom-up) @@ -224,7 +228,7 @@ def visit_children_decor(func): return inner -class Interpreter(_Decoratable): +class Interpreter(_Decoratable, metaclass=_GenericMeta): """Top-down visitor, recursive Visits the tree, starting with the root and finally the leaves (top-down) diff --git a/lark/visitors.pyi b/lark/visitors.pyi new file mode 100644 index 0000000..ac1367a --- /dev/null +++ b/lark/visitors.pyi @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- + +from typing import TypeVar, List, Callable, Generic, Type +from abc import ABC +from .tree import Tree + +_T = TypeVar('_T') +_R = TypeVar('_R') +_FUNC = Callable[..., _T] + + +class Transformer(ABC, Generic[_T]): + + def __init__(self, visit_tokens: bool = True): + ... + + def transform(self, tree: Tree) -> _T: + ... + + +class Transformer_InPlace(Transformer): + pass + + +class VisitorBase: + pass + + +class Visitor(VisitorBase, ABC, Generic[_T]): + + def visit(self, tree: Tree) -> Tree: + ... + + def visit_topdown(self, tree: Tree) -> Tree: + ... + + +class Visitor_Recursive(VisitorBase): + + def visit(self, tree: Tree) -> Tree: + ... + + def visit_topdown(self, tree: Tree) -> Tree: + ... + + +class Interpreter(ABC, Generic[_T]): + + def visit(self, tree: Tree) -> _T: + ... + + def visit_children(self, tree: Tree) -> List[_T]: + ... + + +_InterMethod = Callable[[Type[Interpreter], _T], _R] + + +def v_args( + inline: bool = False, + meta: bool = False, + tree: bool = False +) -> Callable[[_FUNC], _FUNC]: + ... + + +def visit_children_decor(func: _InterMethod) -> _InterMethod: + ... + + +class Discard(Exception): + pass + + +# Deprecated +class InlineTransformer: + pass + + +# Deprecated +def inline_args(obj: _FUNC) -> _FUNC: + ... diff --git a/setup.py b/setup.py index 8543fd4..650bc16 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( requires = [], install_requires = [], - package_data = { '': ['*.md', '*.lark'] }, + package_data = { '': ['*.md', '*.lark', '*.pyi'], 'lark': ['py.typed'] }, test_suite = 'tests.__main__',