source: tol/tolsh/tolsh.vfs/lib/tcllib1.10/page/util_peg.tcl @ 8597867d

1941-docker-image-to-testdevel
Last change on this file since 8597867d was 8597867d, checked in by Jorge Pérez <josp.jorge@…>, 16 years ago

closes #976, se incluye tcllib1.10, base64 debe eliminarse del raiz de lib ya que esta incluido en tcllib

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@2556 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 5.1 KB
Line 
1# -*- tcl -*-
2# ### ### ### ######### ######### #########
3
4## This package provides a number of utility commands to
5## transformations for common operations. It assumes a 'Normalized PE
6## Grammar Tree' as input, possibly augmented with attributes coming
7## from transformation not in conflict with the base definition.
8
9# ### ### ### ######### ######### #########
10## Requisites
11
12package require page::util::quote
13
14namespace eval ::page::util::peg {
15    namespace export \
16            symbolOf symbolNodeOf \
17            updateUndefinedDueRemoval \
18            flatten peOf printTclExpr \
19            getWarnings printWarnings
20
21    # Get the peg char de/encoder commands.
22    # (unquote, quote'tcl).
23
24    namespace import ::page::util::quote::*
25}
26
27# ### ### ### ######### ######### #########
28## API
29
30proc ::page::util::peg::symbolNodeOf {t n} {
31    # Given an arbitrary root it determines the node (itself or an
32    # ancestor) containing the name of the nonterminal symbol the node
33    # belongs to, and returns its id. The result is either the root of
34    # the tree (for the start expression), or a definition mode.
35
36    while {![$t keyexists $n symbol]} {
37        set n [$t parent $n]
38    }
39    return $n
40}
41
42proc ::page::util::peg::symbolOf {t n} {
43    # As above, but returns the symbol name.
44
45    return [$t get [symbolNodeOf $t $n] symbol]
46}
47
48proc ::page::util::peg::updateUndefinedDueRemoval {t} {
49    # The removal of nodes may have caused symbols to lose one or more
50    # users. Example: A used by B and C, B is reachable, C is not, so A
51    # now loses a node in the expression for C calling it, or rather
52    # not anymore.
53
54    foreach {sym def} [$t get root definitions] {
55        set res {}
56        foreach u [$t get $def users] {
57            if {![$t exists $u]} continue
58            lappend res $u
59        }
60        $t set $def users $res
61    }
62
63    # Update the knowledge of undefined nonterminals. To be used when
64    # a transformation can remove invokations of undefined symbols,
65    # and is not able to generate such invokations.
66
67    set res {}
68    foreach {sym invokers} [$t get root undefined] {
69        set sres {}
70        foreach n $invokers {
71            if {![$t exists $n]} continue
72            lappend sres $n
73        }
74        if {[llength $sres]} {
75            lappend res $sym $sres
76        }
77    }
78    $t set root undefined $res
79    return
80}
81
82proc ::page::util::peg::flatten {q t} {
83    # Flatten nested x-, or /-operators.
84    # See peg_normalize.tcl, peg::normalize::ExprFlatten
85
86    foreach op {x /} {
87        # Locate all x operators, whose parents are x oerators as
88        # well, then go back to the child operators and cut them out.
89
90        $q query \
91                tree          withatt op $op \
92                parent unique withatt op $op \
93                children      withatt op $op \
94                over n {
95            $t cut $n
96        }
97    }
98    return
99}
100
101proc ::page::util::peg::getWarnings {t} {
102    # Look at the attributes for problems with the grammar and issue
103    # warnings. They do not prevent us from writing the grammar, but
104    # still represent problems with it the user should be made aware
105    # of.
106
107    array set msg {}
108    array set undefined [$t get root undefined]
109    foreach sym [array names undefined] {
110        set msg($sym) {}
111        foreach ref $undefined($sym) {
112            lappend msg($sym) "Undefined symbol used by the definition of '[symbolOf $t $ref]'."
113        }
114    }
115
116    foreach {sym def} [$t get root definitions] {
117        if {[llength [$t get $def users]] == 0} {
118            set msg($sym) [list "This symbol has been defined, but is not used."]
119        }
120    }
121
122    return [array get msg]
123}
124
125proc ::page::util::peg::printWarnings {msg} {
126    if {![llength $msg]} return
127
128    set dict {}
129    set max -1
130    foreach {k v} $msg {
131        set l [string length [list $k]]
132        if {$l > $max} {set max $l}
133        lappend dict [list $k $v $l]
134    }
135
136    foreach e [lsort -dict -index 0 $dict] {
137        foreach {k msgs l} $e break
138
139        set off [string repeat " " [expr {$max - $l}]]
140        page_info "[list $k]$off : [lindex $msgs 0]"
141
142        if {[llength $msgs] > 1} {
143            set indent [string repeat " " [string length [list $k]]]
144            foreach m [lrange $msgs 1 end] {
145                puts stderr "  $indent$off : $m"
146            }
147        }
148    }
149    return
150}
151
152proc ::page::util::peg::peOf {t eroot} {
153    set op [$t get $eroot op]
154    set pe [list $op]
155
156    set ch [$t children $eroot]
157
158    if {[llength $ch]} {
159        foreach c $ch {
160            lappend pe [peOf $t $c]
161        }
162    } elseif {$op eq "n"} {
163        lappend pe [$t get $eroot sym]
164    } elseif {$op eq "t"} {
165        lappend pe [unquote [$t get $eroot char]]
166    } elseif {$op eq ".."} {
167        lappend pe \
168                [unquote [$t get $eroot begin]] \
169                [unquote [$t get $eroot end]]
170
171    }
172    return $pe
173}
174
175proc ::page::util::peg::printTclExpr {pe} {
176    list [PrintExprSub $pe]
177}
178
179# ### ### ### ######### ######### #########
180## Internal
181
182proc ::page::util::peg::PrintExprSub {pe} {
183    set op   [lindex $pe 0]
184    set args [lrange $pe 1 end]
185
186    #puts stderr "PE [llength $args] $op | $args"
187
188    if {$op eq "t"} {
189        set a [lindex $args 0]
190        return "$op [quote'tcl $a]"
191    } elseif {$op eq ".."} {
192        set a [lindex $args 0]
193        set b [lindex $args 1]
194        return "$op [quote'tcl $a] [quote'tcl $b]"
195    } elseif {$op eq "n"} {
196        return $pe
197    } else {
198        set res $op
199        foreach a $args {
200            lappend res [PrintExprSub $a]
201        }
202        return $res
203    }
204}
205
206# ### ### ### ######### ######### #########
207## Ready
208
209package provide page::util::peg 0.1
Note: See TracBrowser for help on using the repository browser.