util_peg.tcl

Go to the documentation of this file.
00001 /*  -*- tcl -*-*/
00002 /*  ### ### ### ######### ######### #########*/
00003 
00004 /*  This package provides a number of utility commands to*/
00005 /*  transformations for common operations. It assumes a 'Normalized PE*/
00006 /*  Grammar Tree' as input, possibly augmented with attributes coming*/
00007 /*  from transformation not in conflict with the base definition.*/
00008 
00009 /*  ### ### ### ######### ######### #########*/
00010 /*  Requisites*/
00011 
00012 package require page::util::quote
00013 
00014 namespace ::page::util::peg {
00015     namespace export \
00016         symbolOf symbolNodeOf \
00017         updateUndefinedDueRemoval \
00018         flatten peOf printTclExpr \
00019         getWarnings printWarnings
00020 
00021     /*  Get the peg char de/encoder commands.*/
00022     /*  (unquote, quote'tcl).*/
00023 
00024     namespace import ::page::util::quote::*
00025 }
00026 
00027 /*  ### ### ### ######### ######### #########*/
00028 /*  API*/
00029 
00030 ret  ::page::util::peg::symbolNodeOf (type t , type n) {
00031     # Given an arbitrary root it determines the node (itself or an
00032     # ancestor) containing the name of the nonterminal symbol the node
00033     # belongs to, and returns its id. The result is either the root of
00034     # the tree (for the start expression), or a definition mode.
00035 
00036     while {![$t keyexists $n symbol]} {
00037     set n [$t parent $n]
00038     }
00039     return $n
00040 }
00041 
00042 ret  ::page::util::peg::symbolOf (type t , type n) {
00043     # As above, but returns the symbol name.
00044 
00045     return [$t get [symbolNodeOf $t $n] symbol]
00046 }
00047 
00048 ret  ::page::util::peg::updateUndefinedDueRemoval (type t) {
00049     # The removal of nodes may have caused symbols to lose one or more
00050     # users. Example: A used by B and C, B is reachable, C is not, so A
00051     # now loses a node in the expression for C calling it, or rather
00052     # not anymore.
00053 
00054     foreach {sym def} [$t get root definitions] {
00055     set res {}
00056     foreach u [$t get $def users] {
00057         if {![$t exists $u]} continue
00058         lappend res $u
00059     }
00060     $t set $def users $res
00061     }
00062 
00063     # Update the knowledge of undefined nonterminals. To be used when
00064     # a transformation can remove invokations of undefined symbols,
00065     # and is not able to generate such invokations.
00066 
00067     set res {}
00068     foreach {sym invokers} [$t get root undefined] {
00069     set sres {}
00070     foreach n $invokers {
00071         if {![$t exists $n]} continue
00072         lappend sres $n
00073     }
00074     if {[llength $sres]} {
00075         lappend res $sym $sres
00076     }
00077     }
00078     $t set root undefined $res
00079     return
00080 }
00081 
00082 ret  ::page::util::peg::flatten (type q , type t) {
00083     # Flatten nested x-, or /-operators.
00084     # See peg_normalize.tcl, peg::normalize::ExprFlatten
00085 
00086     foreach op {x /} {
00087     # Locate all x operators, whose parents are x oerators as
00088     # well, then go back to the child operators and cut them out.
00089 
00090     $q query \
00091         tree          withatt op $op \
00092         parent unique withatt op $op \
00093         children      withatt op $op \
00094         over n {
00095         $t cut $n
00096     }
00097     }
00098     return
00099 }
00100 
00101 ret  ::page::util::peg::getWarnings (type t) {
00102     # Look at the attributes for problems with the grammar and issue
00103     # warnings. They do not prevent us from writing the grammar, but
00104     # still represent problems with it the user should be made aware
00105     # of.
00106 
00107     array set msg {}
00108     array set undefined [$t get root undefined]
00109     foreach sym [array names undefined] {
00110     set msg($sym) {}
00111     foreach ref $undefined($sym) {
00112         lappend msg($sym) "Undefined symbol used by the definition of '[symbolOf $t $ref]'."
00113     }
00114     }
00115 
00116     foreach {sym def} [$t get root definitions] {
00117     if {[llength [$t get $def users]] == 0} {
00118         set msg($sym) [list "This symbol has been defined, but is not used."]
00119     }
00120     }
00121 
00122     return [array get msg]
00123 }
00124 
00125 ret  ::page::util::peg::printWarnings (type msg) {
00126     if {![llength $msg]} return
00127 
00128     set dict {}
00129     set max -1
00130     foreach {k v} $msg {
00131     set l [string length [list $k]]
00132     if {$l > $max} {set max $l}
00133     lappend dict [list $k $v $l]
00134     }
00135 
00136     foreach e [lsort -dict -index 0 $dict] {
00137     foreach {k msgs l} $e break
00138 
00139     set off [string repeat " " [expr {$max - $l}]]
00140     page_info "[list $k]$off : [lindex $msgs 0]"
00141 
00142     if {[llength $msgs] > 1} {
00143         set indent [string repeat " " [string length [list $k]]]
00144         foreach m [lrange $msgs 1 end] {
00145         puts stderr "  $indent$off : $m"
00146         }
00147     }
00148     }
00149     return
00150 }
00151 
00152 ret  ::page::util::peg::peOf (type t , type eroot) {
00153     set op [$t get $eroot op]
00154     set pe [list $op]
00155 
00156     set ch [$t children $eroot]
00157 
00158     if {[llength $ch]} {
00159     foreach c $ch {
00160         lappend pe [peOf $t $c]
00161     }
00162     } elseif {$op eq "n"} {
00163     lappend pe [$t get $eroot sym]
00164     } elseif {$op eq "t"} {
00165     lappend pe [unquote [$t get $eroot char]]
00166     } elseif {$op eq ".."} {
00167     lappend pe \
00168         [unquote [$t get $eroot begin]] \
00169         [unquote [$t get $eroot end]]
00170 
00171     }
00172     return $pe
00173 }
00174 
00175 ret  ::page::util::peg::printTclExpr (type pe) {
00176     list [PrintExprSub $pe]
00177 }
00178 
00179 /*  ### ### ### ######### ######### #########*/
00180 /*  Internal*/
00181 
00182 ret  ::page::util::peg::PrintExprSub (type pe) {
00183     set op   [lindex $pe 0]
00184     set args [lrange $pe 1 end]
00185 
00186     #puts stderr "PE [llength $args] $op | $args"
00187 
00188     if {$op eq "t"} {
00189     set a [lindex $args 0]
00190     return "$op [quote'tcl $a]"
00191     } elseif {$op eq ".."} {
00192     set a [lindex $args 0]
00193     set b [lindex $args 1]
00194     return "$op [quote'tcl $a] [quote'tcl $b]"
00195     } elseif {$op eq "n"} {
00196     return $pe
00197     } else {
00198     set res $op
00199     foreach a $args {
00200         lappend res [PrintExprSub $a]
00201     }
00202     return $res
00203     }
00204 }
00205 
00206 /*  ### ### ### ######### ######### #########*/
00207 /*  Ready*/
00208 
00209 package provide page::util::peg 0.1
00210 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1