me_util.tcl

Go to the documentation of this file.
00001 /*  -*- tcl -*-*/
00002 /*  ### ### ### ######### ######### #########*/
00003 /*  Package description*/
00004 
00005 /*  Utility commands for the conversion between various representations*/
00006 /*  of abstract syntax trees.*/
00007 
00008 /*  ### ### ### ######### ######### #########*/
00009 /*  Requisites*/
00010 
00011 namespace ::grammar::me::util {
00012     namespace export ast2tree ast2etree tree2ast
00013 }
00014 
00015 /*  ### ### ### ######### ######### #########*/
00016 /*  Implementation*/
00017 
00018 /*  ### ### ### ######### ######### #########*/
00019 /*  API Implementation.*/
00020 
00021 ret  ::grammar::me::util::ast2tree (type ast , type tree , optional root ={)} {
00022     # See grammar::me_ast for the specification of both value and tree
00023     # representations.
00024 
00025     if {$root eq ""} {
00026      root =  [$tree rootname]
00027     }
00028 
00029     /*  Decompose the AST value into its components.*/
00030 
00031     if {[llength $ast] < 3} {
00032     return -code error "Bad node \"$ast\", not enough elements"
00033     }
00034 
00035      type =      [lindex $ast 0]
00036      range =     [lrange $ast 1 2]
00037      children =  [lrange $ast 3 end]
00038 
00039     if {($type eq "") && [llength $children]} {
00040     return -code error \
00041         "Terminal node \"[lrange $ast 0 2]\" has children"
00042     }
00043     foreach {s e} $range break
00044     if {
00045     ![string is integer -strict $s] || ($s < 0) ||
00046     ![string is integer -strict $e] || ($e < 0)
00047     } {
00048     return -code error "Bad range information \"$range\""
00049     }
00050 
00051     /*  Create a node for the root of the AST and fill it with the data*/
00052     /*  from the value. Afterward recurse and build the tree for the*/
00053     /*  children of the root.*/
00054 
00055      new =  [lindex [$tree insert $root end] 0]
00056 
00057     if {$type eq ""} {
00058     $tree  $new =  type terminal
00059     } else {
00060     $tree  $new =  type   nonterminal
00061     $tree  $new =  detail $type
00062     }
00063 
00064     $tree  $new =  range $range
00065 
00066     foreach child $children {
00067     ast2tree $child $tree $new
00068     }
00069     return
00070 }
00071 
00072 ret  ::grammar::me::util::ast2etree (type ast , type mcmd , type tree , optional root ={)} {
00073     # See grammar::me_ast for the specification of both value and tree
00074     # representations.
00075 
00076     if {$root eq ""} {
00077      root =  [$tree rootname]
00078     }
00079 
00080     /*  Decompose the AST value into its components.*/
00081 
00082     if {[llength $ast] < 3} {
00083     return -code error "Bad node \"$ast\", not enough elements"
00084     }
00085 
00086      type =      [lindex $ast 0]
00087      range =     [lrange $ast 1 2]
00088      children =  [lrange $ast 3 end]
00089 
00090     if {($type eq "") && [llength $children]} {
00091     return -code error \
00092         "Terminal node \"[lrange $ast 0 2]\" has children"
00093     }
00094     foreach {s e} $range break
00095     if {
00096     ![string is integer -strict $s] || ($s < 0) ||
00097     ![string is integer -strict $e] || ($e < 0)
00098     } {
00099     return -code error "Bad range information \"$range\""
00100     }
00101 
00102     /*  Create a node for the root of the AST and fill it with the data*/
00103     /*  from the value. Afterward recurse and build the tree for the*/
00104     /*  children of the root.*/
00105 
00106      new =  [lindex [$tree insert $root end] 0]
00107 
00108     if {$type eq ""} {
00109          cmd =  $mcmd
00110     lappend cmd tok
00111     foreach loc $range {lappend cmd $loc}
00112 
00113     $tree  $new =  type   terminal
00114     $tree  $new =  detail [uplevel \/* 0 $cmd]*/
00115     } else {
00116     $tree  $new =  type   nonterminal
00117     $tree  $new =  detail $type
00118     }
00119 
00120      range = _lc {}
00121     foreach loc $range {
00122     lappend range_lc [uplevel \/* 0 \*/
00123         [linsert $mcmd end lc $loc]]
00124     }
00125 
00126     $tree  $new =  range    $range
00127     $tree  $new =  range_lc $range_lc
00128 
00129     foreach child $children {
00130     ast2etree $child $mcmd $tree $new
00131     }
00132     return
00133 }
00134 
00135 ret  ::grammar::me::util::tree2ast (type tree , optional root ={)} {
00136     # See grammar::me_ast for the specification of both value and tree
00137     # representations.
00138 
00139     if {$root eq ""} {
00140      root =  [$tree rootname]
00141     }
00142 
00143      value =  {}
00144 
00145     if {![$tree keyexists $root type]} {
00146     return -code error "Bad node \"$root\", type information is missing"
00147     }
00148     if {![$tree keyexists $root range]} {
00149     return -code error "Bad node \"$root\", range information is missing"
00150     }
00151 
00152      range =  [$tree get $root range]
00153     if {[llength $range] != 2} {
00154     return -code error "Bad node \"root\", bad range information \"$range\""
00155     }
00156 
00157     foreach {s e} $range break
00158     if {
00159     ![string is integer -strict $s] || ($s < 0) ||
00160     ![string is integer -strict $e] || ($e < 0)
00161     } {
00162     return -code error "Bad node \"root\", bad range information \"$range\""
00163     }
00164 
00165     if {[$tree get $root type] eq "terminal"} {
00166     lappend value {}
00167     } else {
00168     if {![$tree keyexists $root detail]} {
00169         return -code error "Bad node \"$root\", nonterminal detail is missing"
00170     }
00171 
00172     lappend value [$tree get $root detail]
00173     }
00174 
00175     /*  Range data ...*/
00176     lappend value $s $e
00177 
00178     foreach child [$tree children $root] {
00179     lappend value [tree2ast $tree $child]
00180     }
00181 
00182     return $value
00183 }
00184 
00185 /*  ### ### ### ######### ######### #########*/
00186 /*  Package Management*/
00187 
00188 package provide grammar::me::util 0.1
00189 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1