dacceptor.tcl

Go to the documentation of this file.
00001 /*  -*- tcl -*-*/
00002 /*  Grammar / Finite Automatons / Acceptance checker, DFA only*/
00003 
00004 /*  ### ### ### ######### ######### #########*/
00005 /*  Package description*/
00006 
00007 /*  A class whose instances take a FA and are able to check strings of*/
00008 /*  symbols for acceptance. This class is restricted to deterministic*/
00009 /*  FAs. The FA can be either a reference to some external FA container*/
00010 /*  object, or a copy of such. The latter makes the acceptor impervious*/
00011 /*  to changes in the original definition.*/
00012 
00013 /*  ### ### ### ######### ######### #########*/
00014 /*  Requisites*/
00015 
00016 package require snit        ; /*  Tcllib | OO system used*/
00017 package require struct:: ; # Tcllib =  | Extended  operations = .
00018 
00019 /*  ### ### ### ######### ######### #########*/
00020 /*  Implementation*/
00021 
00022 snit::type ::grammar::fa::dacceptor {
00023     /*  ### ### ### ######### ######### #########*/
00024     /*  Type API. */
00025 
00026     /*  ### ### ### ######### ######### #########*/
00027     /*  Instance API.*/
00028 
00029     /* constructor {fa args} {}*/
00030     /* destructor  {}*/
00031 
00032     ret  accept? (type symbolstring) {}
00033 
00034     option -any     {}
00035 
00036     /*  ### ### ### ######### ######### #########*/
00037     /*  Internal data structures.*/
00038 
00039     /*  We take the relevant information from the FA specified during*/
00040     /*  construction, i.e. start state, final states, and transition*/
00041     /*  table in form for direct indexing and keep it local. No need to*/
00042     /*  access or even the full FA. We require a deterministic one, and*/
00043     /*  will complete it, if necessary.*/
00044 
00045     variable start ; /*  Name of start state.*/
00046     variable final ; /*  Array, existence = state is final.*/
00047     variable trans ; /*  Transition array: state x symbol -> state*/
00048     variable sym   ; /*  Symbol set (as array), for checking existence.*/
00049     variable any   ; /*  Symbol to map any unknown symbol to. If not*/
00050     /*               ; # specified (eq "") then unknown symbols will  cause non-*/
00051     /*               ; # acceptance.*/
00052     variable stop  ; /*  Stop state, causing immediate non-acceptance when entered.*/
00053 
00054     /*  ### ### ### ######### ######### #########*/
00055     /*  Instance API Implementation.*/
00056 
00057     constructor {fa args} {
00058      any =  {}
00059     $self configurelist $args
00060 
00061     if {![$fa is deterministic]} {
00062         return -code error "Source FA is not deterministic"
00063     }
00064     if {($any ne "") && ![$fa symbol exists $any]} {
00065         return -code error "Chosen any symbol \"$any\" does not exist"
00066     }
00067 
00068     if {![$fa is complete]} {
00069          istmp =  1
00070          tmp =  [grammar::fa ${selfns}::fa = $fa]
00071          before =  [$tmp states]
00072         $tmp complete
00073         /*  Our sink is a stop state.*/
00074          stop =  [struct:: difference =  [$tmp states] $before]
00075     } else {
00076          istmp =  0
00077          tmp =  $fa
00078         /*  We don't know if there is a sink, so no quickstop.*/
00079          stop =  {}
00080     }
00081 
00082      start =  [lindex [$tmp startstates] 0]
00083     foreach s [$tmp finalstates]        { final = ($s) .}
00084     foreach s [ syms =  [$tmp symbols]] { sym = ($s) .}
00085 
00086     foreach s [$tmp states] {
00087         foreach sy $syms {
00088          trans = ($s,$sy) [lindex [$tmp next $s $sy] 0]
00089         }
00090     }
00091 
00092     if {$istmp} {$tmp destroy}
00093     return
00094     }
00095 
00096     /* destructor {}*/
00097 
00098     onconfigure -any {value} {
00099      options = (-any) $value
00100      any =            $value
00101     return
00102     }
00103 
00104     /*  --- --- --- --------- --------- ---------*/
00105 
00106     ret  accept? (type symbolstring) {
00107     set state $start
00108 
00109     ## puts "\n====================== ($symbolstring)"
00110 
00111     if {$any eq ""} {
00112         # No any mapping of unknown symbols.
00113 
00114         foreach sy $symbolstring {
00115         if {![info exists sym($sy)]} {
00116             # Bad symbol in input. String is not accepted,
00117             # abort immediately.
00118             ## puts " \[$state\] -- Unknown symbol ($sy)"
00119             return 0
00120         }
00121 
00122         ## puts " \[$state\] --($sy)--> "
00123 
00124         set state $trans($state,$sy)
00125         # state == "" cannot happen, as our FA is complete.
00126         if {$state eq $stop} {
00127             # This is a known sink, we can stop processing input now.
00128             ## puts " \[$state\] FULL STOP"
00129             return 0
00130         }
00131         }
00132 
00133     } else {
00134         # Mapping of unknown symbols to any.
00135 
00136         foreach sy $symbolstring {
00137         if {![info exists sym($sy)]} {set sy $any}
00138         ## puts " \[$state\] --($sy)--> "
00139         set state $trans($state,$sy)
00140         # state == "" cannot happen, as our FA is complete.
00141         if {$state eq $stop} {
00142             # This is a known sink, we can stop processing input now.
00143             ## puts " \[$state\] FULL STOP"
00144             return 0
00145         }
00146         }
00147     }
00148 
00149     ## puts " \[$state\][expr {[info exists final($state)] ? " ACCEPT" : ""}]"
00150 
00151     return [info exists final($state)]
00152     }
00153 
00154     /*  ### ### ### ######### ######### #########*/
00155     /*  Type API implementation.*/
00156 
00157     /*  ### ### ### ######### ######### #########*/
00158     /*  Type Internals.*/
00159 
00160     /*  ### ### ### ######### ######### #########*/
00161 }
00162 
00163 /*  ### ### ### ######### ######### #########*/
00164 /*  Package Management*/
00165 
00166 package provide grammar::fa::dacceptor 0.1.1
00167 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1