#! /bin/env tclsh
package require {ycl context}
namespace import [yclprefix]::context::context
package require {ycl ns}
variable ns [yclprefix]::ns
proc parser {} {
set res [context]
$res var FAIL 0
$res var ACCEPT 1
$res method [namespace current]::parse
return $res
}
proc parse {self words_ newstates_} {
variable ns
upvar $words_ words
upvar $newstates_ newstates
foreach newstate $newstates {
set normalized [lindex $newstate 0]
set normalized [uplevel [list $ns normalize $normalized] {
[namespace current]}]
lappend states [lreplace $newstate 0 0 $normalized]
}
set i -1
foreach word $words {
incr i
if {![llength $states]} {
return $i
}
set nextstates [list]
set accept_total 0
foreach state $states {
set status [{*}$state $word]
dict update status match accepted states newstates {}
incr accept_total $accepted
foreach newstate $newstates {
#each state should only appear once in the list
if {$newstate ni $nextstates} {
lappend nextstates $newstate
}
}
}
if {$accept_total} {
set states $nextstates
} else {
return $i
}
}
#invoke remainig states with no "val" argument
foreach state $states {
{*}$state
}
}