analysis_peg_reachable.tcl

Go to the documentation of this file.
00001 /*  -*- tcl -*-*/
00002 /*  ### ### ### ######### ######### #########*/
00003 
00004 /*  Perform reachability analysis on the PE grammar delivered by the*/
00005 /*  frontend. The grammar is in normalized form (reduced to essentials,*/
00006 /*  graph like node-x-references, expression trees).*/
00007 
00008 /*  This package assumes to be used from within a PAGE plugin. It uses*/
00009 /*  the API commands listed below. These are identical across the major*/
00010 /*  types of PAGE plugins, allowing this package to be used in reader,*/
00011 /*  transform, and writer plugins. It cannot be used in a configuration*/
00012 /*  plugin, and this makes no sense either.*/
00013 /* */
00014 /*  To ensure that our assumption is ok we require the relevant pseudo*/
00015 /*  package setup by the PAGE plugin management code.*/
00016 /* */
00017 /*  -----------------+--*/
00018 /*  page_info        | Reporting to the user.*/
00019 /*  page_warning     |*/
00020 /*  page_error       |*/
00021 /*  -----------------+--*/
00022 /*  page_log_error   | Reporting of internals.*/
00023 /*  page_log_warning |*/
00024 /*  page_log_info    |*/
00025 /*  -----------------+--*/
00026 
00027 /*  ### ### ### ######### ######### #########*/
00028 /*  Requisites*/
00029 
00030 /*  @mdgen NODEP: page::plugin*/
00031 
00032 package require page::plugin     ; /*  S.a. pseudo-package.*/
00033 package require page::util::flow ; /*  Dataflow walking.*/
00034 package require page::util::peg  ; /*  General utilities.*/
00035 
00036 namespace ::page::analysis::peg::reachable {
00037     namespace import ::page::util::peg::*
00038 }
00039 
00040 /*  ### ### ### ######### ######### #########*/
00041 /*  API*/
00042 
00043 ret  ::page::analysis::peg::reachable::compute (type t) {
00044 
00045     # Ignore call if already done before
00046     if {[$t keyexists root page::analysis::peg::reachable]} return
00047 
00048     # We compute the set of all nodes which are reachable from the
00049     # root node of the start expression. This is a simple topdown walk
00050     # where the children of all reachable nodes are mode reachable as
00051     # well, and invokations of nonterminals symbols are treated as
00052     # children as well. At the end of the flow all reachable non-
00053     # terminal symbols and their expressions are marked, and none
00054     # other.
00055 
00056     # Initialize walking state: 2 arrays, all nodes (except root) are
00057     # in or the other array, and their location tells if they are
00058     # reachable or not. In the beginning no node is reachable. The
00059     # goal array (reach) also serves as minder of which nodes have
00060     # been seen, to cut multiple visits short.
00061 
00062     array set unreach {} ; foreach n [$t nodes] {set unreach($n) .}
00063     unset     unreach(root)
00064     array set reach   {}
00065 
00066     # A node is visited if it has been determined that it is indeed
00067     # reachable.
00068 
00069     page::util::flow [list [$t get root start]] flow n {
00070     # Ignore nodes already reached.
00071     if {[info exists reach($n)]} continue
00072 
00073     # Reclassify node, has been reached now.
00074     unset unreach($n)
00075     set   reach($n) .
00076 
00077     # Schedule children for visit --> topdown flow.
00078     $flow visitl [$t children $n]
00079 
00080     # Treat n-Nodes as special, their definition as indirect
00081     # child. But ignore invokations of undefined nonterminal
00082     # symbols, or those already marked as reachable.
00083 
00084     if {![$t keyexists $n op]} continue
00085     if {[$t get $n op] ne "n"} continue
00086 
00087     set def [$t get $n def]
00088     if {$def eq ""}                continue
00089     if {[info exists reach($def)]} continue
00090     $flow visit $def
00091     }
00092 
00093     # Store results. This also serves as marker.
00094 
00095     $t set root page::analysis::peg::reachable   [array names reach]
00096     $t set root page::analysis::peg::unreachable [array names unreach]
00097     return
00098 }
00099 
00100 ret  ::page::analysis::peg::reachable::remove! (type t) {
00101 
00102     # Determine which nonterminal symbols are reachable from the root
00103     # of the start expression.
00104 
00105     compute $t
00106 
00107     # Remove all nodes which are not reachable.
00108 
00109     set unreach [$t get root page::analysis::peg::unreachable]
00110     foreach n [lsort $unreach] {
00111     if {[$t exists $n]} {
00112         $t delete $n
00113     }
00114     }
00115 
00116     # Notify the user of the definitions which were among the removed
00117     # nodes. Keep only the still-existing definitions.
00118 
00119     set res {}
00120     foreach {sym def} [$t get root definitions] {
00121     if {![$t exists $def]} {
00122         page_warning "  $sym: Unreachable nonterminal symbol, deleting"
00123     } else {
00124         lappend res $sym $def
00125     }
00126     }
00127 
00128     # Clear computation results.
00129 
00130     $t unset root page::analysis::peg::reachable
00131     $t unset root page::analysis::peg::unreachable
00132 
00133     $t set root definitions $res
00134     updateUndefinedDueRemoval $t
00135     return
00136 }
00137 
00138 ret  ::page::analysis::peg::reachable::reset (type t) {
00139     # Remove marker, allow recalculation of reachability after
00140     # changes.
00141 
00142     $t unset root page::analysis::peg::reachable
00143     $t unset root page::analysis::peg::unreachable
00144     return
00145 }
00146 
00147 /*  ### ### ### ######### ######### #########*/
00148 /*  Ready*/
00149 
00150 package provide page::analysis::peg::reachable 0.1
00151 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1