python-library-ralf-model 0.1.2__py3-none-any.whl → 0.1.3__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.
- {python_library_ralf_model-0.1.2.dist-info → python_library_ralf_model-0.1.3.dist-info}/METADATA +1 -1
- python_library_ralf_model-0.1.3.dist-info/RECORD +11 -0
- ralf_model/__init__.py +2 -1
- ralf_model/emit.py +39 -3
- ralf_model/nodes.py +29 -1
- ralf_model/parse.py +142 -14
- python_library_ralf_model-0.1.2.dist-info/RECORD +0 -11
- {python_library_ralf_model-0.1.2.dist-info → python_library_ralf_model-0.1.3.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
ralf_model/__init__.py,sha256=K7430IXwEwqTp7wR4UCWF7rTaQx48MeQNTepJWAs1Tc,1030
|
|
2
|
+
ralf_model/abc.py,sha256=CjfkbS3dy05uL8vWZzAGQdwMI7CNH3JPeFMdauAa1qI,518
|
|
3
|
+
ralf_model/emit.py,sha256=oSGNeObdFqmWAtmvbKncKgh7ZqJEBfybFvKczpRYPGE,3965
|
|
4
|
+
ralf_model/errors.py,sha256=jhceRWdSfSSG34Il4H8zOjdL6l2KtPkdxSg07LZuLww,922
|
|
5
|
+
ralf_model/io.py,sha256=sQ0riTvRk2btxuU9mVnDg0k_ZtcF8OCiGgPefDnR_Zs,2173
|
|
6
|
+
ralf_model/nodes.py,sha256=nBFteWDOSIfL77HaP9zu-sFZyikn2mTLXigJO8uBvjM,3743
|
|
7
|
+
ralf_model/parse.py,sha256=fZNOqr2_dif-SPNEU_Kyqsmsd5_Li8eIKqMxywWjK3Q,24597
|
|
8
|
+
ralf_model/source_expand.py,sha256=ufHTAU740zMuhmJb2fduK1yT8aUFbVhO3uBxRnlidK8,5228
|
|
9
|
+
python_library_ralf_model-0.1.3.dist-info/METADATA,sha256=zcPJIkRn8Ujj-6aprUGyBaSbHahp5OEsKLqN2W8CIVE,2316
|
|
10
|
+
python_library_ralf_model-0.1.3.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
11
|
+
python_library_ralf_model-0.1.3.dist-info/RECORD,,
|
ralf_model/__init__.py
CHANGED
|
@@ -4,7 +4,7 @@ from ralf_model.abc import AbstractRalfBlock, AbstractRalfField, AbstractRalfReg
|
|
|
4
4
|
from ralf_model.emit import dump_ralf
|
|
5
5
|
from ralf_model.errors import RalfError, RalfParseError, RalfSourceError
|
|
6
6
|
from ralf_model.io import dump_ralf_file, dumps_ralf, load_ralf_file, loads_ralf
|
|
7
|
-
from ralf_model.nodes import BlockNode, FieldNode, RalfDocument, RegisterNode
|
|
7
|
+
from ralf_model.nodes import BlockNode, FieldNode, RalfDocument, RegisterNode, SystemNode
|
|
8
8
|
from ralf_model.parse import normalize_ralf_whitespace, parse_ralf
|
|
9
9
|
from ralf_model.source_expand import expand_ralf_sources, resolve_source_path
|
|
10
10
|
|
|
@@ -16,6 +16,7 @@ __all__ = [
|
|
|
16
16
|
"FieldNode",
|
|
17
17
|
"RalfDocument",
|
|
18
18
|
"RegisterNode",
|
|
19
|
+
"SystemNode",
|
|
19
20
|
"RalfError",
|
|
20
21
|
"RalfParseError",
|
|
21
22
|
"RalfSourceError",
|
ralf_model/emit.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from ralf_model.nodes import BlockNode, FieldNode, RalfDocument, RegisterNode
|
|
3
|
+
from ralf_model.nodes import BlockNode, FieldNode, RalfDocument, RegisterNode, SystemNode
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def _fmt_at_int(v: int) -> str:
|
|
@@ -58,6 +58,35 @@ def _emit_block_open_line(b: BlockNode, indent: str) -> str:
|
|
|
58
58
|
return line
|
|
59
59
|
|
|
60
60
|
|
|
61
|
+
def _emit_system_open_line(s: SystemNode, indent: str) -> str:
|
|
62
|
+
line = f"{indent}system {s.name}"
|
|
63
|
+
if s.rhs_head is not None:
|
|
64
|
+
line += f" = {s.rhs_head}"
|
|
65
|
+
if s.rhs_paren_path is not None:
|
|
66
|
+
line += f" ({s.rhs_paren_path})"
|
|
67
|
+
if s.base_address is not None:
|
|
68
|
+
line += f" @{_fmt_at_int(s.base_address)}"
|
|
69
|
+
elif s.base_address is not None:
|
|
70
|
+
line += f" @{_fmt_at_int(s.base_address)}"
|
|
71
|
+
return line
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _emit_system(s: SystemNode, indent: str) -> list[str]:
|
|
75
|
+
head_line = _emit_system_open_line(s, indent)
|
|
76
|
+
if not s.has_body:
|
|
77
|
+
return [f"{head_line};"]
|
|
78
|
+
lines = [head_line + " {"]
|
|
79
|
+
inner = indent + " "
|
|
80
|
+
if s.bytes_width is not None:
|
|
81
|
+
lines.append(f"{inner}bytes {s.bytes_width};")
|
|
82
|
+
for sub in s.systems:
|
|
83
|
+
lines.extend(_emit_system(sub, inner))
|
|
84
|
+
for sub in s.blocks:
|
|
85
|
+
lines.extend(_emit_block(sub, inner))
|
|
86
|
+
lines.append(indent + "}")
|
|
87
|
+
return lines
|
|
88
|
+
|
|
89
|
+
|
|
61
90
|
def _emit_block(b: BlockNode, indent: str) -> list[str]:
|
|
62
91
|
head_line = _emit_block_open_line(b, indent)
|
|
63
92
|
if not b.has_body:
|
|
@@ -77,8 +106,15 @@ def _emit_block(b: BlockNode, indent: str) -> list[str]:
|
|
|
77
106
|
def dump_ralf(doc: RalfDocument) -> str:
|
|
78
107
|
"""将 `RalfDocument` 序列化为 RALF 源文本(规范化排版)。"""
|
|
79
108
|
out: list[str] = []
|
|
80
|
-
|
|
81
|
-
|
|
109
|
+
first = True
|
|
110
|
+
for s in doc.systems:
|
|
111
|
+
if not first:
|
|
112
|
+
out.append("")
|
|
113
|
+
first = False
|
|
114
|
+
out.extend(_emit_system(s, ""))
|
|
115
|
+
for b in doc.blocks:
|
|
116
|
+
if not first:
|
|
82
117
|
out.append("")
|
|
118
|
+
first = False
|
|
83
119
|
out.extend(_emit_block(b, ""))
|
|
84
120
|
return "\n".join(out) + ("\n" if out else "")
|
ralf_model/nodes.py
CHANGED
|
@@ -69,9 +69,37 @@ class BlockNode(BaseModel):
|
|
|
69
69
|
blocks: list[BlockNode] = Field(default_factory=list)
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
class SystemNode(BaseModel):
|
|
73
|
+
"""层次化 system;体内可嵌套 system 与 block,不含 register。"""
|
|
74
|
+
|
|
75
|
+
model_config = ConfigDict(extra="forbid")
|
|
76
|
+
|
|
77
|
+
name: str
|
|
78
|
+
rhs_head: str | None = Field(
|
|
79
|
+
default=None,
|
|
80
|
+
description="`=` 右侧起始的层级名(含可能的 `[..]` 后缀)",
|
|
81
|
+
)
|
|
82
|
+
rhs_paren_path: str | None = Field(
|
|
83
|
+
default=None,
|
|
84
|
+
description="紧跟在 rhs_head 后的圆括号路径内容(不含括号)",
|
|
85
|
+
)
|
|
86
|
+
base_address: int | None = Field(
|
|
87
|
+
default=None,
|
|
88
|
+
description="`@` 后的地址;可出现于简单 `system 名 @addr` 或 `=` 形式末尾",
|
|
89
|
+
)
|
|
90
|
+
has_body: bool = Field(
|
|
91
|
+
default=True,
|
|
92
|
+
description="是否带有 `{ ... }`;仅分号结尾的声明为 False",
|
|
93
|
+
)
|
|
94
|
+
bytes_width: int | None = None
|
|
95
|
+
systems: list[SystemNode] = Field(default_factory=list)
|
|
96
|
+
blocks: list[BlockNode] = Field(default_factory=list)
|
|
97
|
+
|
|
98
|
+
|
|
72
99
|
class RalfDocument(BaseModel):
|
|
73
|
-
"""顶层 RALF
|
|
100
|
+
"""顶层 RALF 文件内容(顶层为若干 `system`;亦兼容顶层 `block`)。"""
|
|
74
101
|
|
|
75
102
|
model_config = ConfigDict(extra="forbid")
|
|
76
103
|
|
|
104
|
+
systems: list[SystemNode] = Field(default_factory=list)
|
|
77
105
|
blocks: list[BlockNode] = Field(default_factory=list)
|
ralf_model/parse.py
CHANGED
|
@@ -5,7 +5,7 @@ from collections.abc import Sequence
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
from ralf_model.errors import RalfParseError
|
|
8
|
-
from ralf_model.nodes import BlockNode, FieldNode, RalfDocument, RegisterNode
|
|
8
|
+
from ralf_model.nodes import BlockNode, FieldNode, RalfDocument, RegisterNode, SystemNode
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class _Parser:
|
|
@@ -39,11 +39,22 @@ class _Parser:
|
|
|
39
39
|
j = self._i + offset
|
|
40
40
|
return self._s[j] if j < self._n else None
|
|
41
41
|
|
|
42
|
-
def
|
|
42
|
+
def _error_location(self) -> tuple[Path | None, int]:
|
|
43
43
|
path = self._path
|
|
44
|
+
line = self.line
|
|
44
45
|
if self._line_sources and 0 < self.line <= len(self._line_sources):
|
|
45
46
|
path = self._line_sources[self.line - 1]
|
|
46
|
-
|
|
47
|
+
local = 1
|
|
48
|
+
idx = self.line - 2
|
|
49
|
+
while idx >= 0 and self._line_sources[idx] == path:
|
|
50
|
+
local += 1
|
|
51
|
+
idx -= 1
|
|
52
|
+
line = local
|
|
53
|
+
return path, line
|
|
54
|
+
|
|
55
|
+
def _error(self, msg: str) -> None:
|
|
56
|
+
path, line = self._error_location()
|
|
57
|
+
raise RalfParseError(msg, line=line, col=self.col, path=path)
|
|
47
58
|
|
|
48
59
|
def skip_ws_and_comments(self) -> None:
|
|
49
60
|
while self._i < self._n:
|
|
@@ -168,16 +179,19 @@ class _Parser:
|
|
|
168
179
|
self._error("期望 ;")
|
|
169
180
|
|
|
170
181
|
def parse_document(self) -> RalfDocument:
|
|
182
|
+
systems: list[SystemNode] = []
|
|
171
183
|
blocks: list[BlockNode] = []
|
|
172
184
|
self.skip_ws_and_comments()
|
|
173
185
|
while self._i < self._n:
|
|
174
186
|
kw = self._peek_keyword()
|
|
175
|
-
if kw == "
|
|
187
|
+
if kw == "system":
|
|
188
|
+
systems.append(self.parse_system())
|
|
189
|
+
elif kw == "block":
|
|
176
190
|
blocks.append(self.parse_block())
|
|
177
191
|
else:
|
|
178
|
-
self._error(f"顶层期望 block,得到 {kw!r}")
|
|
192
|
+
self._error(f"顶层期望 system 或 block,得到 {kw!r}")
|
|
179
193
|
self.skip_ws_and_comments()
|
|
180
|
-
return RalfDocument(blocks=blocks)
|
|
194
|
+
return RalfDocument(systems=systems, blocks=blocks)
|
|
181
195
|
|
|
182
196
|
def _peek_keyword(self) -> str:
|
|
183
197
|
self.skip_ws_and_comments()
|
|
@@ -261,8 +275,8 @@ class _Parser:
|
|
|
261
275
|
self.skip_ws_and_comments()
|
|
262
276
|
return head, paren_inner, addr
|
|
263
277
|
|
|
264
|
-
def
|
|
265
|
-
self.expect_keyword("
|
|
278
|
+
def parse_system(self) -> SystemNode:
|
|
279
|
+
self.expect_keyword("system")
|
|
266
280
|
name = self.read_hierarchical_block_name()
|
|
267
281
|
self.skip_ws_and_comments()
|
|
268
282
|
|
|
@@ -270,14 +284,128 @@ class _Parser:
|
|
|
270
284
|
self._advance()
|
|
271
285
|
addr = self.parse_integer_value()
|
|
272
286
|
self.skip_ws_and_comments()
|
|
273
|
-
self.
|
|
274
|
-
|
|
287
|
+
if self._peek() == ";":
|
|
288
|
+
self._advance()
|
|
289
|
+
return SystemNode(
|
|
290
|
+
name=name,
|
|
291
|
+
base_address=addr,
|
|
292
|
+
has_body=False,
|
|
293
|
+
systems=[],
|
|
294
|
+
blocks=[],
|
|
295
|
+
)
|
|
296
|
+
if self._peek() == "{":
|
|
297
|
+
self._advance()
|
|
298
|
+
bw, subs_sys, subs_blk = self._parse_system_body()
|
|
299
|
+
self.expect_char("}")
|
|
300
|
+
return SystemNode(
|
|
301
|
+
name=name,
|
|
302
|
+
base_address=addr,
|
|
303
|
+
has_body=True,
|
|
304
|
+
bytes_width=bw,
|
|
305
|
+
systems=subs_sys,
|
|
306
|
+
blocks=subs_blk,
|
|
307
|
+
)
|
|
308
|
+
self._error("system @地址 之后应为 ; 或 {")
|
|
309
|
+
|
|
310
|
+
if self._peek() == "=":
|
|
311
|
+
self._advance()
|
|
312
|
+
self.skip_ws_and_comments()
|
|
313
|
+
rhs_head, rhs_path, addr_rhs = self.parse_block_rhs_after_equals()
|
|
314
|
+
self.skip_ws_and_comments()
|
|
315
|
+
if self._peek() == ";":
|
|
316
|
+
self._advance()
|
|
317
|
+
return SystemNode(
|
|
318
|
+
name=name,
|
|
319
|
+
rhs_head=rhs_head,
|
|
320
|
+
rhs_paren_path=rhs_path,
|
|
321
|
+
base_address=addr_rhs,
|
|
322
|
+
has_body=False,
|
|
323
|
+
systems=[],
|
|
324
|
+
blocks=[],
|
|
325
|
+
)
|
|
326
|
+
if self._peek() == "{":
|
|
327
|
+
self._advance()
|
|
328
|
+
bw, subs_sys, subs_blk = self._parse_system_body()
|
|
329
|
+
self.expect_char("}")
|
|
330
|
+
return SystemNode(
|
|
331
|
+
name=name,
|
|
332
|
+
rhs_head=rhs_head,
|
|
333
|
+
rhs_paren_path=rhs_path,
|
|
334
|
+
base_address=addr_rhs,
|
|
335
|
+
has_body=True,
|
|
336
|
+
bytes_width=bw,
|
|
337
|
+
systems=subs_sys,
|
|
338
|
+
blocks=subs_blk,
|
|
339
|
+
)
|
|
340
|
+
self._error("system ... = ... 之后应为 ; 或 {")
|
|
341
|
+
|
|
342
|
+
if self._peek() == "{":
|
|
343
|
+
self._advance()
|
|
344
|
+
bw, subs_sys, subs_blk = self._parse_system_body()
|
|
345
|
+
self.expect_char("}")
|
|
346
|
+
return SystemNode(
|
|
275
347
|
name=name,
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
blocks=
|
|
348
|
+
has_body=True,
|
|
349
|
+
bytes_width=bw,
|
|
350
|
+
systems=subs_sys,
|
|
351
|
+
blocks=subs_blk,
|
|
280
352
|
)
|
|
353
|
+
self._error("system 名称之后应为 @、= 或 {")
|
|
354
|
+
|
|
355
|
+
def _parse_system_body(
|
|
356
|
+
self,
|
|
357
|
+
) -> tuple[int | None, list[SystemNode], list[BlockNode]]:
|
|
358
|
+
bw: int | None = None
|
|
359
|
+
subs_sys: list[SystemNode] = []
|
|
360
|
+
subs_blk: list[BlockNode] = []
|
|
361
|
+
while True:
|
|
362
|
+
self.skip_ws_and_comments()
|
|
363
|
+
if self._peek() == "}":
|
|
364
|
+
break
|
|
365
|
+
kw = self._peek_keyword()
|
|
366
|
+
if kw == "bytes":
|
|
367
|
+
self.expect_keyword("bytes")
|
|
368
|
+
bw = self.parse_integer_value()
|
|
369
|
+
self.expect_char(";")
|
|
370
|
+
elif kw == "system":
|
|
371
|
+
subs_sys.append(self.parse_system())
|
|
372
|
+
elif kw == "block":
|
|
373
|
+
subs_blk.append(self.parse_block())
|
|
374
|
+
else:
|
|
375
|
+
self._error(f"system 内出现未识别的内容 {kw!r}")
|
|
376
|
+
return bw, subs_sys, subs_blk
|
|
377
|
+
|
|
378
|
+
def parse_block(self) -> BlockNode:
|
|
379
|
+
self.expect_keyword("block")
|
|
380
|
+
name = self.read_hierarchical_block_name()
|
|
381
|
+
self.skip_ws_and_comments()
|
|
382
|
+
|
|
383
|
+
if self._peek() == "@":
|
|
384
|
+
self._advance()
|
|
385
|
+
addr = self.parse_integer_value()
|
|
386
|
+
self.skip_ws_and_comments()
|
|
387
|
+
if self._peek() == ";":
|
|
388
|
+
self._advance()
|
|
389
|
+
return BlockNode(
|
|
390
|
+
name=name,
|
|
391
|
+
base_address=addr,
|
|
392
|
+
has_body=False,
|
|
393
|
+
registers=[],
|
|
394
|
+
blocks=[],
|
|
395
|
+
)
|
|
396
|
+
if self._peek() == "{":
|
|
397
|
+
self._advance()
|
|
398
|
+
bw, regs, subs = self._parse_block_body()
|
|
399
|
+
self.expect_char("}")
|
|
400
|
+
return BlockNode(
|
|
401
|
+
name=name,
|
|
402
|
+
base_address=addr,
|
|
403
|
+
has_body=True,
|
|
404
|
+
bytes_width=bw,
|
|
405
|
+
registers=regs,
|
|
406
|
+
blocks=subs,
|
|
407
|
+
)
|
|
408
|
+
self._error("block @地址 之后应为 ; 或 {")
|
|
281
409
|
|
|
282
410
|
if self._peek() == "=":
|
|
283
411
|
self._advance()
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
ralf_model/__init__.py,sha256=k6kVBQxMcUFcdON7X3lVa76vVZrNQ0d0czOIC63sB7k,999
|
|
2
|
-
ralf_model/abc.py,sha256=CjfkbS3dy05uL8vWZzAGQdwMI7CNH3JPeFMdauAa1qI,518
|
|
3
|
-
ralf_model/emit.py,sha256=0IOuH3gZIvJQv7Qgvv6G5iZCX_K6oe9gix-UbktnKGo,2789
|
|
4
|
-
ralf_model/errors.py,sha256=jhceRWdSfSSG34Il4H8zOjdL6l2KtPkdxSg07LZuLww,922
|
|
5
|
-
ralf_model/io.py,sha256=sQ0riTvRk2btxuU9mVnDg0k_ZtcF8OCiGgPefDnR_Zs,2173
|
|
6
|
-
ralf_model/nodes.py,sha256=SwlUtgiyfLgnEVJzh5iQvzy8-nTHgQ5WWgkx1NgD4n8,2710
|
|
7
|
-
ralf_model/parse.py,sha256=PWPClyivq5a2Or9oohUvqxeToUPfH00Sqrvki7wFsQU,19855
|
|
8
|
-
ralf_model/source_expand.py,sha256=ufHTAU740zMuhmJb2fduK1yT8aUFbVhO3uBxRnlidK8,5228
|
|
9
|
-
python_library_ralf_model-0.1.2.dist-info/METADATA,sha256=W_kHqHe0z0NmPX8hC_m27rsH6Fo8YlFHmYKWuKsXFks,2316
|
|
10
|
-
python_library_ralf_model-0.1.2.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
11
|
-
python_library_ralf_model-0.1.2.dist-info/RECORD,,
|
{python_library_ralf_model-0.1.2.dist-info → python_library_ralf_model-0.1.3.dist-info}/WHEEL
RENAMED
|
File without changes
|