mirror of
https://gitee.com/rulego/streamsql.git
synced 2026-07-31 08:07:01 +00:00
185 lines
4.3 KiB
Go
185 lines
4.3 KiB
Go
package cep
|
||
|
||
import (
|
||
"fmt"
|
||
|
||
"github.com/rulego/streamsql/types"
|
||
)
|
||
|
||
// Compile 把模式树编译为 NFA(Thompson 构造)。组合式节点:序列/选择/分组/PERMUTE/量词。
|
||
// PatternExclusion({- -},absence)暂不支持,返回明确错误。
|
||
func Compile(node *types.PatternNode) (*NFA, error) {
|
||
if node == nil {
|
||
return nil, fmt.Errorf("MATCH_RECOGNIZE requires a PATTERN")
|
||
}
|
||
f, err := compileNode(node)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
accept := &state{kind: stAccept}
|
||
patch(f, accept)
|
||
return &NFA{start: f.start, accept: accept}, nil
|
||
}
|
||
|
||
func compileNode(n *types.PatternNode) (*frag, error) {
|
||
switch n.Kind {
|
||
case types.PatternLiteral:
|
||
if n.Symbol == "" {
|
||
return nil, fmt.Errorf("pattern variable name is empty")
|
||
}
|
||
return newMatchFrag(n.Symbol), nil
|
||
case types.PatternSequence:
|
||
var f *frag
|
||
for _, c := range n.Children {
|
||
cf, err := compileNode(c)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if f == nil {
|
||
f = cf
|
||
} else {
|
||
f = concat(f, cf)
|
||
}
|
||
}
|
||
if f == nil {
|
||
return newEpsFrag(), nil
|
||
}
|
||
return f, nil
|
||
case types.PatternGroup:
|
||
// Group 透明:编译其内部序列。量词由外层 Repetition 处理。
|
||
if len(n.Children) == 0 {
|
||
return newEpsFrag(), nil
|
||
}
|
||
return compileNode(n.Children[0])
|
||
case types.PatternAlternation:
|
||
if len(n.Children) == 0 {
|
||
return newEpsFrag(), nil
|
||
}
|
||
var f *frag
|
||
for _, c := range n.Children {
|
||
cf, err := compileNode(c)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if f == nil {
|
||
f = cf
|
||
} else {
|
||
f = alt(f, cf)
|
||
}
|
||
}
|
||
return f, nil
|
||
case types.PatternRepetition:
|
||
if len(n.Children) == 0 || n.Quant == nil {
|
||
return nil, fmt.Errorf("repetition requires a child and quantifier")
|
||
}
|
||
return compileRepeat(n.Children[0], n.Quant)
|
||
case types.PatternPermute:
|
||
return compilePermute(n.Children)
|
||
case types.PatternExclusion:
|
||
return nil, fmt.Errorf("pattern exclusion {- -} is not supported yet (planned for a later phase)")
|
||
}
|
||
return nil, fmt.Errorf("unknown pattern node kind %d", n.Kind)
|
||
}
|
||
|
||
// compileRepeat 展开量词为显式 NFA:{n}=n 份;{n,}=n 份 + 星;{n,m}=n 份 + (m-n) 份可选;
|
||
// 每份重新编译子节点(独立状态),避免回环打结。
|
||
func compileRepeat(child *types.PatternNode, q *types.Quantifier) (*frag, error) {
|
||
if q.Min < 0 {
|
||
return nil, fmt.Errorf("quantifier min must be >= 0")
|
||
}
|
||
var f *frag
|
||
for i := 0; i < q.Min; i++ {
|
||
cf, err := compileNode(child)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if f == nil {
|
||
f = cf
|
||
} else {
|
||
f = concat(f, cf)
|
||
}
|
||
}
|
||
if q.Max < 0 {
|
||
cf, err := compileNode(child)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
star := starFrag(cf)
|
||
if f == nil {
|
||
return star, nil
|
||
}
|
||
return concat(f, star), nil
|
||
}
|
||
if q.Max < q.Min {
|
||
return nil, fmt.Errorf("quantifier max %d < min %d", q.Max, q.Min)
|
||
}
|
||
for i := 0; i < q.Max-q.Min; i++ {
|
||
cf, err := compileNode(child)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
opt := optFrag(cf)
|
||
if f == nil {
|
||
f = opt
|
||
} else {
|
||
f = concat(f, opt)
|
||
}
|
||
}
|
||
if f == nil {
|
||
return newEpsFrag(), nil // {0}:匹配空
|
||
}
|
||
return f, nil
|
||
}
|
||
|
||
// compilePermute 把 PERMUTE(A,B,...) 编译为所有排列的交替(任一顺序匹配)。
|
||
func compilePermute(children []*types.PatternNode) (*frag, error) {
|
||
if len(children) == 0 {
|
||
return newEpsFrag(), nil
|
||
}
|
||
// 排列数为 N!,符号过多会导致 NFA 状态阶乘级膨胀,设上限保护。
|
||
if len(children) > 6 {
|
||
return nil, fmt.Errorf("PERMUTE supports at most 6 symbols (got %d): factorial state blow-up", len(children))
|
||
}
|
||
var result *frag
|
||
for _, perm := range permutations(len(children)) {
|
||
// 每个排列独立状态:按索引顺序重新编译子节点。
|
||
var f *frag
|
||
for _, idx := range perm {
|
||
cf, err := compileNode(children[idx])
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if f == nil {
|
||
f = cf
|
||
} else {
|
||
f = concat(f, cf)
|
||
}
|
||
}
|
||
if result == nil {
|
||
result = f
|
||
} else {
|
||
result = alt(result, f)
|
||
}
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
// permutations 返回 [0,n) 的所有排列索引。
|
||
func permutations(n int) [][]int {
|
||
if n == 0 {
|
||
return [][]int{{}}
|
||
}
|
||
subs := permutations(n - 1)
|
||
var out [][]int
|
||
for _, s := range subs {
|
||
for i := 0; i <= len(s); i++ {
|
||
p := make([]int, 0, len(s)+1)
|
||
p = append(p, s[:i]...)
|
||
p = append(p, n-1)
|
||
p = append(p, s[i:]...)
|
||
out = append(out, p)
|
||
}
|
||
}
|
||
return out
|
||
}
|