Re: format statement: Expanding a string
Available news archives: comp.lang.tcl - comp.lang.python - comp.security.firewalls - sci.crypt - comp.lang.php - comp.lang.javascript
Google
 
Web news.hping.org


comp.lang.tcl archive

Re: format statement: Expanding a string

From: Kaitzschu <kaitzschu@kaitzschu.cjb.net.nospam.plz.invalid>
Date: Thu Mar 02 2006 - 17:30:56 CET

On Thu, 2 Mar 2006, Andreas Leitgeb wrote:

> So what one really needs in this situation is a procedure or command
> that does the following for a given string:
> 1.) try to treat it as list: if it works out,
> return [lrange $str 0 end].
> 2.) if any non-blank prefix of the string is acceptable as
> a list, find a maximal such prefix, convert that to a
> list, and apply "3.)" on the rest.
> 3.) apply something like [split] on the rest, or treat the
> rest as one item.
>
> The second of that is non-trivial on tcl-level, especially when taking
> performance into account.

Trivial it is, performing well is out of the question :)

> I'm not proposing any new core-features (at least not on this topic),
> but if someone wrote a "reasonable list parser", it might be a valueable
> gem on wiki or tcllib.

This is just something I cooked together while waiting for Married.. with
Children to begin. Now it begins, so I'll post this now. Bye.

<some code below>

package require Tcl 8.5; # lassign

# REAsonable LiSt PArser
# not REAsonable List pARSEr

proc realspa {victim} {
  # so, if it is a list, then we'll return it
  if {![catch {llength $victim}]} {return [lrange $victim 0 end]}
  # so, it isn't a list. fine by me
  # there shall be no empty units in either end
  set victim [string trim $victim]
  # then we need something to cut this at
  set cil [regexp -all -indices -inline {\s+} $victim]
  # there are basically two ways to find out where a string is no more a list
  # 1) add stuff from the beginning until it breaks
  # 2) take stuff from the end until it doesn't break
  # 1 is the easy way out, but it'll break in my example too early
  # so case 2 it'll be
  # indices need to be reversed (courtesy of KPV)
  set st -1
  set en [llength $cil]
  foreach tm $cil {
   if {[incr st] >= [incr en -1]} {break}
   lset cil $st [lindex $cil $en]
   lset cil $en $tm
   # http://wiki.tcl.tk/43 has following line too much
   # incr st
  }
# puts "cil=$cil"
  foreach sep $cil {
   lassign $sep s e
# puts "s=$s, e=$e, r=[string range $victim 0 $s-1]"
   if {![catch {llength [string range $victim 0 $s-1]}]} {break}
  }
  # at this point we should know where it broke, and the rest is final cell
  set lst [lrange [string range $victim 0 $s-1] 0 end]
  lappend lst [string range $victim $e+1 end]
}

set t "this is one {malfor matted} {list"

puts "trying out >>$t\ninvalid list? [expr {[catch {llength $t}]?yes:no}]"
set l [realspa $t]
puts "recovered (or used) [llength $l] cells"
foreach i $l {puts "->$i<<<"}

<no more code here>

-- 
-Kaitzschu
s="TCL ";while true;do echo -en "\r$s";s=${s:1:${#s}}${s:0:1};sleep .1;done
Received on Sun Apr 30 02:20:45 2006