Compare commits

..

6 Commits

Author SHA1 Message Date
acereca 9e5d32a420 try zig 2025-01-16 20:27:36 +01:00
acereca 56883c0bed add lsfw 2024-08-11 17:16:58 +02:00
acereca 217a4e032e add zig gitignores 2024-08-10 15:18:40 +02:00
acereca 6110b248d1 add tokenizer 2024-08-10 15:18:09 +02:00
acereca 78b6dfbcee add example skill file 2024-08-10 15:17:59 +02:00
acereca e30ff74cec initial commit 2024-08-09 21:36:13 +02:00
32 changed files with 1022 additions and 1422 deletions
+2 -5
View File
@@ -1,5 +1,2 @@
.venv/*
.idea/*
*.egg-info/*
**/__pycache__/*
*.log
zig-cache
zig-out
-20
View File
@@ -1,20 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "main",
"type": "python",
"request": "launch",
"program": "/home/patrick/git/skill-ls/.venv/bin/skillls",
"python": "/home/patrick/git/skill-ls/.venv/bin/python"
},
{
"name": "main",
"type": "python",
"request": "launch",
"module": "skillls.parsing.iterative",
"python": "/home/patrick/git/skill-ls/.venv/bin/python"
}
]
}
+91
View File
@@ -0,0 +1,91 @@
const std = @import("std");
// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
// runner.
pub fn build(b: *std.Build) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const lib = b.addStaticLibrary(.{
.name = "skill-ls",
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
});
// This declares intent for the library to be installed into the standard
// location when the user invokes the "install" step (the default step when
// running `zig build`).
b.installArtifact(lib);
const exe = b.addExecutable(.{
.name = "skill-ls",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// This declares intent for the executable to be installed into the
// standard location when the user invokes the "install" step (the default
// step when running `zig build`).
b.installArtifact(exe);
// This *creates* a Run step in the build graph, to be executed when another
// step is evaluated that depends on it. The next line below will establish
// such a dependency.
const run_cmd = b.addRunArtifact(exe);
// By making the run step depend on the install step, it will be run from the
// installation directory rather than directly from within the cache directory.
// This is not necessary, however, if the application depends on other installed
// files, this ensures they will be present and in the expected location.
run_cmd.step.dependOn(b.getInstallStep());
// This allows the user to pass arguments to the application in the build
// command itself, like this: `zig build run -- arg1 arg2 etc`
if (b.args) |args| {
run_cmd.addArgs(args);
}
// This creates a build step. It will be visible in the `zig build --help` menu,
// and can be selected like this: `zig build run`
// This will evaluate the `run` step rather than the default, which is "install".
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const lib_unit_tests = b.addTest(.{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
});
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
const exe_unit_tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
// Similar to creating the run step earlier, this exposes a `test` step to
// the `zig build --help` menu, providing a way for the user to request
// running the unit tests.
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_lib_unit_tests.step);
test_step.dependOn(&run_exe_unit_tests.step);
}
+70
View File
@@ -0,0 +1,70 @@
.{
.name = "skill-ls",
// This is a [Semantic Version](https://semver.org/).
// In a future version of Zig it will be used for package deduplication.
.version = "0.0.0",
// This field is optional.
// This is currently advisory only; Zig does not yet do anything
// with this value.
//.minimum_zig_version = "0.11.0",
// This field is optional.
// Each dependency must either provide a `url` and `hash`, or a `path`.
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
// Once all dependencies are fetched, `zig build` no longer requires
// internet connectivity.
.dependencies = .{
.lsfw = .{
.path = "lib/lsfw",
}
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
//.example = .{
// // When updating this field to a new URL, be sure to delete the corresponding
// // `hash`, otherwise you are communicating that you expect to find the old hash at
// // the new URL.
// .url = "https://example.com/foo.tar.gz",
//
// // This is computed from the file contents of the directory of files that is
// // obtained after fetching `url` and applying the inclusion rules given by
// // `paths`.
// //
// // This field is the source of truth; packages do not come from a `url`; they
// // come from a `hash`. `url` is just one of many possible mirrors for how to
// // obtain a package matching this `hash`.
// //
// // Uses the [multihash](https://multiformats.io/multihash/) format.
// .hash = "...",
//
// // When this is provided, the package is found in a directory relative to the
// // build root. In this case the package's hash is irrelevant and therefore not
// // computed. This field and `url` are mutually exclusive.
// .path = "foo",
// // When this is set to `true`, a package is declared to be lazily
// // fetched. This makes the dependency only get fetched if it is
// // actually used.
// .lazy = false,
//},
},
// Specifies the set of files and directories that are included in this package.
// Only files and directories listed here are included in the `hash` that
// is computed for this package.
// Paths are relative to the build root. Use the empty string (`""`) to refer to
// the build root itself.
// A directory listed here means that all files within, recursively, are included.
.paths = .{
// This makes *all* files, recursively, included in this package. It is generally
// better to explicitly list the files and directories instead, to insure that
// fetching from tarballs, file system paths, and version control all result
// in the same contents hash.
"",
// For example...
//"build.zig",
//"build.zig.zon",
//"src",
//"LICENSE",
//"README.md",
},
}
+19
View File
@@ -0,0 +1,19 @@
;;; this is some example module docstring
; random comment
a=1+2.0*3e2-4/ 5
b_var->a
(list 1 2 34)
'(1 2 3 4)
(procedure func_name(param1 param2 @keys (a nil))
; some struff to do
)
"srting"
"wqdwd\"qwesfwf"
-34
View File
@@ -1,34 +0,0 @@
example = nil
example2 = example
(call qdwdq)
;; func2(g_arg1 g_arg2 ?g_args1 1 ?g_argw 2) => nil
(procedure Func2(arg1 arg2 @keys (args "ss") (argw 2) "ggng")
(let ()
; some stuff to do
a = some_obj->field1
some_obj->field2 = 2
db_obj->help()
args = 2
args
(procedure Wqrqw(a1 a2 @keys (a "12") "sqd")
)
)
)
(let (some vars (default "sd"))
; ... some wall of text
"))\""
wqdqwf = '(doqwf)
'wq
var = 1.3
vars = 231
qqvwv
if(expr then expr else expr)
cfunc()
)
somfunccall("somecalcfunc()")
-42
View File
@@ -1,42 +0,0 @@
[project]
name = "skillls"
version = "0.1.0"
dependencies = [
"parsimonious~=0.10.0",
"pygls",
"rich",
"tree-sitter>=0.24.0",
"tree-sitter-skill>=0.1.5",
]
[project.optional-dependencies]
dev = [
"black",
"mypy",
"ruff",
"pytest",
"types-parsimonious",
]
[build-system]
build-backend = 'setuptools.build_meta'
requires = [
'setuptools',
]
[project.scripts]
skillls = "skillls.main:main"
[tools.black]
line-length = 100
target-version = "py311"
include = "skillls"
[tools.ruff]
line-length = 100
include = ['ALL']
[tool.uv.sources]
tree-sitter-skill = { git = "ssh://git@git.acereca.net/acereca/tree-sitter-skill.git" }
View File
View File
-145
View File
@@ -1,145 +0,0 @@
from abc import ABC
from collections.abc import Mapping
from dataclasses import dataclass, field
from enum import Enum
from typing import ClassVar
from lsprotocol.types import SymbolKind
class SkillDataType(Enum):
array = "a"
"""array"""
ddUserType = "b"
"""Boolean"""
opfcontext = "C"
"""OPF Context"""
dbobject = "d"
"""Cadence database object (CDBA)"""
envobj = "e"
"""environment"""
flonum = "f"
"""floating-point number"""
opffile = "F"
"""OPF file ID"""
general = "g"
"""any data type"""
nil = "g"
""""""
dgbSpecIlUserType = "G"
"""gdm spec"""
hdbobject = "h"
"""hierarchical database configuration object"""
list = "l"
"""linked list"""
nmpIlUserType = "m"
"""nmpll user type"""
cdsEvalObject = "M"
"""Cadence evaluation object"""
number = "n"
"""integere of floating point number"""
userType = "o"
"""user defined type (other)"""
port = "p"
"""I/O port"""
gdmspecListIlUSerType = "q"
""" gdm spec list"""
defstruct = "r"
"""defstruct"""
rodObj = "R"
"""relative object design (ROD) object"""
symbol = "s"
"""symbol"""
stringSymbol = "S"
"""symbol or character string"""
string = "t"
"""character string (text)"""
function = "u"
"""function object, either the name if a function (symbol) or a lambda function body (list)"""
funobj = "U"
"""function object"""
hdbpath = "v"
""""""
wtype = "w"
"""window type"""
integer = "x"
"""integer type"""
binary = "y"
"""binary function"""
pointer = "&"
"""pointer type"""
@dataclass(frozen=True)
class Builtin(ABC):
token: str
kind: ClassVar[SymbolKind]
@dataclass(frozen=True)
class Variable(Builtin):
kind: ClassVar[SymbolKind] = SymbolKind.Variable
typ: SkillDataType
default: str | None = None
@dataclass(frozen=True)
class AnonymousVariable(Builtin):
kind: ClassVar[SymbolKind] = SymbolKind.Variable
typ: SkillDataType
default: str | None = None
@dataclass(frozen=True)
class Procedure(Builtin):
kind: ClassVar[SymbolKind] = SymbolKind.Function
args: Mapping[str, Variable] = field(default_factory=dict)
rest: Variable | None = None
kwargs: Mapping[str, Variable] | Mapping[str, AnonymousVariable] = field(
default_factory=dict
)
"""list of ``Variable` if ``@key`` was used, and ``AnonymousVariable`` if ``@option`` was used"""
ret: SkillDataType = SkillDataType.nil
@property
def has_options(self) -> bool:
return bool(self.kwargs) and isinstance(
next(iter(self.kwargs.values())),
AnonymousVariable,
)
@property
def has_keys(self) -> bool:
return bool(self.kwargs) and isinstance(
next(iter(self.kwargs.values())),
Variable,
)
-6
View File
@@ -1,6 +0,0 @@
;; append
append(
l_list1
l_list2
) => l_result
-21
View File
@@ -1,21 +0,0 @@
from collections.abc import Mapping
from .common import Procedure, SkillDataType, Variable
NUM = SkillDataType.number
ANY = SkillDataType.general
FUNCTIONS: Mapping[str, Procedure] = {
"plus": Procedure(
"plus",
ret=NUM,
args={
"op1": Variable("op1", NUM),
"op2": Variable("op2", NUM),
},
rest=Variable("op3", NUM),
),
}
FUNCTIONS["plus"]
-37
View File
@@ -1,37 +0,0 @@
from dataclasses import dataclass, field
from typing import Any, Generic, TypeVar, TypeVarTuple, Union, Unpack
T = TypeVar("T")
L = TypeVarTuple("L")
ID = int
@dataclass
class Cache(Generic[*L, T]):
cached: list[T] = field(default_factory=list)
lookups: dict[type[Union[*L]], dict[Union[*L], ID]] = field(default_factory=dict)
def __getitem__(self, key: Union[*L]) -> T:
id = self.lookups[type(key)][key]
return self.cached[id]
def __setitem__(self, keys: tuple[Unpack[L]], value: T) -> None:
print(type(keys), keys)
id = len(self.cached)
self.cached.append(value)
for key in keys:
self.lookups.setdefault(type(key), {})
self.lookups[type(key)][key] = id
if __name__ == "__main__":
c = Cache[int, str, str]()
print(c)
c[0, None] = "a"
print(c)
-34
View File
@@ -1,34 +0,0 @@
skill = inline_expr+
expr = (inline_expr / nl)
inline_expr = (listraw / listc / listskill / inline_get / inline_op / inline_assign / ws / nl)
inline_assign = TOKEN ws* "=" ws* (inline_expr / LITERAL / TOKEN)
inline_op = TOKEN ws* inline_op_symbol ws* (inline_expr / TOKEN / LITERAL)
inline_op_symbol = ~"[*-+/]"
inline_get = TOKEN inline_get_symbol (inline_expr / TOKEN / LITERAL)
inline_get_symbol = ~"(~>|->)"
listraw = "'" list_start expr* list_end
listc = TOKEN list_start expr* list_end
listskill = list_start expr* list_end
list_start = "("
list_end = ")"
TOKEN = ~"[a-zA-Z_][_a-zA-Z0-9]+"
LITERAL = L_num / L_t / L_nil / L_str
L_num = ~"[0-9]+(\.[0-9]+)?"
L_t = "t"
L_nil = "nil"
L_str = delim_str any_str delim_str
delim_str = "\""
any_str = ~"[^\"]*"
ws = ~"\\h"
nl = ~"\\n"
-276
View File
@@ -1,276 +0,0 @@
from collections.abc import Callable, Generator, Sequence
from dataclasses import dataclass, field
from difflib import Differ
from itertools import chain
from logging import DEBUG, INFO, basicConfig, debug, error, getLogger, info, warning
from re import findall, finditer, fullmatch, match as rematch
import re
from time import time
from cattrs import Converter
from lsprotocol.types import (
INLAY_HINT_RESOLVE,
TEXT_DOCUMENT_DID_CHANGE,
TEXT_DOCUMENT_DID_OPEN,
TEXT_DOCUMENT_DID_SAVE,
TEXT_DOCUMENT_DOCUMENT_SYMBOL,
TEXT_DOCUMENT_HOVER,
TEXT_DOCUMENT_INLAY_HINT,
WORKSPACE_INLAY_HINT_REFRESH,
WORKSPACE_SEMANTIC_TOKENS_REFRESH,
CompletionItem,
Diagnostic,
DiagnosticSeverity,
DidChangeTextDocumentParams,
DidOpenTextDocumentParams,
DidSaveTextDocumentParams,
DocumentSymbol,
DocumentSymbolParams,
Hover,
HoverParams,
InlayHint,
InlayHintKind,
InlayHintParams,
MessageType,
NotebookDocumentSyncOptions,
Position,
Range,
SymbolKind,
TextDocumentContentChangeEvent,
TextDocumentContentChangeEvent_Type1,
TextDocumentSyncKind,
)
from pygls.protocol import LanguageServerProtocol, default_converter
from tree_sitter_skill import language as skill_lang
from tree_sitter import Language, Node, Parser, Query, Tree
from pygls.server import LanguageServer
from pygls.workspace import TextDocument
from .cache import Cache
SKILL_LANG = Language(skill_lang())
SKILL_PARSER = Parser(SKILL_LANG)
URI = str
basicConfig(
filename="skillls.log",
filemode="w",
level=DEBUG,
format="%(asctime)s [%(levelname)s]: %(message)s",
)
logger = getLogger()
cache: Cache[str, CompletionItem] = Cache()
def in_range(what: Position, area: Range) -> bool:
return (what >= area.start) and (what <= area.end)
def find_end(start: Position, lines: list[str]) -> Position:
count = 0
in_str: bool = False
last = ""
for row, line in enumerate(lines[start.line :]):
if row == 0:
line = line[start.character :]
row += start.character
for col, char in enumerate(line[start.character :] if row == 0 else line):
match char:
case "(":
if not in_str:
count += 1
case ")":
if not in_str:
if count > 0:
count -= 1
if count == 0:
return Position(start.line + row, col)
case '"':
if not (in_str and last == "\\"):
in_str = not in_str
case _:
last = char
last = char
error(f"did not fin end for start at {start}")
return Position(len(lines), len(lines[-1]))
@dataclass(frozen=True)
class Environment:
range: Range
@dataclass(frozen=True)
class LetEnvironment(Environment):
locals: set[str] = field(default_factory=set)
def offset_range(range: Range, lines: int, cols: int = 0) -> Range:
return Range(
Position(
range.start.line + lines,
range.start.character + cols,
),
Position(
range.end.line + lines,
range.end.character + cols,
),
)
#
# @dataclass(frozen=True)
# class ProcEnvironment(Environment):
# name: str
# args: tuple[DocumentSymbol, ...]
# kwargs: tuple[DocumentSymbol, ...]
# rest: DocumentSymbol | None = None
#
# @property
# def locals(self) -> tuple[DocumentSymbol, ...]:
# ret = [*self.args, *self.kwargs]
# if self.rest:
# ret.append(self.rest)
#
# return tuple(ret)
class SkillLanguageServer(LanguageServer):
contents: dict[str, TextDocument]
trees: dict[str, Tree]
def __init__(
self,
name: str,
version: str,
loop=None,
protocol_cls: type[LanguageServerProtocol] = LanguageServerProtocol,
converter_factory: Callable[[], Converter] = default_converter,
text_document_sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental,
notebook_document_sync: NotebookDocumentSyncOptions | None = None,
max_workers: int = 2,
):
super().__init__(
name,
version,
loop,
protocol_cls,
converter_factory,
text_document_sync_kind,
notebook_document_sync,
max_workers,
)
self.trees = {}
self.contents = {}
def parse(self, doc: TextDocument) -> None:
parsed = SKILL_PARSER.parse(doc.source.encode("utf8"), encoding="utf8")
self.trees[doc.uri] = parsed
self.contents[doc.uri] = doc
def update(self, uri: str, changes: list[TextDocumentContentChangeEvent]) -> None:
for change in changes:
if isinstance(change, TextDocumentContentChangeEvent_Type1):
logger.debug(f"updating {change.range}")
change_fixed = TextDocumentContentChangeEvent_Type1(
offset_range(change.range, -1),
change.text,
change.range_length,
)
old = self.contents[uri].lines
self.contents[uri].apply_change(change)
d = Differ()
logger.debug("".join(d.compare(old, self.contents[uri].lines)))
else:
pass
self.trees[uri] = SKILL_PARSER.parse(
self.contents[uri].source.encode("utf8"),
old_tree=self.trees[uri],
)
def _get_leaves(self, node: Node) -> list[Node]:
if node.children:
return [l for child in node.children for l in self._get_leaves(child)]
return [node]
def _diagnose_errors(self, uri: str) -> list[Diagnostic]:
diags: list[Diagnostic] = []
q = SKILL_LANG.query("(ERROR) @error")
nodes = (
q.captures(self.trees[uri].root_node)["error"]
if self.trees.get(uri)
else []
)
for node in nodes:
if node.type == "ERROR":
logger.error(node)
logger.error(node.range)
content = node.text.decode("utf8") if node.text else ""
range = Range(
Position(*node.range.start_point), Position(*node.range.end_point)
)
if "UNEXPECTED" in str(node):
msg = f"unexpected '{content}'"
else:
msg = str()
diags.append(
Diagnostic(
range,
msg,
severity=DiagnosticSeverity.Error,
),
)
return diags
def diagnose(self, uri: str) -> list[Diagnostic]:
diags: list[Diagnostic] = []
diags.extend(self._diagnose_errors(uri))
return diags
server = SkillLanguageServer("skillls", "v0.3")
# @server.feature(TEXT_DOCUMENT_DID_SAVE)
@server.feature(TEXT_DOCUMENT_DID_OPEN)
def on_open(ls: SkillLanguageServer, params: DidSaveTextDocumentParams) -> None:
doc = server.workspace.get_text_document(params.text_document.uri)
ls.parse(doc)
diags = ls.diagnose(doc.uri)
ls.publish_diagnostics(doc.uri, diags)
@server.feature(TEXT_DOCUMENT_DID_CHANGE)
def on_change(ls: SkillLanguageServer, params: DidChangeTextDocumentParams) -> None:
ls.update(params.text_document.uri, changes=params.content_changes)
diags = ls.diagnose(params.text_document.uri)
ls.publish_diagnostics(params.text_document.uri, diags)
@server.feature(TEXT_DOCUMENT_DOCUMENT_SYMBOL)
def doc_symbols(
ls: SkillLanguageServer,
params: DocumentSymbolParams,
) -> list[DocumentSymbol]:
# return ls.procs + ls.lets + ls.defs + ls.globals
return []
def main():
server.start_io()
View File
-32
View File
@@ -1,32 +0,0 @@
from dataclasses import dataclass
from enum import Enum, auto
from typing import ClassVar, DefaultDict
from .location import Range
from .tokenize import BaseToken
class ContextType(Enum):
Use = auto()
Assign = auto()
Declare = auto()
Unbind = auto()
@dataclass(frozen=True)
class Context:
lookup: ClassVar[dict[ContextType, list["Context"]]] = {}
typ: ContextType
token: list[BaseToken]
def __post_init__(self):
type(self).lookup.setdefault(self.typ, [])
type(self).lookup[self.typ].append(self)
@property
def range(self) -> Range:
new_range = self.token[0].range
for token in self.token[1:]:
new_range += token.range
return new_range
-296
View File
@@ -1,296 +0,0 @@
from abc import ABC
from dataclasses import dataclass, field
from enum import Enum
from logging import getLogger
import re
from pathlib import Path
from typing import NamedTuple, Self
from lsprotocol.types import (
Diagnostic,
DiagnosticSeverity,
DocumentSymbol,
Position,
Range,
SymbolKind,
)
logger = getLogger(__name__)
class Pair(NamedTuple):
start: str
end: str
class SyntaxPair(Enum):
Paren = Pair("(", ")")
Square = Pair("[", "]")
@classmethod
def by_start_elem(cls, start: str) -> Self:
for option in cls:
if option.value[0] == start:
return option
raise ValueError(f"`{start}` not a valid start character")
@classmethod
def by_end_elem(cls, end: str) -> Self:
for option in cls:
if option.value[1] == end:
return option
raise ValueError(f"`{end}` not a valid end character")
def char_range(line: int, char: int) -> Range:
return Range(Position(line, char), Position(line, char + 1))
def pair_mismatch(line: int, char: int, msg: str) -> Diagnostic:
return Diagnostic(
char_range(line, char),
msg,
severity=DiagnosticSeverity.Error,
)
class StackElement(NamedTuple):
range: Range
elem: SyntaxPair
WHITESPACE_OR_PAREN = re.compile(r"(\s|\(|\)|\[|\]|\'\()+")
TOKEN_REGEX = re.compile(r"\w[a-zA-Z0-9_]*")
NUMBER_REGEX = re.compile(r"\d+(\.\d+)?")
OPERATORS = re.compile(r"(->|~>|\+|\-|\*|\/|\=|\|\||\&\&)")
@dataclass
class TreeToken(ABC):
content: str
range: Range
def String(content: str, range: Range) -> DocumentSymbol:
return DocumentSymbol(
name=content,
range=range,
kind=SymbolKind.String,
selection_range=range,
)
def Operator(content: str, range: Range) -> DocumentSymbol:
return DocumentSymbol(
name=content,
range=range,
kind=SymbolKind.Operator,
selection_range=range,
)
def Number(content: str, range: Range) -> DocumentSymbol:
return DocumentSymbol(
name=content,
range=range,
kind=SymbolKind.Number,
selection_range=range,
)
def Token(content: str, range: Range) -> DocumentSymbol:
return DocumentSymbol(
name=content,
range=range,
kind=SymbolKind.Variable,
selection_range=range,
)
RawIndex = int
ColIndex = int
LineIndex = int
@dataclass
class TokenParser:
_in_string: bool = False
_in_comment: bool = False
_token_tree: list[DocumentSymbol] = field(default_factory=list)
_current: str = ""
_line_indices: list[RawIndex] = field(default_factory=list)
def _get_line(self, index: RawIndex) -> tuple[LineIndex, RawIndex]:
for line, newline_pos in enumerate(self._line_indices):
if index < newline_pos:
return line, self._line_indices[line - 1] if line > 0 else 0
return len(self._line_indices), self._line_indices[-1]
def _get_range(self, start: RawIndex, end: RawIndex) -> Range:
start_line, start_line_index = self._get_line(start)
start_col = start - start_line_index - 1
end_line, end_line_index = self._get_line(end)
end_col = end - end_line_index - 1
return Range(Position(start_line, start_col), Position(end_line, end_col))
def _parse_string(self, raw: str, index: int) -> int:
stop = raw.index('"', index + 1)
self._token_tree.append(
String(raw[index : stop + 1], self._get_range(index, stop))
)
return stop + 1
def _parse_comment(self, raw: str, index: int) -> int:
stop = raw.index("\n", index)
# self._token_tree.append(Comment(raw[index:stop], self._get_range(index, stop)))
return stop + 1
def _parse_whitespace(self, raw: str, index: int) -> int:
if m := WHITESPACE_OR_PAREN.search(raw, index):
stop = m.end()
else:
stop = index + 1
# self._token_tree.append(Whitespace(raw[index:stop]))
return stop
def _parse_operator(self, raw: str, index: int) -> int:
if m := OPERATORS.search(raw, index):
stop = m.end()
else:
stop = index + 1
self._token_tree.append(
Operator(raw[index:stop], self._get_range(index, stop - 1))
)
return stop + 1
def _parse_token(self, raw: str, index: int) -> int:
if m := TOKEN_REGEX.search(raw, index):
stop = m.end()
else:
stop = index + 1
self._token_tree.append(
Token(raw[index:stop], self._get_range(index, stop - 1))
)
return stop
def _parse_number(self, raw: str, index: int) -> int:
if m := NUMBER_REGEX.search(raw, index):
stop = m.end()
else:
stop = index + 1
self._token_tree.append(
Number(raw[index:stop], self._get_range(index, stop - 1))
)
return stop
def prepare_content(self, raw: str) -> None:
self._line_indices = [i for i, char in enumerate(raw) if char == "\n"]
max_index = len(raw)
index = 0
while index < max_index:
if raw[index] == '"':
index = self._parse_string(raw, index)
elif raw[index] == ";":
index = self._parse_comment(raw, index)
elif WHITESPACE_OR_PAREN.match(raw[index : index + 2]):
index = self._parse_whitespace(raw, index)
elif OPERATORS.match(raw[index]):
index = self._parse_operator(raw, index)
elif NUMBER_REGEX.match(raw[index]):
index = self._parse_number(raw, index)
else:
index = self._parse_token(raw, index)
@dataclass()
class IterativeParser:
_stack: list[StackElement] = field(default_factory=list)
def peek(self) -> StackElement:
return self._stack[-1]
def pop(self) -> StackElement:
return self._stack.pop()
def push(self, pair: StackElement) -> None:
return self._stack.append(pair)
def __call__(self, raw: list[str]) -> list[Diagnostic]:
in_string = False
errs = []
for line, raw_line in enumerate(raw):
for char, raw_char in enumerate(raw_line):
match raw_char:
case ";":
if not in_string:
break
case '"':
in_string = not in_string
case "(" | "[":
if not in_string:
self.push(
StackElement(
char_range(line, char),
SyntaxPair.by_start_elem(raw_char),
)
)
case "]" | ")":
if not in_string:
if not self._stack:
errs.append(
pair_mismatch(
line, char, f"one {raw_char} too much"
)
)
continue
expected = SyntaxPair.by_end_elem(raw_char)
elem = self._stack.pop()
if elem.elem == expected:
continue
if self._stack and self._stack[-1].elem == expected:
errs.append(
pair_mismatch(
line, char, f"unclosed {elem.elem.value.start}"
)
)
self._stack.pop()
self._stack.append(elem)
else:
errs.append(
pair_mismatch(
line, char, f"one {raw_char} too much"
)
)
self._stack.append(elem)
for rest in self._stack:
errs.append(
Diagnostic(
rest.range,
f"unclosed {rest.elem.value.start}",
severity=DiagnosticSeverity.Error,
)
)
self._stack = []
return errs
if __name__ == "__main__":
example = Path(__file__).parent.parent.parent / "examples" / "example.il"
t = TokenParser()
t.prepare_content(example.read_text())
print(t._token_tree)
-42
View File
@@ -1,42 +0,0 @@
from dataclasses import dataclass
from functools import cached_property
from typing import overload
from lsprotocol.types import Position, Range
from parsimonious.nodes import Node
@dataclass(frozen=True)
class Locator:
raw: list[str]
def _locate_pos(self, index: int) -> Position:
counter = 0
line = 0
for ix, raw_line in enumerate(self.raw):
if counter + len(raw_line) + 1 > index:
line = ix
break
else:
counter += len(raw_line) + 1
print(counter, line)
return Position(line + 1, index - counter + 1)
@overload
def locate(self, index: int) -> Position:
...
@overload
def locate(self, index: Node) -> Range:
...
def locate(self, index: int | Node) -> Position | Range:
if isinstance(index, int):
return self._locate_pos(index)
print(index.start, index.end)
start = self._locate_pos(index.start)
end = self._locate_pos(index.end)
return Range(start, end)
-1
View File
@@ -1 +0,0 @@
+91
View File
@@ -0,0 +1,91 @@
const tkz = @import("tokenize.zig");
const hlp = @import("helpers.zig");
const std = @import("std");
pub const TokenClass = enum {
symbol,
string,
comment,
docstring,
number,
nil,
t,
list_start,
list_lazy_start,
list_end,
operator,
};
pub const ClassifiedToken = struct {
tok: tkz.Token,
cls: TokenClass,
};
const operators = std.ComptimeStringMap(void, .{
.{"->"},
.{"~>"},
.{"/="},
.{"*="},
.{"-="},
.{"+="},
.{"||"},
.{"&&"},
.{"="},
.{"+"},
.{"-"},
.{"*"},
.{"/"},
.{"~"},
.{"%"},
.{"@keys"},
.{"@rest"},
});
const numbers = std.ComptimeStringMap(void, .{
.{"0"},
.{"1"},
.{"2"},
.{"3"},
.{"4"},
.{"5"},
.{"6"},
.{"7"},
.{"8"},
.{"9"},
});
fn classify(tok: tkz.Token) ClassifiedToken {
return ClassifiedToken{
.tok = tok,
.cls = if (operators.has(tok.value))
TokenClass.operator
else if (std.mem.eql(u8, "'(", tok.value))
TokenClass.list_lazy_start
else if (std.mem.eql(u8, "(", tok.value))
TokenClass.list_start
else if (std.mem.eql(u8, ")", tok.value))
TokenClass.list_end
else if (std.mem.eql(u8, "\"", tok.value[0..1]))
TokenClass.string
else if (std.mem.eql(u8, "nil", tok.value))
TokenClass.nil
else if (std.mem.eql(u8, "t", tok.value))
TokenClass.t
else if (numbers.has(tok.value[0..1]))
TokenClass.number
else if (std.mem.eql(u8, ";", tok.value[0..1]))
if (tok.value.len >= 3 and std.mem.eql(u8, ";;;", tok.value[0..3])) TokenClass.docstring else TokenClass.comment
else
TokenClass.symbol,
};
}
pub fn classifyTokens(toks: []const tkz.Token, allocator: std.mem.Allocator) !std.ArrayList(ClassifiedToken) {
var ctoks = std.ArrayList(ClassifiedToken).init(allocator);
for (toks) |tok| {
try ctoks.append(classify(tok));
}
return ctoks;
}
+9
View File
@@ -0,0 +1,9 @@
const std = @import("std");
pub fn isPartOf(comptime T: type, haystack: [][]const T, needle: []const T) bool {
for (haystack) |straw| {
if (std.mem.eql(u8, straw, needle[0..straw.len])) {
return true;
}
}
return false;
}
Submodule
+1
Submodule src/lsfw added at 5077a6cc6d
+90
View File
@@ -0,0 +1,90 @@
const std = @import("std");
const lsp_types = @import("lsfw/src/types.zig");
const lsp = @import("lsfw/src/lsp.zig");
const lsp_doc = @import("lsfw/src/document.zig");
const lsp_log = @import("lsfw/src/logger.zig");
const tkz = @import("tokenize.zig");
const cls = @import("classifier.zig");
const State = struct { symbols: std.ArrayList(cls.ClassifiedToken) };
const Lsp = lsp.Lsp(State);
const Scope = enum { hi };
fn handleHover(allocator: std.mem.Allocator, ctx: *Lsp.Context, pos: lsp_types.Position) ?[]const u8 {
if (null == ctx.state) {
lsp_log.notify(.info, "could not find token under cursor (at {})", .{pos});
return null;
} else if (0 == ctx.state.?.symbols.items.len) {
handleDocOpen(allocator, ctx);
}
lsp_log.notify(.err, "{}", .{ctx.state.?.symbols});
// for (ctx.state.?.symbols.items) |tok| {
// if (tok.tok.line == pos.line and tok.tok.char <= pos.character and (tok.tok.char + tok.tok.value.len) >= pos.character) {
// lsp_log.notify(.info, "{}", .{tok});
// break;
// }
// }
return null;
}
fn handleCompletion(allocator: std.mem.Allocator, context: *Lsp.Context, position: lsp_types.Position) ?lsp_types.CompletionList {
_ = context;
_ = position;
var completions = std.ArrayList(lsp_types.CompletionItem).init(allocator);
if (std.mem.Allocator.Error.OutOfMemory == completions.append(.{
.label = "(procedure)",
.insertText = "(procedure ${1:func_name}($2)\n\n)",
.insertTextFormat = .Snippet,
.kind = .Function,
})) {
return null;
}
return .{ .items = completions.items };
}
fn handleDocOpen(allocator: std.mem.Allocator, context: *Lsp.Context) void {
lsp_log.notify(.err, "opened doc {s}", .{context.document.uri});
const content = context.document.text;
const toks = tkz.tokenizeContent(content, allocator) catch unreachable;
// const toks = std.ArrayList(tkz.Token).init(allocator);
lsp_log.notify(.err, "toks {}", .{toks});
// defer toks.deinit();
const ctoks = cls.classifyTokens(toks.items, allocator) catch unreachable;
lsp_log.notify(.err, "ctoks {}", .{ctoks});
// defer ctoks.deinit();
// const ast = try stx.generateSyntaxTree(ctoks);
lsp_log.notify(.info, "opened {s}, found {d} tokens", .{ context.document.uri, ctoks.items.len });
if (context.state != null) {
context.state.?.symbols.deinit();
}
context.state = .{
.symbols = std.ArrayList(cls.ClassifiedToken).init(allocator),
};
}
fn handleDocChanged(allocator: std.mem.Allocator, context: *Lsp.Context, _: []lsp_types.ChangeEvent) void {
handleDocOpen(allocator, context);
}
fn handleDocClose(_: std.mem.Allocator, _: *Lsp.Context) void {}
pub fn start() !u8 {
const descr = lsp_types.ServerData{
.serverInfo = .{
.name = "skill lsp",
.version = "0.1.0",
},
};
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
var server = Lsp.init(gpa.allocator(), descr);
server.registerHoverCallback(handleHover);
server.registerCompletionCallback(handleCompletion);
server.registerDocOpenCallback(handleDocOpen);
server.registerDocChangeCallback(handleDocChanged);
server.registerDocCloseCallback(handleDocClose);
return server.start();
}
+35
View File
@@ -0,0 +1,35 @@
const std = @import("std");
const tkz = @import("tokenizer.zig");
// const cls = @import("classifier.zig");
// const stx = @import("syntax.zig");
const lsp = @import("lsp.zig");
pub fn main() !void {
// var file = try std.fs.cwd().openFile("data/example.il", .{});
// defer file.close();
//
// const content = try file.readToEndAlloc(std.heap.page_allocator, 4096 * ((1 << 10) << 10));
//
// const toks = try tkz.tokenizeContent(content);
// // for (toks.items) |tok| {
// // std.debug.print("{}:{} `{s}`\n", .{
// // tok.line,
// // tok.char,
// // tok.value,
// // });
// // }
//
// const ctoks = try cls.classifyTokens(toks);
// // for (ctoks.items) |ctok| {
// // std.debug.print("{}:{}\t`{s:<40}`({})\n", .{
// // ctok.tok.line,
// // ctok.tok.char,
// // ctok.tok.value,
// // ctok.cls,
// // });
// // }
// const ast = try stx.generateSyntaxTree(ctoks);
// std.debug.print("{}\n", .{ast});
//
_ = try lsp.start();
}
+178
View File
@@ -0,0 +1,178 @@
const std = @import("std");
const toks = @import("tokenizer.zig");
pub const ParseError = error{ no_fn_name, no_fn_params };
pub const Tag = enum {
///expression
///`<rhs...>`
///
///lhs ignored
expr,
///variable assignment
///`<lhs> = <rhs...>`
///
///lhs is overwritten to be variable
var_assign,
///lazy evaluated list
///`'(<rhs...>)`
///
///lhs ignored
llist,
///list (evaluated)
///`(<lhs> <rhs...>)`
///
///lhs needs to be a callable
list_eval,
///fn_def (procedure)
///`;;; <lhs>
///(procedure <main_token>(<lhs>) <rhs...>)`
fn_def,
};
pub const Node = struct {
tag: Tag,
main_token: Index,
data: Data,
pub const Data = struct {
lhs: Index,
rhs: Index,
};
pub const Index = u32;
};
pub const AstError = error{};
pub const Parser = struct {
gpa: std.mem.Allocator,
source: [:0]const u8,
token_tags: []const toks.Token.Tag,
token_locs: []const toks.Token.Loc,
tok_i: Node.Index,
errs: std.ArrayList(AstError),
nodes: std.MultiArrayList(Node),
extra_data: std.ArrayList(Node.Index),
scratch: std.ArrayList(Node.Index),
pub fn init(buffer: [:0]const u8, mal: std.MultiArrayList(toks.Token), allocator: std.mem.Allocator) !Parser {
return .{
.gpa = allocator,
.source = buffer,
.token_tags = mal.items(.tag),
.token_locs = mal.items(.loc),
.tok_i = 0,
.errs = std.ArrayList(AstError).init(allocator),
.nodes = std.MultiArrayList(Node){},
.extra_data = std.ArrayList(Node.Index).init(allocator),
.scratch = std.ArrayList(Node.Index).init(allocator),
};
}
fn hasToken(self: *Parser, expected: toks.Token.Tag, offset: isize) ?toks.Token {
if (self.token_tags[@intCast(self.tok_i + offset)] == expected) {
return .{ .loc = self.token_locs[@intCast(self.tok_i + offset)], .tag = self.token_tags[@intCast(self.tok_i + offset)] };
}
return null;
}
fn eatToken(self: *Parser, expected: toks.Token.Tag) ?Node.Index {
const tok = self.hasToken(expected, 0);
if (tok != null) {
self.tok_i += 1;
return self.tok_i - 1;
}
return null;
}
fn parse_fn_proc(self: *Parser) ?Node {
_ = self.eatToken(.sym);
if (self.hasToken(.list_l, -2) != null) {
// lisp style
} else if (self.eatToken(.list_l) != null) {
// c style
} else {
// not a procedure call or invalid syntax?
}
const name = self.eatToken(.sym) orelse return null;
std.debug.print("found procedure def for `{s}`", .{self.source[self.token_locs[name].start..self.token_locs[name].end]});
_ = self.eatToken(.list_l) orelse return null;
var open_lists: usize = 0;
while (true) : (self.tok_i += 1) {
switch (self.token_tags[self.tok_i]) {
.list_l, .list_lz => {
open_lists += 1;
},
.list_r => {
if (open_lists > 0) {
open_lists -= 1;
} else {
break;
}
},
else => {},
}
}
while (true) : (self.tok_i += 1) {
switch (self.token_tags[self.tok_i]) {
.list_l, .list_lz => {
open_lists += 1;
},
.list_r => {
if (open_lists > 0) {
open_lists -= 1;
} else {
break;
}
},
else => {},
}
}
self.tok_i += 1;
return Node{ .tag = .fn_def, .main_token = name, .data = .{ .lhs = 0, .rhs = 0 } };
}
pub fn next(self: *Parser) ?Node {
while (self.tok_i < self.token_tags.len) : (self.tok_i += 1) {
switch (self.token_tags[self.tok_i]) {
toks.Token.Tag.sym => {
if (std.mem.eql(u8, "procedure", self.source[self.token_locs[self.tok_i].start..self.token_locs[self.tok_i].end])) {
return self.parse_fn_proc();
}
},
else => {},
}
}
return null;
}
};
test "parsing of simple example" {
const example =
\\t
\\nil
\\a = b
\\"some string w/ escaped\""
\\(procedure a() )
;
var tokz = toks.Tokenizer.init(example);
var tokens = std.MultiArrayList(toks.Token){};
defer tokens.deinit(std.testing.allocator);
while (tokz.next()) |tok| {
try tokens.append(std.testing.allocator, tok);
std.debug.print("{}\n", .{tok});
}
var parse = try Parser.init(example, tokens, std.testing.allocator);
while (parse.next()) |ast_node| {
std.debug.print("{}\n", .{ast_node});
}
}
+10
View File
@@ -0,0 +1,10 @@
const std = @import("std");
const testing = std.testing;
export fn add(a: i32, b: i32) i32 {
return a + b;
}
test "basic add functionality" {
try testing.expect(add(3, 7) == 10);
}
+55
View File
@@ -0,0 +1,55 @@
const std = @import("std");
const cls = @import("classifier.zig");
pub const SyntaxNode = struct {
ctok: cls.ClassifiedToken,
nodes: ?std.ArrayList(SyntaxNode),
};
pub fn generateSyntaxTree(ctoks: std.ArrayList(cls.ClassifiedToken)) !std.ArrayList(SyntaxNode) {
var nodes = std.ArrayList(SyntaxNode).init(std.heap.page_allocator);
var actives = std.ArrayList(SyntaxNode).init(std.heap.page_allocator);
for (ctoks.items) |ctok| {
switch (ctok.cls) {
cls.TokenClass.comment, cls.TokenClass.docstring => {
try nodes.append(.{
.ctok = ctok,
.nodes = null,
});
},
cls.TokenClass.list_start, cls.TokenClass.list_lazy_start => {
try actives.append(.{
.ctok = ctok,
.nodes = std.ArrayList(SyntaxNode).init(std.heap.page_allocator),
});
},
cls.TokenClass.list_end => {
if (actives.items.len > 0) {
try nodes.append(actives.pop());
} else {
std.debug.print("{}\n", .{actives});
}
},
else => {
const active_top = actives.popOrNull();
if (active_top != null) {
var active = active_top.?;
var actives_nodes: std.ArrayList(SyntaxNode) = undefined;
if (active.nodes != null) {
actives_nodes = active.nodes.?;
} else {
active.nodes = std.ArrayList(SyntaxNode).init(std.heap.page_allocator);
actives_nodes = active.nodes.?;
}
try actives_nodes.append(.{
.ctok = ctok,
.nodes = null,
});
} else {}
},
}
}
return nodes;
}
+99
View File
@@ -0,0 +1,99 @@
const std = @import("std");
const lsp = @import("lsfw/src/lsp.zig");
pub const Token = struct {
/// 0-based index of token start in whole file
start: usize,
/// 1-based line numbert token starts at
line: usize,
/// 1-based char numbert token starts at in line
char: usize,
value: []const u8,
};
const TokenizationError = error{InvalidKeyword};
pub fn tokenizeContent(content: []u8, allocator: std.mem.Allocator) !std.ArrayList(Token) {
var toks = std.ArrayList(Token).init(allocator);
var lines = std.ArrayList(usize).init(allocator);
defer lines.deinit();
var index: usize = 0;
while (index < content.len) {
var l: usize = 1;
const char = content[index];
_ = switch (char) {
'\n' => {
try lines.append(index);
index += l;
continue;
},
';' => {
while (switch (content[index + l]) {
'\n' => false,
else => true,
}) : (l += 1) {}
},
'"' => {
while (switch (content[index + l]) {
'"' => (content[index + l - 1] == '\\'),
else => true,
}) : (l += 1) {}
l += 1;
},
'a'...'z', 'A'...'Z', '_' => {
while (switch (content[index + l]) {
'a'...'z', 'A'...'Z', '0'...'9', '_' => true,
else => false,
}) : (l += 1) {}
},
'0'...'9' => {
while (switch (content[index + l]) {
'0'...'9', '.', 'e' => true,
else => false,
}) : (l += 1) {}
},
'+', '-', '~', '*', '/', '%', '<', '>', '=', '?', '|', '&', '(', ')', '\'' => {
for ([_]*const [2]u8{ "->", "~>", "||", "&&", "/=", "*=", "+=", "-=", "'(" }) |op| {
if (std.mem.eql(u8, op, content[index .. index + 2])) {
l = 2;
break;
}
}
},
'@' => {
while (switch (content[index + l]) {
'a'...'z', 'A'...'Z', '_', '0'...'9' => true,
else => false,
}) : (l += 1) {}
if (std.mem.eql(u8, "@keys", content[index .. index + l])) {} else if (std.mem.eql(u8, "@rest", content[index .. index + l])) {} else {
std.debug.print("line={d}, char={d}\n", .{
.line = lines.items.len,
.char = switch (lines.items.len) {
0 => index,
else => index - lines.items[lines.items.len - 1],
},
});
}
},
else => {
index += l;
continue;
},
};
try toks.append(.{
.start = index,
.value = try allocator.dupe(u8, content[index .. index + l]),
.line = lines.items.len,
.char = switch (lines.items.len) {
0 => index,
else => index - lines.items[lines.items.len - 1],
},
});
index += l;
}
lsp.logger.notify(.err, "done with initial tokenization, generated {d} tokens", .{toks.items.len});
return toks;
}
+272
View File
@@ -0,0 +1,272 @@
const std = @import("std");
pub const Token = struct {
tag: Tag,
loc: Loc,
pub const Loc = struct {
start: usize,
end: usize,
};
pub const Tag = enum {
sym,
num,
str,
/// t
t,
/// nil
nil,
/// =
assign,
/// -=
assign_sub,
/// /=
assign_div,
/// *=
assign_mul,
/// +=
assign_add,
/// ==
op_eq,
/// >
op_gt,
/// >=
op_geq,
/// <
op_lt,
/// <=
op_leq,
/// /
op_div,
/// *
op_mul,
/// +
op_add,
/// -
op_sub,
/// ->
op_acc,
/// ~>
op_derefacc,
/// %
op_mod,
/// !
op_not,
/// !=
op_neq,
/// ||
op_or,
/// &&
op_and,
/// (
list_l,
/// '(
list_lz,
/// )
list_r,
/// @keys
kw_keys,
/// @rest
kw_rest,
};
pub fn format(self: *const Token, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
try writer.print("{d}:{d} .{s}", .{ self.loc.start, self.loc.end, @tagName(self.tag) });
}
};
pub const Tokenizer = struct {
buffer: [:0]const u8,
index: usize,
start: usize,
const State = enum {
start,
alphanum_identifier,
number_or_float,
decimals,
signed_exponent,
unsigned_exponent,
string,
op_plus,
op_minus,
op_star,
op_fslash,
op_pipe,
op_amp,
op_excl,
op_deref,
op_eq,
list_l,
list_lz,
list_r,
};
pub fn init(buf: [:0]const u8) Tokenizer {
return .{
.buffer = buf,
.index = 0,
.start = 0,
};
}
pub fn next(self: *Tokenizer) ?Token {
var state: State = .start;
while (self.index < self.buffer.len) : (self.index += 1) {
const c = self.buffer[self.index];
const loc = Token.Loc{ .start = self.start, .end = self.index };
state = switch (state) {
.start => blk: {
self.start = self.index;
break :blk switch (c) {
'a'...'z', 'A'...'Z', '_' => .alphanum_identifier,
'0'...'9' => .number_or_float,
'.' => .decimals,
'"' => .string,
'+' => .op_plus,
'-' => .op_minus,
'*' => .op_star,
'/' => .op_fslash,
'|' => .op_pipe,
'&' => .op_amp,
'!' => .op_excl,
'~' => .op_deref,
'=' => .op_eq,
'(' => .list_l,
')' => .list_r,
'\'' => .list_lz,
else => .start,
};
},
.alphanum_identifier => switch (c) {
'a'...'z', 'A'...'Z', '0'...'9', '_' => .alphanum_identifier,
else => {
inline for (.{ Token.Tag.t, Token.Tag.nil }) |alphanum_tag| {
if (std.mem.eql(u8, self.buffer[self.start..self.index], @tagName(alphanum_tag))) {
return Token{ .tag = alphanum_tag, .loc = loc };
}
}
return Token{ .tag = .sym, .loc = loc };
},
},
.number_or_float => switch (c) {
'0'...'9' => .number_or_float,
'.' => .decimals,
'e' => .signed_exponent,
' ', '\n' => {
return Token{ .tag = .num, .loc = loc };
},
else => unreachable,
},
.decimals => switch (c) {
'0'...'9' => .decimals,
' ', '\n' => {
return Token{ .tag = .num, .loc = loc };
},
else => unreachable,
},
.signed_exponent => switch (c) {
'0'...'9', '+', '-' => .unsigned_exponent,
else => unreachable,
},
.unsigned_exponent => switch (c) {
'0'...'9' => .unsigned_exponent,
' ', '\n' => {
return Token{ .tag = .num, .loc = loc };
},
else => unreachable,
},
.string => switch (c) {
'"' => {
return Token{ .tag = .str, .loc = loc };
},
'\\' => blk: {
self.index += 1;
break :blk .string;
},
else => .string,
},
.op_plus, .op_minus, .op_fslash, .op_star, .op_excl, .op_eq => switch (c) {
'=' => {
return Token{ .tag = switch (state) {
.op_plus => .assign_add,
.op_minus => .assign_sub,
.op_star => .assign_mul,
.op_fslash => .assign_div,
.op_excl => .op_neq,
.op_eq => .op_eq,
else => unreachable,
}, .loc = loc };
},
' ', '\n' => {
return Token{ .tag = switch (state) {
.op_plus => .op_add,
.op_minus => .op_sub,
.op_star => .op_mul,
.op_fslash => .op_div,
.op_excl => .op_not,
.op_eq => .assign,
else => unreachable,
}, .loc = loc };
},
'>' => {
return Token{ .tag = switch (state) {
.op_minus => .op_acc,
else => unreachable,
}, .loc = loc };
},
else => unreachable,
},
.op_pipe => switch (c) {
'|' => {
return Token{ .tag = .op_or, .loc = loc };
},
else => unreachable,
},
.op_amp => switch (c) {
'&' => {
return Token{ .tag = .op_and, .loc = loc };
},
else => unreachable,
},
.op_deref => switch (c) {
'>' => {
return Token{ .tag = .op_derefacc, .loc = loc };
},
else => unreachable,
},
.list_l => {
return Token{ .tag = .list_l, .loc = loc };
},
.list_r => {
return Token{ .tag = .list_r, .loc = loc };
},
.list_lz => switch (c) {
'(' => {
return Token{ .tag = .op_derefacc, .loc = loc };
},
else => unreachable,
},
};
}
return null;
}
};
test "simple tokenization" {
const example =
\\t
\\nil
\\a = b
\\"some string w/ escaped\""
;
var tokz = Tokenizer.init(example);
try std.testing.expectEqual(Token{ .loc = .{ .start = 0, .end = 1 }, .tag = .t }, tokz.next());
try std.testing.expectEqual(Token{ .loc = .{ .start = 2, .end = 5 }, .tag = .nil }, tokz.next());
try std.testing.expectEqual(Token{ .loc = .{ .start = 6, .end = 7 }, .tag = .sym }, tokz.next());
try std.testing.expectEqual(Token{ .loc = .{ .start = 8, .end = 9 }, .tag = .assign }, tokz.next());
try std.testing.expectEqual(Token{ .loc = .{ .start = 10, .end = 11 }, .tag = .sym }, tokz.next());
try std.testing.expectEqual(Token{ .loc = .{ .start = 12, .end = 37 }, .tag = .str }, tokz.next());
}
-40
View File
@@ -1,40 +0,0 @@
# TODOs
- [x] Paren pair parsing
- iterative parsing and matching of paren/bracket pairs
- [ ] tokenizer
- identify "tokens"
- everythin is a token with exception of:
- operators
- parens/brackets
- numbers
- t / nil
- comments (maybe already handled)
- [ ] namespaces / scopes
- namespaces are started with:
- let / letseq / let...
```skill
; let[T]( locals: list[tuple[symbol, Any] | symbol] | nil, *exprs: Any, last_expr: T) -> T
```
- prog
```skill
; prog( locals: list[symbol] | nil, *exprs: Any) -> Any
```
- procedure
```skill
; function_name(req_param: Any, key_param1: any = value_param2) => Any
procedure( function_name(req_param @keys (key_param1 value_param2))
...
)
function_name(<req_arg> ?key_param1 <value_param2>)
```
- [ ] token contextualization
- looks for declaration / definition of symbol
Generated
-391
View File
@@ -1,391 +0,0 @@
version = 1
revision = 1
requires-python = ">=3.12"
[[package]]
name = "attrs"
version = "24.3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/48/c8/6260f8ccc11f0917360fc0da435c5c9c7504e3db174d5a12a1494887b045/attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff", size = 805984 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/89/aa/ab0f7891a01eeb2d2e338ae8fecbe57fcebea1a24dbb64d45801bfab481d/attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308", size = 63397 },
]
[[package]]
name = "black"
version = "24.10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
{ name = "mypy-extensions" },
{ name = "packaging" },
{ name = "pathspec" },
{ name = "platformdirs" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d8/0d/cc2fb42b8c50d80143221515dd7e4766995bd07c56c9a3ed30baf080b6dc/black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875", size = 645813 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/90/04/bf74c71f592bcd761610bbf67e23e6a3cff824780761f536512437f1e655/black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3", size = 1644256 },
{ url = "https://files.pythonhosted.org/packages/4c/ea/a77bab4cf1887f4b2e0bce5516ea0b3ff7d04ba96af21d65024629afedb6/black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65", size = 1448534 },
{ url = "https://files.pythonhosted.org/packages/4e/3e/443ef8bc1fbda78e61f79157f303893f3fddf19ca3c8989b163eb3469a12/black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f", size = 1761892 },
{ url = "https://files.pythonhosted.org/packages/52/93/eac95ff229049a6901bc84fec6908a5124b8a0b7c26ea766b3b8a5debd22/black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8", size = 1434796 },
{ url = "https://files.pythonhosted.org/packages/d0/a0/a993f58d4ecfba035e61fca4e9f64a2ecae838fc9f33ab798c62173ed75c/black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981", size = 1643986 },
{ url = "https://files.pythonhosted.org/packages/37/d5/602d0ef5dfcace3fb4f79c436762f130abd9ee8d950fa2abdbf8bbc555e0/black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b", size = 1448085 },
{ url = "https://files.pythonhosted.org/packages/47/6d/a3a239e938960df1a662b93d6230d4f3e9b4a22982d060fc38c42f45a56b/black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2", size = 1760928 },
{ url = "https://files.pythonhosted.org/packages/dd/cf/af018e13b0eddfb434df4d9cd1b2b7892bab119f7a20123e93f6910982e8/black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b", size = 1436875 },
{ url = "https://files.pythonhosted.org/packages/8d/a7/4b27c50537ebca8bec139b872861f9d2bf501c5ec51fcf897cb924d9e264/black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d", size = 206898 },
]
[[package]]
name = "cattrs"
version = "24.1.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
]
sdist = { url = "https://files.pythonhosted.org/packages/64/65/af6d57da2cb32c076319b7489ae0958f746949d407109e3ccf4d115f147c/cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85", size = 426462 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c8/d5/867e75361fc45f6de75fe277dd085627a9db5ebb511a87f27dc1396b5351/cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0", size = 66446 },
]
[[package]]
name = "click"
version = "8.1.8"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 },
]
[[package]]
name = "colorama"
version = "0.4.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
]
[[package]]
name = "iniconfig"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
]
[[package]]
name = "lsprotocol"
version = "2023.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "cattrs" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9d/f6/6e80484ec078d0b50699ceb1833597b792a6c695f90c645fbaf54b947e6f/lsprotocol-2023.0.1.tar.gz", hash = "sha256:cc5c15130d2403c18b734304339e51242d3018a05c4f7d0f198ad6e0cd21861d", size = 69434 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8d/37/2351e48cb3309673492d3a8c59d407b75fb6630e560eb27ecd4da03adc9a/lsprotocol-2023.0.1-py3-none-any.whl", hash = "sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2", size = 70826 },
]
[[package]]
name = "markdown-it-py"
version = "3.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mdurl" },
]
sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
]
[[package]]
name = "mdurl"
version = "0.1.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
]
[[package]]
name = "mypy"
version = "1.14.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mypy-extensions" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668 },
{ url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060 },
{ url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167 },
{ url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341 },
{ url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991 },
{ url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016 },
{ url = "https://files.pythonhosted.org/packages/9e/15/bb6a686901f59222275ab228453de741185f9d54fecbaacec041679496c6/mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", size = 11252097 },
{ url = "https://files.pythonhosted.org/packages/f8/b3/8b0f74dfd072c802b7fa368829defdf3ee1566ba74c32a2cb2403f68024c/mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", size = 10239728 },
{ url = "https://files.pythonhosted.org/packages/c5/9b/4fd95ab20c52bb5b8c03cc49169be5905d931de17edfe4d9d2986800b52e/mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", size = 11924965 },
{ url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660 },
{ url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198 },
{ url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276 },
{ url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 },
]
[[package]]
name = "mypy-extensions"
version = "1.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 },
]
[[package]]
name = "packaging"
version = "24.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
]
[[package]]
name = "parsimonious"
version = "0.10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "regex" },
]
sdist = { url = "https://files.pythonhosted.org/packages/7b/91/abdc50c4ef06fdf8d047f60ee777ca9b2a7885e1a9cea81343fbecda52d7/parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c", size = 52172 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/aa/0f/c8b64d9b54ea631fcad4e9e3c8dbe8c11bb32a623be94f22974c88e71eaf/parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f", size = 48427 },
]
[[package]]
name = "pathspec"
version = "0.12.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 },
]
[[package]]
name = "platformdirs"
version = "4.3.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 },
]
[[package]]
name = "pluggy"
version = "1.5.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
]
[[package]]
name = "pygls"
version = "1.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cattrs" },
{ name = "lsprotocol" },
]
sdist = { url = "https://files.pythonhosted.org/packages/86/b9/41d173dad9eaa9db9c785a85671fc3d68961f08d67706dc2e79011e10b5c/pygls-1.3.1.tar.gz", hash = "sha256:140edceefa0da0e9b3c533547c892a42a7d2fd9217ae848c330c53d266a55018", size = 45527 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/11/19/b74a10dd24548e96e8c80226cbacb28b021bc3a168a7d2709fb0d0185348/pygls-1.3.1-py3-none-any.whl", hash = "sha256:6e00f11efc56321bdeb6eac04f6d86131f654c7d49124344a9ebb968da3dd91e", size = 56031 },
]
[[package]]
name = "pygments"
version = "2.19.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
]
[[package]]
name = "pytest"
version = "8.3.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "iniconfig" },
{ name = "packaging" },
{ name = "pluggy" },
]
sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 },
]
[[package]]
name = "regex"
version = "2024.11.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/8e/5f/bd69653fbfb76cf8604468d3b4ec4c403197144c7bfe0e6a5fc9e02a07cb/regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519", size = 399494 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ba/30/9a87ce8336b172cc232a0db89a3af97929d06c11ceaa19d97d84fa90a8f8/regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a", size = 483781 },
{ url = "https://files.pythonhosted.org/packages/01/e8/00008ad4ff4be8b1844786ba6636035f7ef926db5686e4c0f98093612add/regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9", size = 288455 },
{ url = "https://files.pythonhosted.org/packages/60/85/cebcc0aff603ea0a201667b203f13ba75d9fc8668fab917ac5b2de3967bc/regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2", size = 284759 },
{ url = "https://files.pythonhosted.org/packages/94/2b/701a4b0585cb05472a4da28ee28fdfe155f3638f5e1ec92306d924e5faf0/regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4", size = 794976 },
{ url = "https://files.pythonhosted.org/packages/4b/bf/fa87e563bf5fee75db8915f7352e1887b1249126a1be4813837f5dbec965/regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577", size = 833077 },
{ url = "https://files.pythonhosted.org/packages/a1/56/7295e6bad94b047f4d0834e4779491b81216583c00c288252ef625c01d23/regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3", size = 823160 },
{ url = "https://files.pythonhosted.org/packages/fb/13/e3b075031a738c9598c51cfbc4c7879e26729c53aa9cca59211c44235314/regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e", size = 796896 },
{ url = "https://files.pythonhosted.org/packages/24/56/0b3f1b66d592be6efec23a795b37732682520b47c53da5a32c33ed7d84e3/regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe", size = 783997 },
{ url = "https://files.pythonhosted.org/packages/f9/a1/eb378dada8b91c0e4c5f08ffb56f25fcae47bf52ad18f9b2f33b83e6d498/regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e", size = 781725 },
{ url = "https://files.pythonhosted.org/packages/83/f2/033e7dec0cfd6dda93390089864732a3409246ffe8b042e9554afa9bff4e/regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29", size = 789481 },
{ url = "https://files.pythonhosted.org/packages/83/23/15d4552ea28990a74e7696780c438aadd73a20318c47e527b47a4a5a596d/regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39", size = 852896 },
{ url = "https://files.pythonhosted.org/packages/e3/39/ed4416bc90deedbfdada2568b2cb0bc1fdb98efe11f5378d9892b2a88f8f/regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51", size = 860138 },
{ url = "https://files.pythonhosted.org/packages/93/2d/dd56bb76bd8e95bbce684326302f287455b56242a4f9c61f1bc76e28360e/regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad", size = 787692 },
{ url = "https://files.pythonhosted.org/packages/0b/55/31877a249ab7a5156758246b9c59539abbeba22461b7d8adc9e8475ff73e/regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54", size = 262135 },
{ url = "https://files.pythonhosted.org/packages/38/ec/ad2d7de49a600cdb8dd78434a1aeffe28b9d6fc42eb36afab4a27ad23384/regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b", size = 273567 },
{ url = "https://files.pythonhosted.org/packages/90/73/bcb0e36614601016552fa9344544a3a2ae1809dc1401b100eab02e772e1f/regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84", size = 483525 },
{ url = "https://files.pythonhosted.org/packages/0f/3f/f1a082a46b31e25291d830b369b6b0c5576a6f7fb89d3053a354c24b8a83/regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4", size = 288324 },
{ url = "https://files.pythonhosted.org/packages/09/c9/4e68181a4a652fb3ef5099e077faf4fd2a694ea6e0f806a7737aff9e758a/regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0", size = 284617 },
{ url = "https://files.pythonhosted.org/packages/fc/fd/37868b75eaf63843165f1d2122ca6cb94bfc0271e4428cf58c0616786dce/regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0", size = 795023 },
{ url = "https://files.pythonhosted.org/packages/c4/7c/d4cd9c528502a3dedb5c13c146e7a7a539a3853dc20209c8e75d9ba9d1b2/regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7", size = 833072 },
{ url = "https://files.pythonhosted.org/packages/4f/db/46f563a08f969159c5a0f0e722260568425363bea43bb7ae370becb66a67/regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7", size = 823130 },
{ url = "https://files.pythonhosted.org/packages/db/60/1eeca2074f5b87df394fccaa432ae3fc06c9c9bfa97c5051aed70e6e00c2/regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c", size = 796857 },
{ url = "https://files.pythonhosted.org/packages/10/db/ac718a08fcee981554d2f7bb8402f1faa7e868c1345c16ab1ebec54b0d7b/regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3", size = 784006 },
{ url = "https://files.pythonhosted.org/packages/c2/41/7da3fe70216cea93144bf12da2b87367590bcf07db97604edeea55dac9ad/regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07", size = 781650 },
{ url = "https://files.pythonhosted.org/packages/a7/d5/880921ee4eec393a4752e6ab9f0fe28009435417c3102fc413f3fe81c4e5/regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e", size = 789545 },
{ url = "https://files.pythonhosted.org/packages/dc/96/53770115e507081122beca8899ab7f5ae28ae790bfcc82b5e38976df6a77/regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6", size = 853045 },
{ url = "https://files.pythonhosted.org/packages/31/d3/1372add5251cc2d44b451bd94f43b2ec78e15a6e82bff6a290ef9fd8f00a/regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4", size = 860182 },
{ url = "https://files.pythonhosted.org/packages/ed/e3/c446a64984ea9f69982ba1a69d4658d5014bc7a0ea468a07e1a1265db6e2/regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d", size = 787733 },
{ url = "https://files.pythonhosted.org/packages/2b/f1/e40c8373e3480e4f29f2692bd21b3e05f296d3afebc7e5dcf21b9756ca1c/regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff", size = 262122 },
{ url = "https://files.pythonhosted.org/packages/45/94/bc295babb3062a731f52621cdc992d123111282e291abaf23faa413443ea/regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a", size = 273545 },
]
[[package]]
name = "rich"
version = "13.9.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markdown-it-py" },
{ name = "pygments" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 },
]
[[package]]
name = "ruff"
version = "0.9.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/80/63/77ecca9d21177600f551d1c58ab0e5a0b260940ea7312195bd2a4798f8a8/ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0", size = 3553799 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/af/b9/0e168e4e7fb3af851f739e8f07889b91d1a33a30fca8c29fa3149d6b03ec/ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347", size = 11652408 },
{ url = "https://files.pythonhosted.org/packages/2c/22/08ede5db17cf701372a461d1cb8fdde037da1d4fa622b69ac21960e6237e/ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00", size = 11587553 },
{ url = "https://files.pythonhosted.org/packages/42/05/dedfc70f0bf010230229e33dec6e7b2235b2a1b8cbb2a991c710743e343f/ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4", size = 11020755 },
{ url = "https://files.pythonhosted.org/packages/df/9b/65d87ad9b2e3def67342830bd1af98803af731243da1255537ddb8f22209/ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d", size = 11826502 },
{ url = "https://files.pythonhosted.org/packages/93/02/f2239f56786479e1a89c3da9bc9391120057fc6f4a8266a5b091314e72ce/ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c", size = 11390562 },
{ url = "https://files.pythonhosted.org/packages/c9/37/d3a854dba9931f8cb1b2a19509bfe59e00875f48ade632e95aefcb7a0aee/ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f", size = 12548968 },
{ url = "https://files.pythonhosted.org/packages/fa/c3/c7b812bb256c7a1d5553433e95980934ffa85396d332401f6b391d3c4569/ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684", size = 13187155 },
{ url = "https://files.pythonhosted.org/packages/bd/5a/3c7f9696a7875522b66aa9bba9e326e4e5894b4366bd1dc32aa6791cb1ff/ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d", size = 12704674 },
{ url = "https://files.pythonhosted.org/packages/be/d6/d908762257a96ce5912187ae9ae86792e677ca4f3dc973b71e7508ff6282/ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df", size = 14529328 },
{ url = "https://files.pythonhosted.org/packages/2d/c2/049f1e6755d12d9cd8823242fa105968f34ee4c669d04cac8cea51a50407/ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247", size = 12385955 },
{ url = "https://files.pythonhosted.org/packages/91/5a/a9bdb50e39810bd9627074e42743b00e6dc4009d42ae9f9351bc3dbc28e7/ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e", size = 11810149 },
{ url = "https://files.pythonhosted.org/packages/e5/fd/57df1a0543182f79a1236e82a79c68ce210efb00e97c30657d5bdb12b478/ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe", size = 11479141 },
{ url = "https://files.pythonhosted.org/packages/dc/16/bc3fd1d38974f6775fc152a0554f8c210ff80f2764b43777163c3c45d61b/ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb", size = 12014073 },
{ url = "https://files.pythonhosted.org/packages/47/6b/e4ca048a8f2047eb652e1e8c755f384d1b7944f69ed69066a37acd4118b0/ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a", size = 12435758 },
{ url = "https://files.pythonhosted.org/packages/c2/40/4d3d6c979c67ba24cf183d29f706051a53c36d78358036a9cd21421582ab/ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145", size = 9796916 },
{ url = "https://files.pythonhosted.org/packages/c3/ef/7f548752bdb6867e6939489c87fe4da489ab36191525fadc5cede2a6e8e2/ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5", size = 10773080 },
{ url = "https://files.pythonhosted.org/packages/0e/4e/33df635528292bd2d18404e4daabcd74ca8a9853b2e1df85ed3d32d24362/ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6", size = 10001738 },
]
[[package]]
name = "skillls"
version = "0.1.0"
source = { editable = "." }
dependencies = [
{ name = "parsimonious" },
{ name = "pygls" },
{ name = "rich" },
{ name = "tree-sitter" },
{ name = "tree-sitter-skill" },
]
[package.optional-dependencies]
dev = [
{ name = "black" },
{ name = "mypy" },
{ name = "pytest" },
{ name = "ruff" },
{ name = "types-parsimonious" },
]
[package.metadata]
requires-dist = [
{ name = "black", marker = "extra == 'dev'" },
{ name = "mypy", marker = "extra == 'dev'" },
{ name = "parsimonious", specifier = "~=0.10.0" },
{ name = "pygls" },
{ name = "pytest", marker = "extra == 'dev'" },
{ name = "rich" },
{ name = "ruff", marker = "extra == 'dev'" },
{ name = "tree-sitter", specifier = ">=0.24.0" },
{ name = "tree-sitter-skill", git = "ssh://git@git.acereca.net/acereca/tree-sitter-skill.git" },
{ name = "types-parsimonious", marker = "extra == 'dev'" },
]
provides-extras = ["dev"]
[[package]]
name = "tree-sitter"
version = "0.24.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a7/a2/698b9d31d08ad5558f8bfbfe3a0781bd4b1f284e89bde3ad18e05101a892/tree-sitter-0.24.0.tar.gz", hash = "sha256:abd95af65ca2f4f7eca356343391ed669e764f37748b5352946f00f7fc78e734", size = 168304 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/57/3a590f287b5aa60c07d5545953912be3d252481bf5e178f750db75572bff/tree_sitter-0.24.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:14beeff5f11e223c37be7d5d119819880601a80d0399abe8c738ae2288804afc", size = 140788 },
{ url = "https://files.pythonhosted.org/packages/61/0b/fc289e0cba7dbe77c6655a4dd949cd23c663fd62a8b4d8f02f97e28d7fe5/tree_sitter-0.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26a5b130f70d5925d67b47db314da209063664585a2fd36fa69e0717738efaf4", size = 133945 },
{ url = "https://files.pythonhosted.org/packages/86/d7/80767238308a137e0b5b5c947aa243e3c1e3e430e6d0d5ae94b9a9ffd1a2/tree_sitter-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fc5c3c26d83c9d0ecb4fc4304fba35f034b7761d35286b936c1db1217558b4e", size = 564819 },
{ url = "https://files.pythonhosted.org/packages/bf/b3/6c5574f4b937b836601f5fb556b24804b0a6341f2eb42f40c0e6464339f4/tree_sitter-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:772e1bd8c0931c866b848d0369b32218ac97c24b04790ec4b0e409901945dd8e", size = 579303 },
{ url = "https://files.pythonhosted.org/packages/0a/f4/bd0ddf9abe242ea67cca18a64810f8af230fc1ea74b28bb702e838ccd874/tree_sitter-0.24.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:24a8dd03b0d6b8812425f3b84d2f4763322684e38baf74e5bb766128b5633dc7", size = 581054 },
{ url = "https://files.pythonhosted.org/packages/8c/1c/ff23fa4931b6ef1bbeac461b904ca7e49eaec7e7e5398584e3eef836ec96/tree_sitter-0.24.0-cp312-cp312-win_amd64.whl", hash = "sha256:f9e8b1605ab60ed43803100f067eed71b0b0e6c1fb9860a262727dbfbbb74751", size = 120221 },
{ url = "https://files.pythonhosted.org/packages/b2/2a/9979c626f303177b7612a802237d0533155bf1e425ff6f73cc40f25453e2/tree_sitter-0.24.0-cp312-cp312-win_arm64.whl", hash = "sha256:f733a83d8355fc95561582b66bbea92ffd365c5d7a665bc9ebd25e049c2b2abb", size = 108234 },
{ url = "https://files.pythonhosted.org/packages/61/cd/2348339c85803330ce38cee1c6cbbfa78a656b34ff58606ebaf5c9e83bd0/tree_sitter-0.24.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d4a6416ed421c4210f0ca405a4834d5ccfbb8ad6692d4d74f7773ef68f92071", size = 140781 },
{ url = "https://files.pythonhosted.org/packages/8b/a3/1ea9d8b64e8dcfcc0051028a9c84a630301290995cd6e947bf88267ef7b1/tree_sitter-0.24.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0992d483677e71d5c5d37f30dfb2e3afec2f932a9c53eec4fca13869b788c6c", size = 133928 },
{ url = "https://files.pythonhosted.org/packages/fe/ae/55c1055609c9428a4aedf4b164400ab9adb0b1bf1538b51f4b3748a6c983/tree_sitter-0.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57277a12fbcefb1c8b206186068d456c600dbfbc3fd6c76968ee22614c5cd5ad", size = 564497 },
{ url = "https://files.pythonhosted.org/packages/ce/d0/f2ffcd04882c5aa28d205a787353130cbf84b2b8a977fd211bdc3b399ae3/tree_sitter-0.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25fa22766d63f73716c6fec1a31ee5cf904aa429484256bd5fdf5259051ed74", size = 578917 },
{ url = "https://files.pythonhosted.org/packages/af/82/aebe78ea23a2b3a79324993d4915f3093ad1af43d7c2208ee90be9273273/tree_sitter-0.24.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7d5d9537507e1c8c5fa9935b34f320bfec4114d675e028f3ad94f11cf9db37b9", size = 581148 },
{ url = "https://files.pythonhosted.org/packages/a1/b4/6b0291a590c2b0417cfdb64ccb8ea242f270a46ed429c641fbc2bfab77e0/tree_sitter-0.24.0-cp313-cp313-win_amd64.whl", hash = "sha256:f58bb4956917715ec4d5a28681829a8dad5c342cafd4aea269f9132a83ca9b34", size = 120207 },
{ url = "https://files.pythonhosted.org/packages/a8/18/542fd844b75272630229c9939b03f7db232c71a9d82aadc59c596319ea6a/tree_sitter-0.24.0-cp313-cp313-win_arm64.whl", hash = "sha256:23641bd25dcd4bb0b6fa91b8fb3f46cc9f1c9f475efe4d536d3f1f688d1b84c8", size = 108232 },
]
[[package]]
name = "tree-sitter-skill"
version = "0.1.1"
source = { git = "ssh://git@git.acereca.net/acereca/tree-sitter-skill.git#ce8634713b13f1787837fd9a7c515383ecedac07" }
dependencies = [
{ name = "tree-sitter" },
]
[[package]]
name = "types-parsimonious"
version = "0.10.0.20240331"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/11/8a/3e0f5d72ea35bc5fba64899fca45124a4398c78e28c40a3e119f15882d35/types-parsimonious-0.10.0.20240331.tar.gz", hash = "sha256:c9ca50c968b83203a285ee8fbe4a50c5aa6d8ca903d92802ee5398cb95608ceb", size = 5482 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b5/fe/f6f9b4ec9c4cd0c567bcd581d65795bb07b0613fe3d15b249af348efa42a/types_parsimonious-0.10.0.20240331-py3-none-any.whl", hash = "sha256:6828faa2b74c03d229d2ea5b661a9de47589a837fec48424804c42b9113a28cd", size = 6308 },
]
[[package]]
name = "typing-extensions"
version = "4.12.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
]