diff --git a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelTask.cs b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelTask.cs index 8b613e16..d6a25f35 100644 --- a/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelTask.cs +++ b/StgSharp.Mathematics/Numeric/Runtime/MatrixParallelTask.cs @@ -54,7 +54,7 @@ namespace StgSharp.Mathematics.Numeric.Runtime /// /// Being offset of first kernel in a L4 cache line. /// - [FieldOffset(24)] public int CacheIndex; + [FieldOffset(24)] public nuint CacheIndex; /// /// Count of kernels to be calculated in a L4 cache line. /// diff --git a/StgSharp.RegularAnalysis/NGRA_pattern_file.md b/StgSharp.RegularAnalysis/NGRA_pattern_file.md new file mode 100644 index 00000000..7f658f0d --- /dev/null +++ b/StgSharp.RegularAnalysis/NGRA_pattern_file.md @@ -0,0 +1,1110 @@ +# NGRA `.ngra` 描述文件设计草案 + +## 1. 定位 + +**NGRA**,即 **Nitload Generalized Regulation Analysis**,是一个广义序列分析器框架。 +其实现位于StgSharp.RegularAnalysis项目/命名空间下 + +NGRA 的目标不是只处理字符串正则,而是处理任意“可分类线性序列”,例如: + +- 字符串; +- 字节流; +- 比特流; +- token 序列; +- AST 子节点序列; +- 游戏事件流; +- 玩家行为流; +- 二进制协议流。 + +`.ngra` 文件是 NGRA 接收的描述文件,用于描述如何从输入流中提取目标序列元素,以及如何通过规则递归地识别、分组、压缩出更高层的岛屿结构。 + +NGRA 读取 `.ngra` 文件后,会进行解析器/分析器的源生成。使用者需要根据场景补充必要的序列元素定义、分类逻辑以及树构造方法。 + +--- + +## 2. 基本设计原则 + +`.ngra` 文件应当保持声明式,主要负责描述: + +1. 输入是什么; +2. 分析的目标元素是什么; +3. 规则如何从输入中提取目标元素; +4. 规则之间如何调用、组合、分层; +5. 分析器运行模式是什么。 + +`.ngra` 文件不应当承担过多语义任务,例如: + +- 类型推导; +- 作用域解析; +- 复杂数据流分析; +- IL 生成; +- 任意 C# 代码嵌入; +- 复杂 tree builder 逻辑。 + +这些应当交给 NGRA 生成器外部的使用者代码完成。 + +--- + +## 3. `.ngra` 文件结构 + +一个 `.ngra` 文件由两部分组成: + +1. 文件头部指令; +2. NGRAP 表达式集合。 + +示例: + +```ngra +#input string +#element token +#import std_text.ngra +#run scanning + +Identifier := Regex(/[ \t]*(?[A-Za-z_][A-Za-z0-9_]*)/, id); +Number := Regex(/[ \t]*(?[0-9]+)/, num); +NewLine := Regex/(?\r\n|\n|\r/, nl); + +IfExpression := + + + (?: ) + + (?: ) +; +``` + +--- + +## 4. 文件头部指令 + +### 4.1 `#input` + +声明输入流类型。 + +```ngra +#input string +#input byte +#input bit +#input token +#input event +#input custom +``` + +含义: + +| 指令 | 含义 | +| --- | --- | +| `#input string` | 输入为字符串/文本流 | +| `#input byte` | 输入为字节流 | +| `#input bit` | 输入为比特流 | +| `#input token` | 输入为已有 token 序列 | +| `#input event` | 输入为事件流 | +| `#input custom` | 输入为用户自定义序列 | + +`#input` 会影响哪些内联函数可用。 + +例如: + +- `#input string` 下可用 `Regex(...)`、`Char(...)`; +- `#input byte` 下可用 `Byte(...)`; +- `#input bit` 下可用 `Bit(...)`; +- `#input token` / `#input event` 通常不使用原始提取函数,而直接使用 `<...>` 规则匹配。 + +--- + +### 4.2 `#element` + +声明规则左值对应的目标元素类型。 + +```ngra +#element token +#element syntax +#element event +#element custom +``` + +示例: + +```ngra +#input string +#element token +``` + +表示: + +- 输入是字符串; +- `.ngra` 规则主要生成和处理 token 类型的目标元素。 + +又如: + +```ngra +#input event +#element event +``` + +表示: + +- 输入是事件流; +- 规则处理的基本单元就是事件元素。 + +`#element` 可对应具体宿主语言类型,例如 C# 中的: + +```csharp +SyntaxNode +PlayerEvent +TerrainUnit +``` + +具体映射方式由 NGRA 源生成器配置或用户代码提供。 + +--- + +### 4.3 `#import` + +导入其他 `.ngra` 文件作为当前上下文。 + +```ngra +#import std_text.ngra +#import std_binary.ngra +#import magicspinner_common.ngra +``` + +被导入文件可以提供: + +- 通用 token 定义; +- 通用规则; +- 公共正则片段; +- 标准库式规则; +- 共享的序列描述。 + +建议规则: + +1. 重复 import 忽略; +2. import 循环需要检测; +3. 同名符号默认报错; +4. 后续可以考虑 namespace 或显式覆盖机制。 + +--- + +### 4.4 `#run` + +声明分析器运行模式。 + +```ngra +#run scanning +#run stepping +``` + +#### `scanning` + +一次性扫描模式。 + +```ngra +#run scanning +``` + +含义: + +> 分析器读取完整输入,尽可能完成全部分析,产出最终结果,然后结束。 + +适合: + +- 编译器前端; +- 源码文件解析; +- 二进制文件解析; +- 静态日志分析; +- 一次性数据处理。 + +#### `stepping` + +增量步进模式。 + +```ngra +#run stepping +``` + +含义: + +> 分析器保持内部状态,每次接收一个或一批输入元素,执行一步或若干步分析,不自动结束。 + +适合: + +- 游戏事件流; +- 玩家行为流; +- 网络流; +- 实时日志; +- 交互式 CLI; +- MagicSpinner 运行时施法流; +- 增量编译。 + +`stepping` 模式下,分析器通常需要提供类似接口: + +```csharp +Feed(...) +Step() +Flush() +Reset() +Complete() +``` + +并支持: + +- pending match; +- partial result; +- 状态保留; +- 用户显式结束输入。 + +--- + +## 5. NGRAP 表达式 + +`.ngra` 文件主体由一组 NGRAP 表达式组成。 + +每条 NGRAP 表达式的根操作是赋值: + +```ngra +Symbol := Pattern; +``` + +其中: + +- 左值 `Symbol` 必须是单个符号; +- 左值表示一个目标元素或目标元素序列; +- 右值 `Pattern` 是得到该目标元素/序列的规则描述; +- 左值符号可以在其他右值中被调用; +- 这种调用可以递归发生; +- NGRA 通过分层调用和岛屿压缩生成分析结构。 + +示例: + +```ngra +Identifier := Regex(/[A-Za-z_][A-Za-z0-9_]*/); + +Expression := + + | + | + | +; + +IfExpression := + + + (?: ) + + (?: ) +; +``` + +--- + +## 6. 单条 NGRAP 表达式与整体 `.ngra` 的关系 + +一条 NGRAP 表达式的右值可以视为一种增强型正则表达式。 + +它支持: + +- 顺序拼接; +- 选择; +- 分组; +- 捕获; +- 计数; +- 条件; +- 局部规则调用; +- 类型化序列元素匹配。 + +但整个 `.ngra` 文件不是一条正则表达式,而是一个规则集合。 + +可以概括为: + +> 单条规则是增强型序列正则; +> 整个 `.ngra` 文件是分层序列压缩规则系统。 + +或者: + +> Rule-level regex, system-level grammar. + +--- + +## 7. 调用算符 `<...>` + +### 7.1 普通规则调用 + +```ngra + + + +``` + +表示调用已有规则或匹配已有目标元素类型。 + +例如: + +```ngra +Expression := + + | + | +; +``` + +### 7.2 带值匹配简写 + +```ngra + + + +``` + +表示匹配某个类型并要求其 `value` 属性满足给定字面量。 + +这是一种常用简写,等价于: + +```ngra +{value="if"} +{value="("} +{value="{"} +``` + +例如: + +```ngra +IfExpression := + + + + + +; +``` + +### 7.3 带属性约束匹配 + +```ngra +{kind=Identifier} +{value="if"} +{value < 500} +{type="Damage" && amount > 50} +``` + +表示先调用某个目标元素或规则,再对该元素属性施加约束。 + +约束写在 `{...}` 中,约定如下: + +- 元素属性使用裸属性名,例如 `value`、`kind`、`type`; +- NGRA 匹配上下文仍保留 `@count`、`@size` 这类 `@...` 名称; +- `` 继续保留,作为 `{value="..."}` 的简写。 + +--- + +## 8. 匿名局部正则调用 `` + +为了避免过度声明语法胶水,可以使用: + +```ngra + + + + + + + + +``` + +`` 表示: + +> 使用局部正则进行拼接匹配,但该片段默认 discard,不作为后续语义分析中的显式目标元素。 + +在当前输入类型支持正则的前提下,`` 内允许书写任何可用的正则表达式,而不只限字面量。 +由于其匹配结果默认 discard,因此不提供类似 `Regex(expr, group)` 的局部取组语义。 + +示例: + +```ngra +IfExpression := + + + (?: ) + + (?: ) +; +``` + +`` 适合表示: + +- 关键字和字面量胶水; +- 括号; +- 逗号; +- 分号; +- 冒号; +- 局部正则片段; +- 其他纯语法胶水。 + +它应当参与 source span 与 diagnostics,但默认不成为 AST 子节点。 + +--- + +## 9. 捕获组 + +建议使用接近 PCRE / .NET Regex 的命名捕获形式: + +```ngra +(?: pattern) +``` + +示例: + +```ngra +IfExpression := + + + (?: ) + + (?: ) + ( (?: ))? +; +``` + +捕获引用使用 `$name`: + +```ngra +LengthPrefixed := + (?: ) + {=$len.value} +; +``` + +命名空间建议: + +| 类型 | 示例 | +| --- | --- | +| 捕获定义 | `(?: pattern)` | +| 捕获引用 | `$name` | +| NGRA 元属性 | `@count`, `@size`, `@line`, `@column` | +| 元素属性 | `value`, `kind`, `type` | + +不建议使用 `@name:` 作为捕获语法,以免和 `@count` 等元属性混淆。 + +--- + +## 10. 内联函数 + +`.ngra` 内联函数应保持克制,主要分为两类: + +1. 输入提取函数; +2. 规则定义辅助函数。 + +目前建议首发保留少量输入提取函数和少量正则组合函数。 + +--- + +### 10.1 `Regex(expr)` + +从字符串输入中提取匹配正则的目标元素。 + +```ngra +Identifier := Regex(/[A-Za-z_][A-Za-z0-9_]*/); +Number := Regex(/[0-9]+/); +``` + +要求: + +- 输入必须是字符串或兼容文本流; +- 匹配应当锚定在当前位置; +- 匹配失败不消费输入。 + +--- + +### 10.2 `Regex(expr, group)` + +从字符串输入中匹配完整正则,但只把指定捕获组赋值给左值。 + +```ngra +Identifier := Regex(/[ \t]*(?[A-Za-z_][A-Za-z0-9_]*)/, id); +``` + +语义: + +1. 整个 `expr` 负责匹配和消费输入; +2. 只有 `group` 指定的捕获组用于生成左值元素; +3. group 外的内容不进入主序列; +4. group 外内容可以视实现保留为 trivia/span 信息; +5. 匹配必须从当前位置开始。 + +这使得 `.ngra` 可以局部决定哪些空白有用、哪些空白只是分隔符。 + +例如: + +```ngra +Identifier := Regex(/[ \t]*(?[A-Za-z_][A-Za-z0-9_]*)/, id); +NewLine := Regex/(?\r\n|\n|\r/, nl); +IndentRaw := Regex/(?m)^(?[ \t]+)/, indent); +``` + +这样普通水平空白可以被 identifier 消费掉,但换行和行首缩进仍然可以作为有意义元素保留。 + +这对于 Python、YAML、Makefile、Markdown 等空白敏感语言很重要。 + +--- + +### 10.3 `Byte(int)` + +从字节流中读取指定数量的字节。 + +```ngra +Magic := Byte(4); +Height := Byte(2); +``` + +要求: + +```ngra +#input byte +``` + +或兼容字节流输入。 + +--- + +### 10.4 `Bit(int)` + +从比特流中读取指定数量的比特。 + +```ngra +Flag := Bit(1); +Mode := Bit(3); +``` + +要求: + +```ngra +#input bit +``` + +或兼容比特流输入。 + +--- + +### 10.5 `Char(int)` + +根据字符集规则读取指定数量的字符。 + +```ngra +OneChar := Char(1); +FourChars := Char(4); +``` + +要求: + +```ngra +#input string +``` + +或兼容文本输入。 + +注意: + +- 需要明确字符单位; +- 在 C# 中 `char` 是 UTF-16 code unit; +- 后续可以考虑是否需要 `Rune(int)` 表示 Unicode scalar value。 + +--- + +### 10.6 `Append(expr1, expr2, ...)` + +按顺序拼接多个正则片段,等价于正则级串接。 + +```ngra +Identifier := Regex( + Append(/[ \t]*/, /(?[A-Za-z_][A-Za-z0-9_]*)/), + id +); +``` + +适合把较长的正则拆成多个可读片段,而不是把所有内容压在一个表达式里。 + +--- + +### 10.7 `Cases(expr1, expr2, ...)` + +在多个正则片段之间做分支选择,等价于正则级 `|`。 + +```ngra +NewLine := Regex(Cases(/\r\n/, /\n/, /\r/)); +``` + +适合把若干候选形式显式列出,避免在单个正则中写过长的分支链。 + +--- + +### 10.8 `Count(expr, count)` / `Count(expr, min, max)` + +对正则片段施加重复次数约束,等价于正则级 `{n}` 或 `{min,max}`。 + +```ngra +HexByte := Regex(Count(/[0-9A-Fa-f]/, 2)); +Indent := Regex(Count(/[ \t]/, 1, 4)); +``` + +这些函数用于构造传给 `Regex(...)` 的正则表达式本身,不引入宿主语言动作语义。 + +--- + +## 11. 空白处理策略 + +不建议默认引入类似: + +```ngra +Whitespace := Regex(/\s+/) -> skip; +``` + +因为: + +1. `-> skip` 类似 lexer action,会污染纯声明式设计; +2. 全局丢弃空白过于粗暴; +3. 无法很好支持缩进敏感语言; +4. 容易导致后续扩展成任意动作系统。 + +推荐使用: + +```ngra +Regex(expr, group) +``` + +通过 group 外部内容控制哪些输入被消费但不产出。 + +例如: + +```ngra +Identifier := Regex(/[ \t]*(?[A-Za-z_][A-Za-z0-9_]*)/, id); +Number := Regex(/[ \t]*(?[0-9]+)/, num); +``` + +这表示: + +- 水平空白被消费; +- 只有 `id` / `num` 捕获组成为 token; +- 换行可以单独声明为有意义 token。 + +如果后续确实需要全局忽略机制,可以另行考虑: + +```ngra +#ignore Whitespace +#trivia Comment +``` + +但这不应作为首要机制。 + +--- + +## 12. 条件表达式与属性谓词 + +`<...>` 调用算符后的 `{...}` 应支持简单条件表达式。 + +示例: + +```ngra +Plain := {value < 500}+; +``` + +表示匹配连续的高度小于 500 的 `Height` 元素。 + +可以支持: + +```ngra +{kind=Identifier} +{value="if"} +{value < 500} +{type="Damage" && amount > 50} +``` + +建议支持的小型表达式能力: + +- 字面量; +- 属性访问; +- 比较; +- 布尔运算; +- 简单算术; +- 捕获引用; +- 有限纯函数。 + +不建议支持任意内嵌 C#。 + +复杂逻辑应通过用户注册命名谓词或后续 semantic pass 实现。 + +--- + +## 13. 基本属性 + +NGRA 应内建一组 match context 基本属性。 + +### 13.1 `@count` + +当前匹配片段中的序列元素数量。 + +```ngra +Plain := + {value < 500}+ + where @count >= 8; +``` + +### 13.2 `@size` + +当前匹配片段覆盖的字节长度。 + +```ngra +Packet := +
+ + where @size <= 4096; +``` + +如果当前输入不提供 byte span,则该属性不可用或需要由用户序列适配器提供。 + +### 13.3 `@line` + +当前匹配起始位置所在行。 + +```ngra +TopLevelOnly := + + where @line == 1; +``` + +如果设置为换行符无关序列,则 `@line` 可恒定为 `1`。 + +### 13.4 `@column` + +当前匹配起始位置相对于行首的偏移量。 + +```ngra +Indented := + + where @column > 1; +``` + +对于无行列概念的输入,可以不可用,或由输入适配器定义。 + +建议: + +- `@...` 命名空间保留给 NGRA match context; +- 用户元素属性使用裸属性名,并写在 `<...>{...}` 内; +- 捕获变量使用 `$name`。 + +--- + +## 14. 岛屿语法与分层压缩 + +NGRA 的核心机制之一是: + +> 规则匹配成功后,可以将匹配到的序列片段压缩成左值类型的岛屿元素,供更高层规则继续分析。 + +例如: + +```ngra +IfExpression := + + + (?: ) + + (?: ) +; +``` + +匹配成功后,可以生成: + +```text + +``` + +上层规则不必再关心其内部 token 细节。 + +这使得 NGRA 可以形成分层分析: + +```text +raw string + -> token sequence + -> expression islands + -> statement islands + -> block/function/module islands + -> AST / domain nodes +``` + +岛屿语法的优势: + +1. 局部错误不影响全局; +2. 适合增量编译; +3. 同层岛屿可并行分析; +4. 支持先壳后体; +5. 有助于解决声明顺序问题; +6. 可以用于代码、二进制流、事件流等多种序列。 + +--- + +## 15. 递归调用与预压缩 + +`.ngra` 规则允许递归调用。 + +示例: + +```ngra +Expression := + + | + | +; + +IfExpression := + + + (?: ) + + (?: ) +; +``` + +但为了避免卡死在递归识别中,NGRA 在编译 `.ngra` 文件时应当进行规则图分析。 + +需要检测: + +- 递归调用; +- 左递归; +- 空匹配递归; +- 强连通规则组; +- 是否存在明确边界; +- 是否需要预压缩; +- 是否可以并行分析。 + +核心策略: + +> 对被调用序列预先进行边界识别和压缩,使上层规则不必纠结内部细节。 + +例如: + +```ngra +Block := ... ; +``` + +可以先识别 `{ ... }` 的边界并生成 `Block` island,再进入内部解析 statements。 + +--- + +## 16. Tree Builder 与用户代码 + +NGRA 可以提供默认树节点类型,例如: + +```csharp +NgraNode +NgraToken +NgraMatch +NgraSpan +``` + +但实际使用中,用户通常需要根据领域定义自己的节点。 + +例如 MagicSpinner 可能需要: + +```csharp +MagicSpinnerToken +MagicSpinnerSyntaxNode +SpellDeclarationNode +IfExpressionNode +VisionTagNode +``` + +因此 `.ngra` 文件只描述匹配和捕获,不应强行规定所有 AST 构造细节。 + +可选设计: + +```ngra +IfExpression := + + + (?: ) + + (?: ) +; +``` + +生成器产生匹配结果后,调用用户 tree builder: + +```csharp +BuildIfExpression(NgraMatch match) +``` + +如果用户不提供 builder,则使用默认 generic node: + +```text +GenericNode { + Type = "IfExpression", + Captures = { + condition, + then + }, + Span = ... +} +``` + +--- + +## 17. 与 ANTLR 的关系 + +ANTLR 的强项是: + +- 单个 `.g4` 文件即可定义 lexer/parser; +- 工具链成熟; +- 生成 visitor/listener; +- 非常适合传统编译器前端。 + +NGRA 不应当在 ANTLR 最强的传统 parser generator 领域硬碰硬。 + +NGRA 的核心优势应当是: + +- 输入序列泛化; +- 不局限于字符/token; +- 支持任意可分类线性序列; +- 支持岛屿压缩; +- 支持分层并行分析; +- 支持事件流、二进制流、AST 节点流; +- 规则右值使用增强型正则表达式风格; +- `scanning` / `stepping` 双运行模式。 + +可以概括为: + +> ANTLR 是传统语言前端生成器; +> NGRA 是广义序列分析器源生成框架。 + +此外,`.ngra` 文件的解释器/解析器本身应当使用 NGRA 构建。 +也就是说,NGRA 的实现路线默认采用自举:先落地最小可运行核心,再用 NGRA 描述 `.ngra` 自身语法并逐步替换过渡实现。 +这可以保证语法设计、规则执行模型和解释器实现始终保持同一种表达体系。 + +--- + +## 18. 运行模式示例 + +### 18.1 scanning 模式 + +```ngra +#input string +#element token +#run scanning + +Identifier := Regex(/[ \t]*(?[A-Za-z_][A-Za-z0-9_]*)/, id); +Number := Regex(/[ \t]*(?[0-9]+)/, num); + +Expression := + + | +; +``` + +适合一次性输入: + +```text +source.ngra input -> complete output +``` + +--- + +### 18.2 stepping 模式 + +```ngra +#input event +#element event +#run stepping + +DangerPattern := + {amount > 50} + {value < 20} + + +; +``` + +适合持续输入: + +```text +event1 -> analyzer state +event2 -> analyzer state +event3 -> partial/full match +... +``` + +分析器不会自动关闭,直到用户显式结束。 + +--- + +## 19. 当前设计小结 + +当前 `.ngra` 设计可以概括为: + +```text +.ngra file + = header directives + + NGRAP assignment expressions +``` + +头部指令: + +```ngra +#input string|byte|bit|token|event|custom_name +#element token|syntax|event|custom_name +#import other.ngra +#run scanning|stepping +``` + +规则形式: + +```ngra +Symbol := Pattern; +``` + +核心机制: + +- 左值是目标元素或目标元素序列; +- 右值是增强型序列正则; +- `Regex(expr, group)` 支持消费输入但只产出指定组; +- `<...>` 调用目标元素或规则,`` 是 `{value="..."}` 的简写; +- `<...>{...}` 对元素属性施加约束; +- `` 可直接书写完整可用正则,且默认 discard; +- `(?: pattern)` 定义捕获组; +- `$name` 引用捕获; +- `Append`、`Cases`、`Count` 用于组合正则表达式; +- `@count`、`@size`、`@line`、`@column` 提供匹配上下文; +- 规则调用可递归; +- NGRA 通过预压缩和岛屿分层避免递归卡死; +- `scanning` 用于一次性分析; +- `stepping` 用于持续事件流分析; +- `.ngra` 解释器本身采用 NGRA 自举实现; +- 树构造由默认节点或用户 tree builder 完成。 + +--- + +## 20. 后续待定问题 + +以下内容可以后续继续设计: + +1. 是否需要 `#start` 指令; +2. 是否需要 `#namespace`; +3. 是否需要 `#output`; +4. 是否需要 `#builder`; +5. 是否保留 `#ignore` / `#trivia`; +6. `` 与 `Regex(...)` 共享哪一套正则方言与 flags 语义; +7. `Regex(expr, group)` 中 group 是否支持数字组; +8. `@offset`、`@endLine`、`@endColumn` 是否内建; +9. 用户自定义内联函数的注册方式; +10. 用户自定义谓词的纯度声明; +11. stepping 模式的窗口和缓存策略; +12. import 的 namespace 与符号冲突策略; +13. 默认 GenericNode 的具体结构; +14. tree builder 的源生成接口形式; +15. 自举阶段的 core grammar 与完整 grammar 应如何分层演化。 + +--- + +## 22. 一句话定义 + +NGRA 是一个广义序列分析器源生成框架;`.ngra` 文件通过头部指令声明分析环境, +通过 `Symbol := Pattern;` 形式的 NGRAP 表达式描述 +如何从输入序列中提取、匹配、捕获、约束并压缩目标元素, +最终生成可用于源码、二进制流、事件流或任意可分类线性序列的分析器。