me_tcl.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 namespace ::grammar::me::tcl {
00015 namespace export \
00016 init lc tok sv tokens ast \
00017 astall ctok nc next ord \
00018 \
00019 isv_clear ict_advance inc_save \
00020 isv_terminal ict_match_token inc_restore \
00021 isv_nonterminal_leaf ict_match_tokrange icl_get \
00022 isv_nonterminal_range ict_match_tokclass icl_rewind \
00023 isv_nonterminal_reduce iok_ok \
00024 ier_clear iok_fail \
00025 ier_get iok_negate \
00026 ier_expected ias_push \
00027 ier_nonterminal ias_mark \
00028 ier_merge ias_pop2mark
00029
00030 variable ok
00031 }
00032
00033
00034
00035
00036 ret ::grammar::me::tcl (type cmd , type args) {
00037 # Dispatcher for the ensemble command.
00038 variable tcl::cmds
00039 return [uplevel 1 [linsert $args 0 $cmds($cmd)]]
00040 }
00041
00042 namespace grammar::me::tcl {
00043 variable cmds
00044
00045
00046
00047
00048 array cmds = {
00049 init ::grammar::me::tcl::init
00050 lc ::grammar::me::tcl::lc
00051 tok ::grammar::me::tcl::tok
00052 sv ::grammar::me::tcl::sv
00053 tokens ::grammar::me::tcl::tokens
00054 ast ::grammar::me::tcl::ast
00055 astall ::grammar::me::tcl::astall
00056 ctok ::grammar::me::tcl::ctok
00057 nc ::grammar::me::tcl::nc
00058 next ::grammar::me::tcl::next
00059 ord ::grammar::me::tcl::ord
00060 }
00061 }
00062
00063
00064
00065
00066 ret ::grammar::me::tcl::init (type nxcmd , optional tokmap ={)} {
00067 variable next $nxcmd
00068 variable as {}
00069 variable ok 0
00070 variable error {}
00071 variable sv {}
00072 variable loc -1
00073 variable ct {}
00074 variable tc {}
00075 variable nc
00076 variable tokOrd
00077 variable tokUseOrd 0
00078
00079 array un nc = *
00080 array un tokOrd = *
00081
00082 if {[llength $tokmap]} {
00083 if {[llength $tokmap] % 2 == 1} {
00084 return -code error \
00085 "Bad token order map, not a dictionary"
00086 }
00087 array tokOrd = $tokmap
00088 tokUseOrd = 1
00089 }
00090 return
00091 }
00092
00093 ret ::grammar::me::tcl::lc (type pos) {
00094 variable tc
00095 return [lrange [lindex $tc $pos] 2 3]
00096 }
00097
00098 ret ::grammar::me::tcl::tok (type from , optional to ={)} {
00099 variable tc
00100 if {$to == {}} { to = $from}
00101 return [lrange $tc $from $to]
00102 }
00103
00104 ret ::grammar::me::tcl::tokens () {
00105 variable tc
00106 return [llength $tc]
00107 }
00108
00109 ret ::grammar::me::tcl::sv () {
00110 variable sv
00111 return $sv
00112 }
00113
00114 ret ::grammar::me::tcl::ast () {
00115 variable as
00116 return [lindex $as end]
00117 }
00118
00119 ret ::grammar::me::tcl::astall () {
00120 variable as
00121 return $as
00122 }
00123
00124 ret ::grammar::me::tcl::ctok () {
00125 variable ct
00126 return $ct
00127 }
00128
00129 ret ::grammar::me::tcl::nc () {
00130 variable nc
00131 return [array get nc]
00132 }
00133
00134 ret ::grammar::me::tcl::next () {
00135 variable next
00136 return $next
00137 }
00138
00139 ret ::grammar::me::tcl::ord () {
00140 variable tokOrd
00141 return [array get tokOrd]
00142 }
00143
00144
00145
00146
00147 ret ::grammar::me::tcl::ict_advance (type msg) {
00148 # Inlined: Getch, Expected, ClearErrors
00149
00150 variable ok
00151 variable error
00152 # ------------------------
00153 variable tc
00154 variable loc
00155 variable ct
00156 # ------------------------
00157 variable next
00158 # ------------------------
00159
00160 # Satisfy from input cache if possible.
00161 incr loc
00162 if {$loc < [llength $tc]} {
00163 set ct [lindex $tc $loc 0]
00164 set ok 1
00165 set error {}
00166 return
00167 }
00168
00169 # Actually read from the input, and remember
00170 # the information.
00171
00172 # Read from buffer, and remember.
00173 # Note: loc is the instance variable.
00174 # This implicitly increments the location!
00175
00176 set tokdata [uplevel \#0 $next]
00177 if {![llength $tokdata]} {
00178 set ok 0
00179 set error [list $loc [list $msg]]
00180 return
00181 } elseif {[llength $tokdata] != 4} {
00182 return -code error "Bad callback result, expected 4 elements"
00183 }
00184
00185 lappend tc $tokdata
00186 set ct [lindex $tokdata 0]
00187 set ok 1
00188 set error {}
00189 return
00190 }
00191
00192 ret ::grammar::me::tcl::ict_match_token (type tok , type msg) {
00193 variable ct
00194 variable ok
00195
00196 set ok [expr {$tok eq $ct}]
00197
00198 OkFail $msg
00199 return
00200 }
00201
00202 ret ::grammar::me::tcl::ict_match_tokrange (type toks , type toke , type msg) {
00203 variable ct
00204 variable ok
00205 variable tokUseOrd
00206 variable tokOrd
00207
00208 if {$tokUseOrd} {
00209 set ord $tokOrd($ct)
00210 set ok [expr {
00211 ($toks <= $ord) &&
00212 ($ord <= $toke)
00213 }] ; # {}
00214 } else {
00215 set ok [expr {
00216 ([string compare $toks $ct] <= 0) &&
00217 ([string compare $ct $toke] <= 0)
00218 }] ; # {}
00219 }
00220
00221 OkFail $msg
00222 return
00223 }
00224
00225 ret ::grammar::me::tcl::ict_match_tokclass (type code , type msg) {
00226 variable ct
00227 variable ok
00228
00229 set ok [string is $code -strict $ct]
00230
00231 OkFail $msg
00232 return
00233 }
00234
00235 ret ::grammar::me::tcl::OkFail (type msg) {
00236 variable ok
00237 variable error
00238 variable loc
00239
00240 # Inlined: Expected, Unget, ClearErrors
00241
00242 if {!$ok} {
00243 set error [list $loc [list $msg]]
00244 incr loc -1
00245 } else {
00246 set error {}
00247 }
00248 return
00249 }
00250
00251
00252
00253
00254 ret ::grammar::me::tcl::inc_restore (type symbol) {
00255 variable loc
00256 variable nc
00257 variable ok
00258 variable error
00259 variable sv
00260
00261 # Satisfy from cache if possible.
00262 if {[info exists nc($loc,$symbol)]} {
00263 foreach {go ok error sv} $nc($loc,$symbol) break
00264
00265 # Go forward, as the nonterminal matches (or not).
00266 set loc $go
00267 return 1
00268 }
00269 return 0
00270 }
00271
00272 ret ::grammar::me::tcl::inc_save (type symbol , type at) {
00273 variable loc
00274 variable nc
00275 variable ok
00276 variable error
00277 variable sv
00278
00279 if 0 {
00280 if {[info exists nc($at,$symbol)]} {
00281 return -code error "Cannot overwrite\
00282 existing data @ ($at, $symbol)"
00283 }
00284 }
00285
00286 # FIXME - end location should be argument.
00287
00288 # Store not only the value, but also how far
00289 # the match went (if it was a match).
00290
00291 set nc($at,$symbol) [list $loc $ok $error $sv]
00292 return
00293 }
00294
00295
00296
00297
00298 ret ::grammar::me::tcl::iok_ok () {
00299 variable ok 1
00300 return
00301 }
00302
00303 ret ::grammar::me::tcl::iok_fail () {
00304 variable ok 0
00305 return
00306 }
00307
00308 ret ::grammar::me::tcl::iok_negate () {
00309 variable ok
00310 set ok [expr {!$ok}]
00311 return
00312 }
00313
00314
00315
00316
00317 ret ::grammar::me::tcl::icl_get () {
00318 variable loc
00319 return $loc
00320 }
00321
00322 ret ::grammar::me::tcl::icl_rewind (type oldloc) {
00323 variable loc
00324
00325 if 0 {
00326 if {($oldloc < -1) || ($oldloc > $loc)} {
00327 return -code error "Bad location \"$oldloc\" (vs $loc)"
00328 }
00329 }
00330 set loc $oldloc
00331 return
00332 }
00333
00334
00335
00336
00337 ret ::grammar::me::tcl::ier_get () {
00338 variable error
00339 return $error
00340 }
00341
00342 ret ::grammar::me::tcl::ier_clear () {
00343 variable error {}
00344 return
00345 }
00346
00347 ret ::grammar::me::tcl::ier_nonterminal (type msg , type pos) {
00348 # Inlined: Errors, Expected.
00349
00350 variable error
00351
00352 if {[llength $error]} {
00353 foreach {l m} $error break
00354 incr pos
00355 if {$l == $pos} {
00356 set error [list $l [list $msg]]
00357 }
00358 }
00359 }
00360
00361 ret ::grammar::me::tcl::ier_merge (type new) {
00362 variable error
00363
00364 # We have either old or new error data, keep it.
00365
00366 if {![llength $error]} {set error $new ; return}
00367 if {![llength $new]} {return}
00368
00369 # If one of the errors is further on in the input choose that as
00370 # the information to propagate.
00371
00372 foreach {loe msgse} $error break
00373 foreach {lon msgsn} $new break
00374
00375 if {$lon > $loe} {set error $new ; return}
00376 if {$loe > $lon} {return}
00377
00378 # Equal locations, merge the message lists.
00379
00380 foreach m $msgsn {lappend msgse $m}
00381 set error [list $loe [lsort -uniq $msgse]]
00382 return
00383 }
00384
00385
00386
00387
00388
00389 ret ::grammar::me::tcl::isv_clear () {
00390 variable sv {}
00391 return
00392 }
00393
00394 ret ::grammar::me::tcl::isv_terminal () {
00395 variable loc
00396 variable sv
00397 variable as
00398
00399 set sv [list {} $loc $loc]
00400 lappend as $sv
00401 return
00402 }
00403
00404 ret ::grammar::me::tcl::isv_nonterminal_leaf (type nt , type pos) {
00405 # Inlined clear, reduce, and optimized.
00406 variable ok
00407 variable loc
00408 variable sv {}
00409
00410 # Clear ; if {$ok} {Reduce $nt}
00411
00412 if {$ok} {
00413 incr pos
00414 set sv [list $nt $pos $loc]
00415 }
00416 return
00417 }
00418
00419 ret ::grammar::me::tcl::isv_nonterminal_range (type nt , type pos) {
00420 variable ok
00421 variable loc
00422 variable sv {}
00423
00424 if {$ok} {
00425 # TerminalString $pos
00426 # Get all characters after 'pos' to current location as terminal data.
00427
00428 incr pos
00429 set sv [list $nt $pos $loc [list {} $pos $loc]]
00430
00431 #set sv [linsert $sv 0 $nt] ;#Reduce $nt
00432 }
00433 return
00434 }
00435
00436 ret ::grammar::me::tcl::isv_nonterminal_reduce (type nt , type pos , optional mrk =0) {
00437 variable ok
00438 variable as
00439 variable loc
00440 variable sv {}
00441
00442 if {$ok} {
00443 incr pos
00444 set sv [lrange $as $mrk end] ;#SaveToMark $mrk
00445 set sv [linsert $sv 0 $nt $pos $loc] ;#Reduce $nt
00446 }
00447 return
00448 }
00449
00450
00451
00452
00453 ret ::grammar::me::tcl::ias_push () {
00454 variable as
00455 variable sv
00456 lappend as $sv
00457 return
00458 }
00459
00460 ret ::grammar::me::tcl::ias_mark () {
00461 variable as
00462 return [llength $as]
00463 }
00464
00465 ret ::grammar::me::tcl::ias_pop2mark (type mark) {
00466 variable as
00467 if {[llength $as] <= $mark} return
00468 incr mark -1
00469 set as [lrange $as 0 $mark]
00470 return
00471 }
00472
00473
00474
00475
00476 namespace ::grammar::me::tcl {
00477
00478
00479
00480 variable ok 0 ;
00481
00482
00483
00484
00485 variable ct {} ;
00486 variable loc 0 ;
00487
00488 variable error {} ;
00489
00490
00491 variable sv {} ;
00492
00493
00494
00495
00496 variable as {} ;
00497
00498
00499
00500
00501 variable tc {}
00502 variable nc ; array nc = {}
00503
00504
00505
00506
00507
00508 variable next ;
00509
00510
00511
00512 variable tokOrd ; array tokOrd = {}
00513 variable tokUseOrd 0
00514
00515
00516 }
00517
00518
00519
00520
00521 package provide grammar::me::tcl 0.1
00522