SQL & Regex(2): thompson construction



-- Thompson Construction : convert Regular Expression Parse Tree to NFA
-- require: parse_node table is filled with tree-struct data

-- ========================================================================
exec clearobj 'NFA_trans_table', 1
go
create table NFA_trans_table(nid int, from_state int, to_state int, input char default ''
    constraint PK_NFA primary key(nid, from_state, to_state))
go
-- ========================================================================
exec clearobj 'NFA_property', 1
go
create table NFA_property(nid int primary key, initial int, final int, nsize int)
go
-- ========================================================================
exec clearobj 'NFA_get_prop', 1
go
create function NFA_get_prop(@id int, @prop_name nvarchar(100))
    returns int
with encryption
as
begin
    return case @prop_name
        when 'initial' then (select initial from NFA_property where nid = @id)
        when 'final' then (select final from NFA_property where nid = @id)
        else (select nsize from NFA_property where nid = @id)
        end
end
go
-- ========================================================================
exec clearobj 'NFA_set_prop', 1
go
create proc NFA_set_prop(@id int, @prop_name nvarchar(100), @prop_value int)
with encryption
as
begin
    if @prop_name = 'initial'
        update NFA_property set initial = @prop_value
    else if @prop_name = 'final'
        update NFA_property set final = @prop_value
    else
        update NFA_property set nsize = @prop_value
end
go
-- ========================================================================
exec clearobj 'NFA_copy', 1
go
create proc NFA_copy
    @new_id int, @old_id int
with encryption
as
    insert NFA_property select @new_id, initial, final, nsize from NFA_property where nid = @old_id
    insert NFA_trans_table select @new_id, from_state, to_state, input from NFA_trans_table where nid = @old_id
go
-- ========================================================================
exec clearobj 'NFA_fill', 1
go
create proc NFA_fill
    @new_id int, @old_id int
with encryption
as
    insert into NFA_trans_table select @new_id, from_state, to_state, input from NFA_trans_table where nid = @old_id
go
-- ========================================================================
exec clearobj 'NFA_shift_right', 1
go
create proc NFA_shift_right
    @id int, @shift int
with encryption
as
    update NFA_property set initial = initial + @shift, final = final + @shift, nsize = nsize + @shift where nid = @id
    update NFA_trans_table set from_state = from_state + @shift, to_state = to_state + @shift where nid = @id
go
-- ========================================================================
exec clearobj 'build_nfa_basic', 1
go
create proc build_nfa_basic
    @id int, @input char
with encryption
as
    insert NFA_property select @id, 0, 1, 2
    insert NFA_trans_table select @id, 0, 1, @input
go
-- ========================================================================
exec clearobj 'build_nfa_alter', 1
go
create proc build_nfa_alter
    @id int, @nfa1 int, @nfa2 int
with encryption
as
    declare @initial1 int, @initial2 int, @final1 int, @final2 int, @size1 int, @size2 int
    exec NFA_shift_right @nfa1, 1
    select @size1 = dbo.NFA_get_prop(@nfa1, 'nsize')
    exec NFA_shift_right @nfa2, @size1
    select @initial1 = initial, @final1 = final, @size1 = nsize from NFA_property where nid = @nfa1
    select @initial2 = initial, @final2 = final, @size2 = nsize from NFA_property where nid = @nfa2
    exec NFA_copy @id, @nfa2
    exec NFA_fill @id, @nfa1
    insert into NFA_trans_table select @id, 0, @initial1, '#'
    insert into NFA_trans_table select @id, 0, @initial2, '#'
    update NFA_property set initial = 0 where nid = @id
    update NFA_property set nsize = nsize + 1 where nid = @id
    update NFA_property set final  = nsize - 1 where nid = @id
    insert into NFA_trans_table select @id, @final1, dbo.NFA_get_prop(@id, 'final'), '#'
    insert into NFA_trans_table select @id, @final2, dbo.NFA_get_prop(@id, 'final'), '#'
go
-- ========================================================================
exec clearobj 'build_nfa_concat', 1
go
create proc build_nfa_concat
    @id int, @nfa1 int, @nfa2 int
with encryption
as
    declare @size int, @initial int
    select @size = dbo.NFA_get_prop(@nfa1, 'nsize')-1
    exec NFA_shift_right @nfa2, @size
    exec NFA_copy @id, @nfa2
    exec NFA_fill @id, @nfa1
    select @initial = dbo.NFA_get_prop(@nfa1, 'initial')
    exec NFA_set_prop @id, 'initial', @initial
go
-- ========================================================================
exec clearobj 'build_nfa_star', 1
go
create proc build_nfa_star
    @id int, @nfa1 int
with encryption
as
    declare @initial int, @final int, @size int, @new_final int
    exec NFA_copy @id, @nfa1
    update NFA_property set nsize = nsize + 1 where nid = @id
    select @initial = initial, @final = final, @size = nsize from NFA_property where nid = @id
    select @new_final = @size - 1
    insert NFA_trans_table select @id, @final, @initial, '#'
    insert NFA_trans_table select @id, 0, @initial, '#'
    insert NFA_trans_table select @id, @final, @new_final, '#'
    insert NFA_trans_table select @id, 0, @new_final, '#'
    exec NFA_set_prop @id, 'initial', 0
    exec NFA_set_prop @id, 'final', @new_final
go
-- ========================================================================
exec clearobj 'thompson_cobuild', 1
go
create proc thompson_cobuild
    @id int
with encryption
as
    declare @type nvarchar(100), @data char, @leftchild int, @rightchild int
    select @type = type, @data = data, @leftchild = leftchild, @rightchild = rightchild from parse_node where [id] = @id

    if @type = 'CHAR'
        exec build_nfa_basic @id, @data
    else if @type = 'ALTER'
    begin
        exec thompson_cobuild @leftchild
        exec thompson_cobuild @rightchild
        exec build_nfa_alter @id, @leftchild, @rightchild
    end
    else if @type = 'CONCAT'
    begin
        exec thompson_cobuild @leftchild
        exec thompson_cobuild @rightchild
        exec build_nfa_concat @id, @leftchild, @rightchild
    end
    else if @type = 'STAR'
    begin
        exec thompson_cobuild @leftchild
        exec build_nfa_star @id, @leftchild
    end
    else if @type = 'QUESTION'
    begin
        -- a? = (a|EPS)
        declare @eps_id int
        select @eps_id = -@leftchild
        exec thompson_cobuild @leftchild
        exec build_nfa_basic @eps_id, '#'
        exec build_nfa_alter @id, @leftchild, @eps_id
    end
    else
    begin
        select msg='invalid type'
        return
    end
--    delete from NFA_trans_table where nid <> @id
go
-- ========================================================================
-- ========================================================================
exec clearobj 'thompson_construction', 1
go
create proc thompson_construction
with encryption
as
    delete NFA_trans_table
    delete NFA_property

    declare @root int
    select @root = [id] from parse_node where isnull(pid, 0) = 0

    exec thompson_cobuild @root
    delete NFA_property where nid <> @root
    delete NFA_trans_table where nid <> @root
go
-- ========================================================================
exec thompson_construction
select * from NFA_trans_table
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值