You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

132 lines
2.6 KiB

# -*- tcl -*-
# ### ### ### ######### ######### #########
## Terminal packages - string -> action mappings
## (bind objects). For use with 'receive listen'.
## In essence a DFA with tree structure.
# ### ### ### ######### ######### #########
## Requirements
package require snit
package require term::receive
namespace eval ::term::receive::bind {}
# ### ### ### ######### ######### #########
snit::type ::term::receive::bind {
constructor {{dict {}}} {
foreach {str cmd} $dict {Register $str $cmd}
return
}
method map {str cmd} {
Register $str $cmd
return
}
method default {cmd} {
set default $cmd
return
}
# ### ### ### ######### ######### #########
##
method listen {{chan stdin}} {
#parray dfa
::term::receive::listen $self $chan
return
}
method unlisten {{chan stdin}} {
::term::receive::unlisten $chan
return
}
# ### ### ### ######### ######### #########
##
variable default {}
variable state {}
method reset {} {
set state {}
return
}
method next {c} {Next $c ; return}
method process {str} {
foreach c [split $str {}] {Next $c}
return
}
method eof {} {Eof ; return}
proc Next {c} {
upvar 1 dfa dfa state state default default
set key [list $state $c]
#puts -nonewline stderr "('$state' x '$c')"
if {![info exists dfa($key)]} {
# Unknown sequence. Reset. Restart.
# Run it through the default action.
if {$default ne ""} {
uplevel #0 [linsert $default end $state$c]
}
#puts stderr =\ RESET
set state {}
} else {
foreach {what detail} $dfa($key) break
#puts -nonewline stderr "= $what '$detail'"
if {$what eq "t"} {
# Incomplete sequence. Next state.
set state $detail
#puts stderr " goto ('$state')"
} elseif {$what eq "a"} {
# Action, then reset.
set state {}
#puts stderr " run ($detail)"
uplevel #0 [linsert $detail end $state$c]
} else {
return -code error \
"Internal error. Bad DFA."
}
}
return
}
proc Eof {} {}
# ### ### ### ######### ######### #########
##
proc Register {str cmd} {
upvar 1 dfa dfa
set prefix {}
set last {{} {}}
foreach c [split $str {}] {
set key [list $prefix $c]
set next $prefix$c
set dfa($key) [list t $next]
set last $key
set prefix $next
}
set dfa($last) [list a $cmd]
}
variable dfa -array {}
##
# ### ### ### ######### ######### #########
}
# ### ### ### ######### ######### #########
## Ready
package provide term::receive::bind 0.1
##
# ### ### ### ######### ######### #########