infinity-data 1.0.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 (52) hide show
  1. infinity_data/__init__.py +41 -0
  2. infinity_data/emit/__init__.py +9 -0
  3. infinity_data/emit/converter.py +55 -0
  4. infinity_data/frontend.py +37 -0
  5. infinity_data/infra/__init__.py +4 -0
  6. infinity_data/infra/diagnostics.py +212 -0
  7. infinity_data/infra/file.py +83 -0
  8. infinity_data/infra/ll1_stream.py +71 -0
  9. infinity_data/infra/location.py +80 -0
  10. infinity_data/infra/path.py +46 -0
  11. infinity_data/parser/__init__.py +79 -0
  12. infinity_data/parser/diagnostics.py +92 -0
  13. infinity_data/parser/models.py +295 -0
  14. infinity_data/parser/parser.py +988 -0
  15. infinity_data/parser/token_stream.py +128 -0
  16. infinity_data/pipeline.py +252 -0
  17. infinity_data/sandbox/__init__.py +32 -0
  18. infinity_data/sandbox/config.py +61 -0
  19. infinity_data/sandbox/errors.py +106 -0
  20. infinity_data/sandbox/mediator.py +214 -0
  21. infinity_data/sandbox/schema.py +21 -0
  22. infinity_data/semantic/__init__.py +59 -0
  23. infinity_data/semantic/builder/__init__.py +29 -0
  24. infinity_data/semantic/builder/builder.py +523 -0
  25. infinity_data/semantic/builder/models.py +163 -0
  26. infinity_data/semantic/constraints.py +163 -0
  27. infinity_data/semantic/diagnostics.py +172 -0
  28. infinity_data/semantic/executor/__init__.py +10 -0
  29. infinity_data/semantic/executor/executor.py +259 -0
  30. infinity_data/semantic/registry/__init__.py +168 -0
  31. infinity_data/semantic/registry/_core.py +212 -0
  32. infinity_data/semantic/registry/dict_constraints.py +56 -0
  33. infinity_data/semantic/registry/general.py +362 -0
  34. infinity_data/semantic/registry/logic.py +134 -0
  35. infinity_data/semantic/registry/types.py +136 -0
  36. infinity_data/semantic/resolver/__init__.py +20 -0
  37. infinity_data/semantic/resolver/imports.py +191 -0
  38. infinity_data/semantic/resolver/models.py +67 -0
  39. infinity_data/semantic/resolver/resolver.py +345 -0
  40. infinity_data/tokenizer/__init__.py +16 -0
  41. infinity_data/tokenizer/char_stream.py +72 -0
  42. infinity_data/tokenizer/diagnostics.py +62 -0
  43. infinity_data/tokenizer/finalizer.py +271 -0
  44. infinity_data/tokenizer/models/__init__.py +17 -0
  45. infinity_data/tokenizer/models/raw_tokens.py +61 -0
  46. infinity_data/tokenizer/models/tokens.py +245 -0
  47. infinity_data/tokenizer/tokenizer.py +531 -0
  48. infinity_data-1.0.0.dist-info/METADATA +60 -0
  49. infinity_data-1.0.0.dist-info/RECORD +52 -0
  50. infinity_data-1.0.0.dist-info/WHEEL +5 -0
  51. infinity_data-1.0.0.dist-info/licenses/LICENSE +21 -0
  52. infinity_data-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,79 @@
1
+ """语法分析:RawAst 数据模型与解析器。
2
+
3
+ - :class:`Parser`:LL(1) 递归下降解析器(parser.py)
4
+ - RawAst 数据模型(models.py):Document / 语句 / 值 / 约束 / 模板定义节点
5
+
6
+ 公共面从此包再导出,兼容 ``from infinity_data.parser import Document``;
7
+ 内部实现文件(models.py / parser.py / token_stream.py)不直接引用。
8
+
9
+ 注意:parser 包内部文件仍从 ``parser.models`` 模块级导入(避免经包根
10
+ ``__init__`` 触发自引用循环)——此约定与 semantic 子包一致。
11
+ """
12
+
13
+ from infinity_data.parser.models import (
14
+ ArrayValue,
15
+ AstNode,
16
+ Constraint,
17
+ ConstraintCall,
18
+ ConstraintIdent,
19
+ ConstraintLiteral,
20
+ Constraints,
21
+ ConstraintStmt,
22
+ DictValue,
23
+ Document,
24
+ DollarValue,
25
+ EnvImportStmt,
26
+ ErrorConstraint,
27
+ ErrorStatement,
28
+ ErrorValue,
29
+ Field,
30
+ FileImportItem,
31
+ FileImportStmt,
32
+ JsonPathIndex,
33
+ JsonPathKey,
34
+ JsonPathSegment,
35
+ LiteralValue,
36
+ Statement,
37
+ TemplateCallValue,
38
+ TemplateConfig,
39
+ TemplateDef,
40
+ TemplateField,
41
+ TemplateImportItem,
42
+ TemplateImportStmt,
43
+ Value,
44
+ )
45
+ from infinity_data.parser.parser import Parser
46
+
47
+ __all__ = [
48
+ 'ArrayValue',
49
+ 'AstNode',
50
+ 'Constraint',
51
+ 'ConstraintCall',
52
+ 'ConstraintIdent',
53
+ 'ConstraintLiteral',
54
+ 'Constraints',
55
+ 'ConstraintStmt',
56
+ 'DictValue',
57
+ 'Document',
58
+ 'DollarValue',
59
+ 'EnvImportStmt',
60
+ 'ErrorConstraint',
61
+ 'ErrorStatement',
62
+ 'ErrorValue',
63
+ 'Field',
64
+ 'FileImportItem',
65
+ 'FileImportStmt',
66
+ 'JsonPathIndex',
67
+ 'JsonPathKey',
68
+ 'JsonPathSegment',
69
+ 'LiteralValue',
70
+ 'Parser',
71
+ 'Statement',
72
+ 'TemplateCallValue',
73
+ 'TemplateConfig',
74
+ 'TemplateDef',
75
+ 'TemplateField',
76
+ 'TemplateImportItem',
77
+ 'TemplateImportStmt',
78
+ 'Value',
79
+ ]
@@ -0,0 +1,92 @@
1
+ """语法分析阶段诊断构造器与诊断定义。
2
+
3
+ 语法错误统一为 :class:`Diagnostic`(纯数据,从不抛异常);
4
+ :func:`diag` 便捷构造语法错误诊断,收集使用 :class:`DiagnosticCollector`。
5
+ 诊断定义(``parse.*``)导入时注册进全局注册表(:func:`register`)。
6
+ """
7
+
8
+ from typing import Any
9
+
10
+ from infinity_data.infra.diagnostics import Diagnostic, Severity, diagnostic_define, register_diagnostic_define
11
+ from infinity_data.infra.location import SourceRange
12
+
13
+ __all__ = ['diag']
14
+
15
+ register_diagnostic_define(
16
+ diagnostic_define(
17
+ 'parse.unrecognized_statement',
18
+ '[{location}] 无法识别的顶层 token: {name}',
19
+ en='[{location}] unrecognized top-level token: {name}',
20
+ ),
21
+ diagnostic_define(
22
+ 'parse.unrecognized_import', '[{location}] 无法识别的导入语句', en='[{location}] unrecognized import statement'
23
+ ),
24
+ diagnostic_define(
25
+ 'parse.unexpected_token',
26
+ '[{location}] 期望 {expected},实际为 {actual}',
27
+ en='[{location}] expected {expected}, got {actual}',
28
+ ),
29
+ diagnostic_define(
30
+ 'parse.template_arg_order',
31
+ '[{location}] 位置参数不能出现在命名参数之后',
32
+ en='[{location}] positional arguments cannot follow named arguments',
33
+ ),
34
+ diagnostic_define('parse.empty_token_list', 'Token 列表为空,无法解析', en='empty token list, nothing to parse'),
35
+ diagnostic_define(
36
+ 'parse.invalid_json_path', '[{location}] 无效的 JSON 路径{detail}', en='[{location}] invalid JSON path{detail}'
37
+ ),
38
+ diagnostic_define(
39
+ 'parse.unrecognized_value', '[{location}] 无法解析的值: {name}', en='[{location}] unrecognized value: {name}'
40
+ ),
41
+ diagnostic_define(
42
+ 'parse.missing_separator',
43
+ '[{location}] 元素之间缺少分隔符(逗号或换行,空格不构成分隔)',
44
+ en='[{location}] missing separator between elements (comma or newline; space is not a separator)',
45
+ ),
46
+ diagnostic_define(
47
+ 'parse.value_field',
48
+ '[{location}] 值位置出现字段定义 {name}(外层数组/对象未闭合)',
49
+ en='[{location}] field definition {name} in value position (enclosing array/object unclosed)',
50
+ ),
51
+ diagnostic_define(
52
+ 'parse.field_requires_equals',
53
+ '[{location}] 字段 {name} 省略等号仅限复合值与模板调用,字面量/引用须用 = 赋值',
54
+ en='[{location}] field {name}: "=" required here (omit "=" only for dict/array/template call)',
55
+ ),
56
+ diagnostic_define(
57
+ 'parse.template_field_no_constraint',
58
+ '[{location}] 模板字段 {field} 必须有类型标注(如 {field}: int)',
59
+ en='[{location}] template field {field} requires a type annotation (e.g. {field}: int)',
60
+ ),
61
+ diagnostic_define(
62
+ 'parse.invalid_cast',
63
+ '[{location}] 未知的类型转换 {type}(合法: bool/int/float/str)',
64
+ en='[{location}] unknown cast type {type} (valid: bool/int/float/str)',
65
+ ),
66
+ diagnostic_define(
67
+ 'parse.unrecognized_constraint',
68
+ '[{location}] 无法解析的约束: {name}',
69
+ en='[{location}] unrecognized constraint: {name}',
70
+ ),
71
+ diagnostic_define('parse.statement_error', '{path_prefix}{message}'),
72
+ diagnostic_define(
73
+ 'parse.template_config_unknown',
74
+ '[{location}] 未知的模板配置项: {key}(合法项: {valid})',
75
+ en='[{location}] unknown template config key: {key} (valid: {valid})',
76
+ ),
77
+ diagnostic_define(
78
+ 'parse.template_config_type',
79
+ '[{location}] 模板配置 {key} 期望 {expected},实际为 {actual}',
80
+ en='[{location}] template config {key} expects {expected}, got {actual}',
81
+ ),
82
+ diagnostic_define(
83
+ 'parse.template_config_value',
84
+ '[{location}] 模板配置 {key} 必须是字面量(不支持 $ 引用 / 模板调用)',
85
+ en='[{location}] template config {key} must be a literal (no $ refs / template calls)',
86
+ ),
87
+ )
88
+
89
+
90
+ def diag(code: str, params: dict[str, Any], source: SourceRange | None) -> Diagnostic:
91
+ """构造语法阶段错误诊断(severity 恒为 ERROR)。"""
92
+ return Diagnostic(Severity.ERROR, code, params, source)
@@ -0,0 +1,295 @@
1
+ """语法分析阶段 AST 节点(RawAst)。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from typing import Literal
7
+
8
+ from infinity_data.tokenizer.models.raw_tokens import SourceRange
9
+ from infinity_data.tokenizer.models.tokens import (
10
+ BoolToken,
11
+ FloatToken,
12
+ IntegerToken,
13
+ NoexistToken,
14
+ NullToken,
15
+ StringToken,
16
+ )
17
+
18
+
19
+ # ═══════════════════════════════════════════════════════════
20
+ # 节点
21
+ # ═══════════════════════════════════════════════════════════
22
+ @dataclass
23
+ class AstNode:
24
+ """AST 节点基类。"""
25
+
26
+ source: SourceRange
27
+
28
+
29
+ # ═══════════════════════════════════════════════════════════
30
+ # 文档
31
+ # ═══════════════════════════════════════════════════════════
32
+
33
+
34
+ @dataclass
35
+ class Document(AstNode):
36
+ """顶层文档,包含一组语句。
37
+
38
+ 顶层是隐式 dict;``: <constraint, ...>`` 以 :class:`ConstraintStmt`
39
+ 形式出现在 statements 中,语义分析阶段作用于编译产物 root。
40
+ """
41
+
42
+ statements: list[Statement] = field(default_factory=lambda: [])
43
+
44
+
45
+ # ═══════════════════════════════════════════════════════════
46
+ # 语句
47
+ # ═══════════════════════════════════════════════════════════
48
+
49
+
50
+ @dataclass
51
+ class TemplateImportItem(AstNode):
52
+ """模板导入项: Name [as Alias]。"""
53
+
54
+ name: str # 被导入文件中的模板名
55
+ alias: str | None = None # 本地别名(可选)
56
+
57
+
58
+ @dataclass
59
+ class TemplateImportStmt(AstNode):
60
+ """模板导入: !from "path" import Name1, Name2 as N2"""
61
+
62
+ from_path: str # 文件路径(unix 风格)
63
+ items: list[TemplateImportItem] # 导入项列表
64
+
65
+
66
+ @dataclass
67
+ class EnvImportStmt(AstNode):
68
+ """环境变量导入: !env import NAME [as NEW_NAME]"""
69
+
70
+ name: str # 环境变量名
71
+ alias: str | None # 别名(可选)
72
+
73
+
74
+ @dataclass
75
+ class JsonPathKey(AstNode):
76
+ """JSON 路径中的键访问: .key 或 .\"key\""""
77
+
78
+ key: str
79
+
80
+
81
+ @dataclass
82
+ class JsonPathIndex(AstNode):
83
+ """JSON 路径中的索引访问: [N]"""
84
+
85
+ index: int
86
+
87
+
88
+ type JsonPathSegment = JsonPathKey | JsonPathIndex
89
+
90
+
91
+ @dataclass
92
+ class FileImportItem(AstNode):
93
+ """配置文件导入项。"""
94
+
95
+ json_path: list[JsonPathSegment] # 路径段列表;空列表 = 导入整个文件
96
+ alias: str # 别名(必须)
97
+
98
+
99
+ @dataclass
100
+ class FileImportStmt(AstNode):
101
+ """配置文件导入: !file "path" as <format> import .path.to.key as alias, ..."""
102
+
103
+ file_path: str # 文件路径
104
+ format: str | None # 文件格式: "yaml", "json", "toml" 或 None(自动检测后缀)
105
+ imports: list[FileImportItem]
106
+
107
+
108
+ @dataclass
109
+ class TemplateField(AstNode):
110
+ """模板内部字段定义。与普通 Field 不同之处:
111
+ - 必须带有类型约束
112
+ - 默认值可选(省略表示必填字段)
113
+ - 必填字段必须在非必填字段之前
114
+ """
115
+
116
+ name: str
117
+ constraints: Constraints # 模板字段必须有类型标注
118
+ default_value: Value | None # None = 必填字段
119
+
120
+
121
+ @dataclass
122
+ class TemplateConfig:
123
+ """模板头部配置(``~X(key=value)``),语法层解析为类型化字段。
124
+
125
+ - ``allow_extra``:校验时是否放行额外字段(模板即约束 / schema)
126
+ - ``positional``:是否允许位置参数(false = 只接受命名参数)
127
+ - ``description``:模板文档(元数据,暂不消费,供 LSP/文档)
128
+
129
+ 未来新增配置项:在此加字段,parser 侧在对应键集合补一行(字段即白名单)。
130
+ """
131
+
132
+ allow_extra: bool = False
133
+ positional: bool = True
134
+ description: str | None = None
135
+
136
+
137
+ @dataclass
138
+ class TemplateDef(AstNode):
139
+ """模板定义: ~Name { ... } 或 ~Name(config=value) { ... }"""
140
+
141
+ name: str
142
+ fields: list[TemplateField]
143
+ config: TemplateConfig = field(default_factory=TemplateConfig)
144
+ constraints: list[Constraint] = field(default_factory=lambda: [])
145
+
146
+
147
+ @dataclass
148
+ class Field(AstNode):
149
+ """普通字段定义:name[: type] [= value]。
150
+
151
+ 值缺失(裸 key)不是合法语法:语义分析阶段报错。
152
+ noexist 需显式书写 ``= noexist`` 字面量。
153
+ """
154
+
155
+ name: str
156
+ constraints: Constraints | None = None
157
+ value: Value | None = None
158
+
159
+
160
+ @dataclass
161
+ class ConstraintStmt(AstNode):
162
+ """顶层结构级约束: ``: <constraint, ...>``(作用于编译产物 root)。
163
+
164
+ 顶层是隐式 dict,``:`` 起始的语句约束整个 root,而非某个字段。
165
+ 约束函数与字段级约束共用同一注册表。
166
+ """
167
+
168
+ constraints: list[Constraint]
169
+
170
+
171
+ # ═══════════════════════════════════════════════════════════
172
+ # 约束
173
+ # ═══════════════════════════════════════════════════════════
174
+
175
+
176
+ @dataclass
177
+ class ConstraintIdent(AstNode):
178
+ """简单约束标识符,如 int, str, ?"""
179
+
180
+ name: str
181
+
182
+
183
+ @dataclass
184
+ class ConstraintCall(AstNode):
185
+ """约束函数调用,如 each(str)、range(1, 10)、not(?)、any(int, str)。"""
186
+
187
+ name: str
188
+ arguments: list[Constraint] = field(default_factory=lambda: [])
189
+
190
+
191
+ @dataclass
192
+ class ConstraintLiteral(AstNode):
193
+ """约束中的字面量参数,如 range(1, 10) 中的 1、10。"""
194
+
195
+ value: LiteralValue
196
+
197
+
198
+ type Constraint = ConstraintIdent | ConstraintCall | ConstraintLiteral | ErrorConstraint
199
+
200
+
201
+ @dataclass
202
+ class Constraints(AstNode):
203
+ """约束列表,如 int, str?, <int, range(1,10)>, <int, each(str)>。
204
+
205
+ 语义说明:
206
+ - constraints 列表,若 len > 1,隐含 all(constraint1, constraint2, ...)
207
+ """
208
+
209
+ constraints: list[Constraint] = field(default_factory=lambda: [])
210
+
211
+
212
+ # ═══════════════════════════════════════════════════════════
213
+ # 值
214
+ # ═══════════════════════════════════════════════════════════
215
+
216
+
217
+ @dataclass
218
+ class LiteralValue(AstNode):
219
+ """字面量值"""
220
+
221
+ value: FloatToken | IntegerToken | BoolToken | NullToken | NoexistToken | StringToken
222
+
223
+
224
+ @dataclass
225
+ class DollarValue(AstNode):
226
+ """$ 导入空间引用: $NAME [as type]。
227
+
228
+ 用于引用 !env import 导入的变量。
229
+ """
230
+
231
+ name: str # 变量名
232
+ type_cast: Literal['int', 'float', 'bool', 'str', None] # 可选类型转换
233
+
234
+
235
+ @dataclass
236
+ class DictValue(AstNode):
237
+ """对象值: { ... }
238
+
239
+ ``: <constraint, ...>`` 结构级约束作用于该字面量 dict 的整体。
240
+ """
241
+
242
+ fields: list[Field]
243
+ constraints: list[Constraint] = field(default_factory=lambda: [])
244
+
245
+
246
+ @dataclass
247
+ class ArrayValue(AstNode):
248
+ """数组值: [ ... ]"""
249
+
250
+ elements: list[Value]
251
+
252
+
253
+ @dataclass
254
+ class TemplateCallValue(AstNode):
255
+ """模板调用: Name(args...)"""
256
+
257
+ template_name: str
258
+ positional_args: list[Value]
259
+ named_args: dict[str, Value]
260
+
261
+
262
+ # ═══════════════════════════════════════════════════════════
263
+ # 错误节点
264
+ # ═══════════════════════════════════════════════════════════
265
+
266
+
267
+ @dataclass
268
+ class ErrorStatement(AstNode):
269
+ """解析失败的语句。用于错误恢复。"""
270
+
271
+ message: str
272
+
273
+
274
+ @dataclass
275
+ class ErrorValue(AstNode):
276
+ """解析失败的值。用于错误恢复。"""
277
+
278
+ message: str
279
+
280
+
281
+ @dataclass
282
+ class ErrorConstraint(AstNode):
283
+ """解析失败的约束。用于错误恢复。"""
284
+
285
+ message: str
286
+
287
+
288
+ # ═══════════════════════════════════════════════════════════
289
+ # 联合类型
290
+ # ═══════════════════════════════════════════════════════════
291
+
292
+ type Statement = (
293
+ TemplateImportStmt | EnvImportStmt | FileImportStmt | TemplateDef | Field | ConstraintStmt | ErrorStatement
294
+ )
295
+ type Value = LiteralValue | DollarValue | DictValue | ArrayValue | TemplateCallValue | ErrorValue