xr-syntax 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. xr_syntax/__init__.py +59 -0
  2. xr_syntax/cmake/__init__.py +26 -0
  3. xr_syntax/cmake/builder.py +91 -0
  4. xr_syntax/cmake/document.py +90 -0
  5. xr_syntax/cmake/factory.py +158 -0
  6. xr_syntax/cmake/grammar/LICENSE.tree-sitter-cmake +21 -0
  7. xr_syntax/cmake/grammar/__init__.py +61 -0
  8. xr_syntax/cmake/grammar/node-types.json +905 -0
  9. xr_syntax/cmake/parser.py +430 -0
  10. xr_syntax/cmake/view.py +74 -0
  11. xr_syntax/core/__init__.py +51 -0
  12. xr_syntax/core/diagnostic.py +24 -0
  13. xr_syntax/core/document.py +170 -0
  14. xr_syntax/core/fragment.py +92 -0
  15. xr_syntax/core/grammar.py +280 -0
  16. xr_syntax/core/green.py +178 -0
  17. xr_syntax/core/parser_schema.py +44 -0
  18. xr_syntax/core/red.py +370 -0
  19. xr_syntax/core/rewriter.py +67 -0
  20. xr_syntax/core/span.py +48 -0
  21. xr_syntax/core/text.py +22 -0
  22. xr_syntax/core/tree.py +238 -0
  23. xr_syntax/core/visitor.py +55 -0
  24. xr_syntax/cpp/__init__.py +56 -0
  25. xr_syntax/cpp/_declaration.py +296 -0
  26. xr_syntax/cpp/_declarator.py +382 -0
  27. xr_syntax/cpp/_expression.py +489 -0
  28. xr_syntax/cpp/_lexical_support.py +31 -0
  29. xr_syntax/cpp/_ranges.py +387 -0
  30. xr_syntax/cpp/_support.py +271 -0
  31. xr_syntax/cpp/builder.py +371 -0
  32. xr_syntax/cpp/document.py +314 -0
  33. xr_syntax/cpp/factory.py +380 -0
  34. xr_syntax/cpp/grammar/__init__.py +404 -0
  35. xr_syntax/cpp/invocation.py +244 -0
  36. xr_syntax/cpp/lexer.py +414 -0
  37. xr_syntax/cpp/lexical.py +112 -0
  38. xr_syntax/cpp/parser.py +381 -0
  39. xr_syntax/cpp/syntax_utils.py +158 -0
  40. xr_syntax/cpp/view.py +385 -0
  41. xr_syntax/format/__init__.py +43 -0
  42. xr_syntax/format/document.py +223 -0
  43. xr_syntax/py.typed +0 -0
  44. xr_syntax-0.1.0.dist-info/METADATA +670 -0
  45. xr_syntax-0.1.0.dist-info/RECORD +48 -0
  46. xr_syntax-0.1.0.dist-info/WHEEL +5 -0
  47. xr_syntax-0.1.0.dist-info/licenses/LICENSE +202 -0
  48. xr_syntax-0.1.0.dist-info/top_level.txt +1 -0
xr_syntax/__init__.py ADDED
@@ -0,0 +1,59 @@
1
+ """定义 xr-syntax 顶层公共接口,集中导出语言无关语法核心以及 C++ 前端的常用类型。
2
+ Public package surface for the language-neutral source model and C++ frontend.
3
+ """
4
+
5
+ from .core import (
6
+ Diagnostic,
7
+ GreenChild,
8
+ GreenNode,
9
+ GreenToken,
10
+ GreenTrivia,
11
+ ParserKindInfo,
12
+ ParserSchema,
13
+ SourcePoint,
14
+ SourceSpan,
15
+ SyntaxElement,
16
+ SyntaxFragment,
17
+ SyntaxNode,
18
+ SyntaxToken,
19
+ SyntaxTree,
20
+ SyntaxTrivia,
21
+ )
22
+ from .cpp import (
23
+ CppBlockBuilder,
24
+ CppDocument,
25
+ CppFactory,
26
+ CppFileBuilder,
27
+ CppFunctionBuilder,
28
+ CppParser,
29
+ CppRegion,
30
+ )
31
+
32
+ # ---------------------------------------------------------------------------
33
+ # 模块实现:定义 xr-syntax 顶层公共接口,集中导出语言无关语法核心以及 C++ 前端的常用类型。
34
+ # ---------------------------------------------------------------------------
35
+
36
+ __all__ = [
37
+ "CppBlockBuilder",
38
+ "CppDocument",
39
+ "CppFactory",
40
+ "CppFileBuilder",
41
+ "CppFunctionBuilder",
42
+ "CppParser",
43
+ "CppRegion",
44
+ "Diagnostic",
45
+ "GreenChild",
46
+ "GreenNode",
47
+ "GreenToken",
48
+ "GreenTrivia",
49
+ "ParserKindInfo",
50
+ "ParserSchema",
51
+ "SourcePoint",
52
+ "SourceSpan",
53
+ "SyntaxElement",
54
+ "SyntaxFragment",
55
+ "SyntaxNode",
56
+ "SyntaxToken",
57
+ "SyntaxTree",
58
+ "SyntaxTrivia",
59
+ ]
@@ -0,0 +1,26 @@
1
+ """定义 CMake 前端公共接口;它与 C++ 前端共享同一套不可变语法树、重写和布局基础设施。
2
+ CMake frontend built on the same syntax core and edit model as C++.
3
+ """
4
+
5
+ from .builder import CMakeFileBuilder
6
+ from .document import CMakeDocument
7
+ from .factory import CMakeFactory
8
+ from .grammar import CMAKE_GRAMMAR, GRAMMAR_REVISION, GRAMMAR_VERSION
9
+ from .parser import CMakeParser
10
+ from .view import CMakeArgumentView, CMakeCommandView
11
+
12
+ # ---------------------------------------------------------------------------
13
+ # 模块实现:定义 CMake 前端公共接口;它与 C++ 前端共享同一套不可变语法树、重写和布局基础设施。
14
+ # ---------------------------------------------------------------------------
15
+
16
+ __all__ = [
17
+ "CMAKE_GRAMMAR",
18
+ "CMakeArgumentView",
19
+ "CMakeCommandView",
20
+ "CMakeDocument",
21
+ "CMakeFactory",
22
+ "CMakeFileBuilder",
23
+ "CMakeParser",
24
+ "GRAMMAR_REVISION",
25
+ "GRAMMAR_VERSION",
26
+ ]
@@ -0,0 +1,91 @@
1
+ """提供只在 build() 边界解析一次的 CMake 文件构建器。
2
+ CMake file builder that parses once at the build() boundary.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from collections.abc import Iterable
8
+ from dataclasses import dataclass, field
9
+
10
+ from xr_syntax.core import SourceDraft, SyntaxFragment
11
+
12
+ from .document import CMakeDocument
13
+ from .factory import CMakeFactory
14
+
15
+ # ---------------------------------------------------------------------------
16
+ # 模块实现:提供只在 build() 边界解析一次的 CMake 文件构建器。
17
+ # ---------------------------------------------------------------------------
18
+
19
+ @dataclass
20
+ class CMakeFileBuilder:
21
+ """累积 CMake source draft,并在 build() 时统一解析。
22
+ Accumulate CMake source drafts and parse the complete file once in build().
23
+ """
24
+
25
+ factory: CMakeFactory = field(default_factory=CMakeFactory)
26
+ items: list[SourceDraft | SyntaxFragment] = field(default_factory=list)
27
+
28
+ def add(self, item: SourceDraft | SyntaxFragment) -> SourceDraft | SyntaxFragment:
29
+ """追加同语言 draft 或已验证 fragment。
30
+ Append a same-language draft or validated fragment.
31
+ """
32
+ self.factory._source_of(item)
33
+ self.items.append(item)
34
+ return item
35
+
36
+ def raw(self, source: str) -> SourceDraft:
37
+ """追加原始 CMake source draft。
38
+ Append raw CMake source for validation by the final parse.
39
+ """
40
+ draft = SourceDraft(self.factory.language, source)
41
+ self.add(draft)
42
+ return draft
43
+
44
+ def comment(self, text: str) -> SourceDraft:
45
+ """追加 CMake 注释 draft。
46
+ Append one CMake comment draft.
47
+ """
48
+ draft = self.factory._comment_draft(text)
49
+ self.add(draft)
50
+ return draft
51
+
52
+ def command(
53
+ self,
54
+ name: str,
55
+ arguments: Iterable[str] = (),
56
+ ) -> SourceDraft:
57
+ """追加 CMake 命令 draft。
58
+ Append one CMake command draft.
59
+ """
60
+ draft = self.factory._command_draft(name, arguments)
61
+ self.add(draft)
62
+ return draft
63
+
64
+ def if_block(
65
+ self,
66
+ condition: Iterable[str],
67
+ body: Iterable[SourceDraft | SyntaxFragment],
68
+ ) -> SourceDraft:
69
+ """追加完整的 if()/endif() 条件块 draft。
70
+ Append one complete if()/endif() block draft.
71
+ """
72
+ draft = self.factory._if_block_draft(condition, body)
73
+ self.add(draft)
74
+ return draft
75
+
76
+ def build(self, *, require_clean: bool = False) -> CMakeDocument:
77
+ """渲染全部源码并只 parse 一次;可要求生成结果没有 diagnostics。
78
+ Parse the complete generated file once and optionally require a clean result.
79
+ """
80
+ rendered = [
81
+ self.factory._source_of(item).rstrip("\r\n")
82
+ for item in self.items
83
+ ]
84
+ source = "\n".join(rendered)
85
+ if source and not source.endswith("\n"):
86
+ source += "\n"
87
+ document = CMakeDocument.parse(source, parser=self.factory.parser)
88
+ if require_clean and document.diagnostics:
89
+ messages = "; ".join(item.message for item in document.diagnostics)
90
+ raise ValueError(f"generated CMake source has parser diagnostics: {messages}")
91
+ return document
@@ -0,0 +1,90 @@
1
+ """提供面向 CMake 的高层文档查询接口,底层仍使用语言无关的不可变语法模型。
2
+ High-level CMake document queries over the generic syntax model.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from xr_syntax.core import SyntaxDocument, SyntaxElement, SyntaxNode
8
+
9
+ from .grammar import CMAKE_GRAMMAR
10
+ from .parser import CMakeParser
11
+ from .view import CMakeCommandView
12
+
13
+ # ---------------------------------------------------------------------------
14
+ # 基于共享语法核心实现的 CMake 文档查询
15
+ # CMake document queries using the shared syntax core
16
+ # ---------------------------------------------------------------------------
17
+
18
+ class CMakeDocument(SyntaxDocument):
19
+ """在通用不可变语法树之上提供 CMake 专用查询和编辑接口。
20
+ CMake-specific query facade over the same immutable syntax core used by C++.
21
+ """
22
+ __slots__ = ()
23
+
24
+ language = "cmake"
25
+ grammar = CMAKE_GRAMMAR
26
+
27
+ @classmethod
28
+ def parse(
29
+ cls,
30
+ source: str | bytes,
31
+ *,
32
+ source_name: str | None = None,
33
+ parser: CMakeParser | None = None,
34
+ ) -> CMakeDocument:
35
+ """使用可选的固定版本 CMake grammar 解析文本或字节并创建文档快照。
36
+ Parse CMake source using the optional pinned language-pack grammar.
37
+ """
38
+ selected = parser or CMakeParser()
39
+ return cls(
40
+ selected.parse(source, source_name=source_name),
41
+ selected,
42
+ )
43
+
44
+ def comments(self) -> tuple[SyntaxElement, ...]:
45
+ """按源码顺序返回全部 CMake 注释节点。
46
+ Return CMake comments in source order.
47
+ """
48
+ return self.elements("comment")
49
+
50
+ def commands(self, name: str | None = None) -> tuple[SyntaxNode, ...]:
51
+ """返回 CMake 命令节点,并可按命令名进行大小写不敏感过滤。
52
+ Return command nodes, optionally filtered case-insensitively by command name.
53
+ """
54
+ nodes = tuple(
55
+ node
56
+ for node in self.root.descendants(include_self=True)
57
+ if isinstance(node, SyntaxNode)
58
+ and (node.kind == "normal_command" or node.kind.endswith("_command"))
59
+ )
60
+ if name is None:
61
+ return nodes
62
+ normalized = name.casefold()
63
+ return tuple(
64
+ node
65
+ for node in nodes
66
+ if CMakeCommandView(node).name.casefold() == normalized
67
+ )
68
+
69
+ def command_views(self, name: str | None = None) -> tuple[CMakeCommandView, ...]:
70
+ """返回类型化命令视图,并可按命令名过滤。
71
+ Return typed command views, optionally filtered by command name.
72
+ """
73
+ return tuple(CMakeCommandView(node) for node in self.commands(name))
74
+
75
+ def blocks(self) -> tuple[SyntaxNode, ...]:
76
+ """返回 if、foreach、while、function、macro 等结构化块节点。
77
+ Return structured block nodes such as if/foreach/while/function/macro constructs.
78
+ """
79
+ kinds = {
80
+ "if_condition",
81
+ "foreach_loop",
82
+ "while_loop",
83
+ "function_def",
84
+ "macro_def",
85
+ }
86
+ return tuple(
87
+ node
88
+ for node in self.root.descendants(include_self=True)
89
+ if isinstance(node, SyntaxNode) and node.kind in kinds
90
+ )
@@ -0,0 +1,158 @@
1
+ """提供 CMake 命令、注释和条件块的 parser-backed 片段工厂。
2
+ Factories for parser-backed CMake source fragments.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from collections.abc import Iterable
8
+
9
+ from xr_syntax.core import GreenToken, SourceDraft, SyntaxElement, SyntaxFragment, SyntaxNode
10
+ from xr_syntax.format import Group, Indent, concat, join, line, render, softline
11
+
12
+ from .document import CMakeDocument
13
+ from .parser import CMakeParser
14
+
15
+ # ---------------------------------------------------------------------------
16
+ # 模块实现:提供 CMake 命令、注释和条件块的 parser-backed 片段工厂。
17
+ # ---------------------------------------------------------------------------
18
+
19
+ class CMakeFactory:
20
+ """创建带 CMake 语言归属的 parser-backed 片段。
21
+ Create parser-backed fragments carrying explicit CMake language provenance.
22
+ """
23
+
24
+ language = "cmake"
25
+
26
+ def __init__(
27
+ self,
28
+ parser: CMakeParser | None = None,
29
+ *,
30
+ width: int = 100,
31
+ ) -> None:
32
+ """初始化 CMake 片段工厂并保存布局宽度。
33
+ Initialize the CMake fragment factory and store its layout width.
34
+ """
35
+ self.parser = parser or CMakeParser()
36
+ self.width = width
37
+
38
+ def raw(self, source: str) -> SyntaxFragment:
39
+ """创建显式 opaque 的原始 CMake 片段。
40
+ Create an explicit opaque CMake source fragment.
41
+ """
42
+ return SyntaxFragment(
43
+ self.language,
44
+ GreenToken("raw", source, named=True),
45
+ opaque=True,
46
+ )
47
+
48
+ def comment(self, text: str) -> SyntaxFragment:
49
+ """创建一条 CMake 行注释片段。
50
+ Create one CMake line-comment fragment.
51
+ """
52
+ draft = self._comment_draft(text)
53
+ return self._fragment(self._first_element(draft.source, "comment"))
54
+
55
+ def command(
56
+ self,
57
+ name: str,
58
+ arguments: Iterable[str] = (),
59
+ ) -> SyntaxFragment:
60
+ """按给定宽度创建一个 CMake 命令片段。
61
+ Create one CMake command fragment with width-aware argument layout.
62
+ """
63
+ draft = self._command_draft(name, arguments)
64
+ return self._fragment(self._first_node(draft.source, "normal_command"))
65
+
66
+ def if_block(
67
+ self,
68
+ condition: Iterable[str],
69
+ body: Iterable[SyntaxFragment],
70
+ ) -> SyntaxFragment:
71
+ """由条件和 body 片段创建 if()/endif() 块。
72
+ Create a complete if()/endif() block from condition and body fragments.
73
+ """
74
+ draft = self._if_block_draft(condition, body)
75
+ return self._fragment(self._first_node(draft.source, "if_condition"))
76
+
77
+ def _comment_draft(self, text: str) -> SourceDraft:
78
+ """生成尚未解析的 CMake 注释源码。
79
+ Build unparsed source for one CMake comment.
80
+ """
81
+ return SourceDraft(self.language, f"# {text}")
82
+
83
+ def _command_draft(
84
+ self,
85
+ name: str,
86
+ arguments: Iterable[str] = (),
87
+ ) -> SourceDraft:
88
+ """通过布局 IR 生成尚未解析的 CMake 命令源码。
89
+ Render one unparsed CMake command through the layout IR.
90
+ """
91
+ document = Group(
92
+ concat(
93
+ name,
94
+ "(",
95
+ Indent(
96
+ concat(
97
+ softline,
98
+ join(line, tuple(arguments)),
99
+ )
100
+ ),
101
+ softline,
102
+ ")",
103
+ )
104
+ )
105
+ return SourceDraft(self.language, render(document, width=self.width))
106
+
107
+ def _if_block_draft(
108
+ self,
109
+ condition: Iterable[str],
110
+ body: Iterable[SourceDraft | SyntaxFragment],
111
+ ) -> SourceDraft:
112
+ """生成尚未解析的 if()/endif() 块源码。
113
+ Build unparsed source for one if()/endif() block.
114
+ """
115
+ opening = self._command_draft("if", condition).source
116
+ body_text = "\n".join(
117
+ self._source_of(item).rstrip("\r\n") for item in body
118
+ )
119
+ rendered = [opening]
120
+ if body_text:
121
+ rendered.append(body_text)
122
+ rendered.append("endif()")
123
+ return SourceDraft(self.language, "\n".join(rendered))
124
+
125
+ def _source_of(self, item: SourceDraft | SyntaxFragment) -> str:
126
+ """返回同语言 draft/fragment 的源码文本。
127
+ Return source text from a same-language draft or syntax fragment.
128
+ """
129
+ if isinstance(item, SourceDraft):
130
+ return item.source_for(self.language)
131
+ item.green_for(self.language)
132
+ return item.render()
133
+
134
+ def _fragment(self, element: SyntaxElement) -> SyntaxFragment:
135
+ """把解析元素包装成 CMake fragment。
136
+ Wrap one parsed syntax element as a CMake fragment.
137
+ """
138
+ return SyntaxFragment(self.language, element.green)
139
+
140
+ def _first_element(self, source: str, kind: str) -> SyntaxElement:
141
+ """返回临时解析结果中指定 kind 的第一个元素。
142
+ Return the first parsed syntax element of the requested kind.
143
+ """
144
+ document = CMakeDocument.parse(source, parser=self.parser)
145
+ elements = document.elements(kind)
146
+ if not elements:
147
+ raise ValueError(f"generated CMake fragment did not contain {kind}")
148
+ return elements[0]
149
+
150
+ def _first_node(self, source: str, kind: str) -> SyntaxNode:
151
+ """返回临时解析结果中指定 kind 的第一个节点。
152
+ Return the first parsed node of the requested kind.
153
+ """
154
+ document = CMakeDocument.parse(source, parser=self.parser)
155
+ nodes = document.nodes(kind)
156
+ if not nodes:
157
+ raise ValueError(f"generated CMake fragment did not contain {kind}")
158
+ return nodes[0]
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Uy Ha
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,61 @@
1
+ """加载并校验固定版本的 CMake grammar 元数据。
2
+ Load and validate pinned CMake grammar metadata.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import hashlib
8
+ import json
9
+ import pkgutil
10
+ from typing import Any
11
+
12
+ from xr_syntax.core import LanguageGrammar
13
+
14
+ GRAMMAR_VERSION = "0.7.4"
15
+ GRAMMAR_REVISION = "ca627bb5828616b6246aafdc3c3222789e728e37"
16
+ NODE_TYPES_SHA256 = "e696c1156c9916d1d26f2e4643b6d32794dd079b0c8640aa1dabf2f33a3f5cdf"
17
+
18
+
19
+ def _load() -> LanguageGrammar:
20
+ """读取、校验 CMake grammar 元数据并构造 LanguageGrammar。
21
+ Load and validate CMake grammar metadata and build a LanguageGrammar.
22
+ """
23
+ payload = pkgutil.get_data(__package__, "node-types.json")
24
+ if payload is None:
25
+ raise RuntimeError("packaged CMake grammar schema is missing")
26
+
27
+ # Windows checkout 可能使用 CRLF,校验前统一为 LF。
28
+ # Windows checkouts may use CRLF, so normalize to LF before hashing.
29
+ text = payload.decode("utf-8").replace("\r\n", "\n").replace("\r", "\n")
30
+ normalized = text.encode("utf-8")
31
+ digest = hashlib.sha256(normalized).hexdigest()
32
+ if digest != NODE_TYPES_SHA256:
33
+ raise RuntimeError(
34
+ "packaged CMake grammar schema checksum mismatch: "
35
+ f"{digest} != {NODE_TYPES_SHA256}"
36
+ )
37
+
38
+ decoded: Any = json.loads(text)
39
+ if not isinstance(decoded, list) or not all(
40
+ isinstance(item, dict) for item in decoded
41
+ ):
42
+ raise RuntimeError("packaged CMake node-types schema has an invalid root")
43
+
44
+ return LanguageGrammar.from_node_types(
45
+ language="cmake",
46
+ version=GRAMMAR_VERSION,
47
+ source_revision=GRAMMAR_REVISION,
48
+ source_sha256=NODE_TYPES_SHA256,
49
+ data=decoded,
50
+ )
51
+
52
+
53
+ CMAKE_GRAMMAR = _load()
54
+
55
+
56
+ __all__ = [
57
+ "CMAKE_GRAMMAR",
58
+ "GRAMMAR_REVISION",
59
+ "GRAMMAR_VERSION",
60
+ "NODE_TYPES_SHA256",
61
+ ]