112 lines
3.1 KiB
Python
112 lines
3.1 KiB
Python
from typing import Any, Sequence
|
|
from lsprotocol.types import Range
|
|
from parsimonious import ParseError
|
|
from dataclasses import dataclass
|
|
|
|
from parsimonious.nodes import Node, NodeVisitor
|
|
|
|
from .location import Locator
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class BaseToken:
|
|
range: Range
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Literal(BaseToken):
|
|
value: str | float | bool
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Token(BaseToken):
|
|
value: str
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class List(BaseToken):
|
|
value: list[BaseToken]
|
|
|
|
|
|
@dataclass
|
|
class SkillVisitor(NodeVisitor):
|
|
locator: Locator
|
|
|
|
def visit_skill(self, _: Node, visited_children: Sequence[Any]) -> list[BaseToken]:
|
|
children = []
|
|
for childlist in visited_children:
|
|
for child in childlist:
|
|
if isinstance(child, BaseToken):
|
|
children.append(child)
|
|
|
|
return children
|
|
|
|
def visit_TOKEN(self, node: Node, _: Any) -> Token:
|
|
return Token(self.locator.locate(node), node.text)
|
|
|
|
def visit_LITERAL(self, node: Node, visited_children: list[None | Node]) -> Literal:
|
|
value, *_ = visited_children
|
|
if value:
|
|
match value.expr_name:
|
|
case "L_t":
|
|
return Literal(self.locator.locate(node), True)
|
|
case "L_nil":
|
|
return Literal(self.locator.locate(node), False)
|
|
case "L_num":
|
|
return Literal(self.locator.locate(node), float(value.text))
|
|
case "L_string":
|
|
return Literal(self.locator.locate(node), value.text)
|
|
case _:
|
|
pass
|
|
|
|
raise ParseError("something went wrong during literal parsing")
|
|
|
|
def visit_listraw(
|
|
self, node: Node, visited_children: list[list[list[Any]]]
|
|
) -> List:
|
|
rest = visited_children[2]
|
|
|
|
children = []
|
|
|
|
for child in rest:
|
|
for part in child:
|
|
if isinstance(part, BaseToken):
|
|
children.append(part)
|
|
|
|
return List(self.locator.locate(node), children)
|
|
|
|
def visit_listc(self, node: Node, visited_children: list[list[list[Any]]]) -> List:
|
|
rest = ([[visited_children[0]]], visited_children[2])
|
|
|
|
children = []
|
|
|
|
for child_list in rest:
|
|
for child in child_list:
|
|
for part in child:
|
|
if isinstance(part, BaseToken):
|
|
children.append(part)
|
|
|
|
return List(self.locator.locate(node), children)
|
|
|
|
def visit_listskill(
|
|
self, node: Node, visited_children: list[list[list[Any]]]
|
|
) -> List:
|
|
rest = visited_children[1]
|
|
|
|
children = []
|
|
|
|
for child in rest:
|
|
for part in child:
|
|
if isinstance(part, BaseToken):
|
|
children.append(part)
|
|
|
|
return List(self.locator.locate(node), children)
|
|
|
|
def visit_inline_assign(self, node: Node, visited_children: Sequence[Any]):
|
|
print(node)
|
|
|
|
def generic_visit(
|
|
self, node: Node, visited_children: Sequence[Any]
|
|
) -> Node | Sequence[None | Node]:
|
|
return visited_children or node
|