So... kicking off a new thread here.
(I'll be lucky if anyone understands this I'll just bet!)
I'm attempting to build a parser based on these specs:
<http://www.topcat.hypermart.net/papers/topic-spec.txt>
Here's the setup described verbally, (code below)...
1: if there's a match for a term I supply in a line
that does not contain a tab, then display the line,
and proceed to step 2...
2: when step 1 is true, display all empty lines and,
lines that begin with a tab - until - a line is found,
that contains an alphanumeric char in its 1st element,
in that event proceed to step 3, else stay in step 2.
3: when step 2 finds an alphanumeric char in its 1st element
start over beginning at step 1.
Comments/suggestions always welcome. Here's the relevant
portion of the code:
(defvar n 0)
; while reading from standard-input in a loop...
let (
(x (length (string-trim '(#\Space) line)))
(y (search s (string-downcase line))))
(case n
; when n = 0:
;
; - line length must be greater than zero
; - search term must be found in 'line'
; - line must not contain a tab
; so: write line, & set n = 1
((n 0) (and (> x 0) (numberp y) (char/= (char line 0) #\Tab)
(write-line line)
(setf n 1)))
; when n = 1:
;
; - line can be only one of, zero length, or begin w/ tab
; so: write line, & set n = 2
((n 1) (or (eql x 0) (char= (char line 0) #\Tab)
(write-line line)
(setf n 2)))
; when n = 2:
;
; - line length must be greater than zero
; - 1st char of line must be alpha-numeric
; so: set n = 0
;
; but if not?
; I cant not yet account for that - here's where I'm stuck,
; how to create an 'else', all my attempts are not working
; thus far
((n 2) (and (> x 0) (t (alphanumericp (char line 0)))
(setf n 0)))
) ; end case...
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/7/2011 7:50:26 PM |
|
mss <mss@dev.null> writes:
> let (
> (x (length (string-trim '(#\Space) line)))
> (y (search s (string-downcase line))))
You got your parentheses wrong here. It should be:
let
((x (length (string-trim '(#\Space) line)))
(y (search s (string-downcase line))))
Then you can easily see that you've got two errors:
let
you have not defined any variable named let. So you will get an unbound
variable error.
((x (length (string-trim '(#\Space) line)))
(y (search s (string-downcase line))))
(x (length (string-trim '(#\Space) line))) is not the name of a function
therefore the application is wrong.
> (case n
>
> ; when n = 0:
> ;
> ; - line length must be greater than zero
> ; - search term must be found in 'line'
> ; - line must not contain a tab
> ; so: write line, & set n = 1
>
>
> ((n 0) (and (> x 0) (numberp y) (char/= (char line 0) #\Tab)
> (write-line line)
> (setf n 1)))
> ...
Here, it's your indentation that is wrong. Why don't you use emacs? A
single key chord will format it correctly:
(case n
; when n = 0:
;
; - line length must be greater than zero
; - search term must be found in 'line'
; - line must not contain a tab
; so: write line, & set n = 1
((n 0) (and (> x 0) (numberp y) (char/= (char line 0) #\Tab)
(write-line line)
(setf n 1)))
; when n = 1:
;
; - line can be only one of, zero length, or begin w/ tab
; so: write line, & set n = 2
((n 1) (or (eql x 0) (char= (char line 0) #\Tab)
(write-line line)
(setf n 2)))
; when n = 2:
;
; - line length must be greater than zero
; - 1st char of line must be alpha-numeric
; so: set n = 0
;
; but if not?
; I cant not yet account for that - here's where I'm stuck,
; how to create an 'else', all my attempts are not working
; thus far
((n 2) (and (> x 0) (t (alphanumericp (char line 0)))
(setf n 0)))
) ; end case...
Why are you considering the symbol N as a case value for N? Can N be
bound to the symbol N? If that's the case, why do you mention it in
three clauses? Only the first one will ever be considered!
When N is bound to 1, it will NEVER be changed to 2.
T is not the name of a function, therefore you will have an error
whenver N is bound to 2.
In conclusion, you're being sloppy, and there's no way you can become a
programmer if you keep being sloppy. Therefore stop it right now!
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
Pascal
|
2/7/2011 9:06:00 PM
|
|
Pascal J. Bourguignon wrote:
> In conclusion, you're being sloppy, and there's no way you can become a
> programmer if you keep being sloppy. Therefore stop it right now!
Thanks Pascal (I think).
Back to the code for me, more to come.
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 1:52:08 AM
|
|
Well its 'alive' & while not hitting on all cylinders just yet,
I'm now at the 2nd step of:
'make it run, make it run right, make it run better'
Here's an example of the file I'm parsing:
Apples, Fruit
Block line 1
Block line 2
Block line n...
Oranges, Fruit
Block line 1
Block line 2
Block line n...
Calling the function as 'loadblock("fruit")', I can correctly
write up to - yet excluding - the line beginning with 'Oranges'.
And therein lies the next step: I'm not sure why the line 'Oranges'
and beneath are being skipped as I thought my logic accounted for
finding all instances of 'fruit' on a line that does not contain a
leading tab.
Here's my code. Its not fully formatted/indented as per Lisp
conventions to give my self some elbow room (but it will be
eventually). Comments are very much appreciated.
;
(defun loadblock(s)
(defvar n 0)
(loop for line = (read-line *standard-input* nil)
while line
do
(let
((x (length (string-trim '(#\Space) line)))
(y (search s (string-downcase line)))); end let
(case n
((0) (and (> x 0) (numberp y) (char/= (char line 0) #\Tab)
(write-line line)
(setf n 1)))
((1) (if (or (eql x 0) (char= (char line 0) #\Tab))
(write-line line)
(setf n 2)))
((2) (and (> x 0) (alphanumericp (char line 0))
(setf n 0)))
); end case
); end do
) ; end loop
) ; end function
;
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 2:20:09 PM
|
|
mss wrote:
> And therein lies the next step: I'm not sure why the line 'Oranges'
> and beneath are being skipped as I thought my logic accounted for
> finding all instances of 'fruit' on a line that does not contain a
> leading tab.
Thinking aloud here: I need to somehow 'goto' the 1st keylist form,
from the last keylist form...
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 2:42:41 PM
|
|
On Feb 8, 3:20=A0pm, mss <m...@dev.null> wrote:
> Well its 'alive' & while not hitting on all cylinders just yet,
> I'm now at the 2nd step of:
>
> 'make it run, make it run right, make it run better'
>
> Here's an example of the file I'm parsing:
An "example" is not enough. This is an example of "code"
x + 42;
What is the full spec of the file you are parsing? First produce that
and then it will become easy to figure out how to "parse" the file.
Cheers
Marco
>
> Apples, Fruit
>
> =A0 =A0 =A0 =A0 Block line 1
> =A0 =A0 =A0 =A0 Block line 2
> =A0 =A0 =A0 =A0 Block line n...
>
> Oranges, Fruit
>
> =A0 =A0 =A0 =A0 Block line 1
> =A0 =A0 =A0 =A0 Block line 2
> =A0 =A0 =A0 =A0 Block line n...
>
> Calling the function as 'loadblock("fruit")', I can correctly
> write up to - yet excluding - the line beginning with 'Oranges'.
> And therein lies the next step: I'm not sure why the line 'Oranges'
> and beneath are being skipped as I thought my logic accounted for
> finding all instances of 'fruit' on a line that does not contain a
> leading tab.
>
> Here's my code. Its not fully formatted/indented as per Lisp
> conventions to give my self some elbow room (but it will be
> eventually). Comments are very much appreciated.
>
> ;
>
> (defun loadblock(s)
>
> (defvar n 0)
>
> =A0 =A0 (loop for line =3D (read-line *standard-input* nil)
>
> =A0 =A0 =A0 =A0 while line
> =A0 =A0 =A0 =A0 do
>
> =A0 =A0 =A0 =A0 (let
> =A0 =A0 =A0 =A0 =A0 =A0 ((x (length (string-trim '(#\Space) line)))
> =A0 =A0 =A0 =A0 =A0 =A0 (y (search s (string-downcase line)))); end let
>
> =A0 =A0 =A0 =A0 =A0(case n
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0((0) (and (> x 0) (numberp y) (char/=3D (char =
line 0) #\Tab)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (write-line line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (setf n 1)))
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0((1) (if (or (eql x 0) (char=3D (char line 0) =
#\Tab))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (write-line line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (setf n 2)))
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0((2) (and (> x 0) (alphanumericp (char line 0)=
)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (setf n 0)))
>
> =A0 =A0 =A0 =A0 =A0); end case
>
> =A0 =A0 =A0 =A0); end do
>
> =A0 =A0 ) ; end loop
>
> ) ; end function
>
> ;
>
> --
> later on,
> Mike
>
> http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
Marco
|
2/8/2011 3:46:01 PM
|
|
mss <mss@dev.null> writes:
> Well its 'alive' & while not hitting on all cylinders just yet,
> I'm now at the 2nd step of:
>
> 'make it run, make it run right, make it run better'
I honestly doubt that it's alive already ... See below.
>
> Here's an example of the file I'm parsing:
>
>
> Apples, Fruit
>
>
> Block line 1
> Block line 2
> Block line n...
>
>
> Oranges, Fruit
>
>
> Block line 1
> Block line 2
> Block line n...
Ok - I put that in a file.
> Calling the function as 'loadblock("fruit")', I can correctly
No, actually you can't. That has to read
(loadblock "fruit")
if is meant to work at all. But you know that, I'm sure.
> write up to - yet excluding - the line beginning with 'Oranges'.
> And therein lies the next step: I'm not sure why the line 'Oranges'
> and beneath are being skipped as I thought my logic accounted for
> finding all instances of 'fruit' on a line that does not contain a
> leading tab.
>
> Here's my code. Its not fully formatted/indented as per Lisp
> conventions to give my self some elbow room (but it will be
> eventually). Comments are very much appreciated.
So here's my formatted and indented version which still does not see the
organges...
(defun loadblock (string &optional (stream *standard-input*))
(let ((n 0))
(loop for line = (read-line stream nil)
while line
do
(let ((x (length (string-trim '(#\Space) line)))
(y (search string (string-downcase line))))
(case n
((0) (if (and (> x 0)
(numberp y)
(char/= (char line 0) #\Tab))
(write-line line)
(setq n 1)))
((1) (if (or (= x 0)
(char= (char line 0) #\Tab))
(write-line line)
(setq n 2)))
((2) (if (and (> x 0)
(alphanumericp (char line 0)))
(setq n 0)))))))
(values))
With this you can do
CL-USER> (with-open-file (s "/tmp/mss.data" :direction :input)
(loadblock "fruit" s))
Which gives:
Apples, Fruit
Block line 1
Block line 2
Block line n...
; No value
In order to facilitate debugging a little a format here and a format
there is useful:
(defun loadblock (string &optional (stream *standard-input*))
(let ((n 0))
(loop for line = (read-line stream nil)
while line
do
(let ((x (length (string-trim '(#\Space) line)))
(y (search string (string-downcase line))))
;; DEBUG INFO
(format *debug-io* "~&;; LOADBLOCK: x = ~s" x)
(format *debug-io* "~&;; y = ~s" y)
(format *debug-io* "~&;; n = ~d" n)
(case n
((0) (if (and (> x 0)
(numberp y)
(char/= (char line 0) #\Tab))
(write-line line)
(setq n 1)))
((1) (if (or (= x 0)
(char= (char line 0) #\Tab))
(write-line line)
(setq n 2)))
((2) (if (and (> x 0)
(alphanumericp (char line 0)))
(setq n 0)))))))
(values))
And running this gives:
CL-USER> (with-open-file (s "/tmp/mss.data" :direction :input)
(loadblock "fruit" s))
;; LOADBLOCK: x = 13
;; y = 8
;; n = 0Apples, Fruit
;; LOADBLOCK: x = 0
;; y = NIL
;; n = 0
;; LOADBLOCK: x = 0
;; y = NIL
;; n = 1
;; LOADBLOCK: x = 13
;; y = NIL
;; n = 1 Block line 1
;; LOADBLOCK: x = 13
;; y = NIL
;; n = 1 Block line 2
;; LOADBLOCK: x = 16
;; y = NIL
;; n = 1 Block line n...
;; LOADBLOCK: x = 0
;; y = NIL
;; n = 1
;; LOADBLOCK: x = 0
;; y = NIL
;; n = 1
;; LOADBLOCK: x = 14
;; y = 9
;; n = 1
;; LOADBLOCK: x = 0
;; y = NIL
;; n = 2
;; LOADBLOCK: x = 0
;; y = NIL
;; n = 2
;; LOADBLOCK: x = 13
;; y = NIL
;; n = 2
;; LOADBLOCK: x = 13
;; y = NIL
;; n = 2
;; LOADBLOCK: x = 16
;; y = NIL
;; n = 2; No value
.... which should give you an idea why you see no oranges ...
Cheers
Frank
|
|
0
|
|
|
|
Reply
|
Frank
|
2/8/2011 6:45:42 PM
|
|
Marco Antoniotti wrote:
> On Feb 8, 3:20�pm, mss <m...@dev.null> wrote:
>> Well its 'alive' & while not hitting on all cylinders just yet,
>> I'm now at the 2nd step of:
>>
>> 'make it run, make it run right, make it run better'
>>
>> Here's an example of the file I'm parsing:
>
> An "example" is not enough. This is an example of "code"
>
> x + 42;
>
> What is the full spec of the file you are parsing? First produce that
> and then it will become easy to figure out how to "parse" the file.
>
> Cheers
>
> Marco
Thanks Marco.
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 6:53:58 PM
|
|
Frank GOENNINGER wrote:
>> Calling the function as 'loadblock("fruit")', I can correctly
>
> No, actually you can't. That has to read
>
> (loadblock "fruit")
>
> if is meant to work at all. But you know that, I'm sure.
No it does work, but in the portion that contains the single
quotes, (which I added for emphasis), that was a bad idea
(new to Lisp...).
> So here's my formatted and indented version which still does not see the
> organges...
[...]
> *debug-io*
Ahh...
Thanks for that tip Frank!
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 7:00:40 PM
|
|
mss wrote:
>
> So... kicking off a new thread here.
>
> (I'll be lucky if anyone understands this I'll just bet!)
>
> I'm attempting to build a parser based on these specs:
>
> <http://www.topcat.hypermart.net/papers/topic-spec.txt>
>
> Here's the setup described verbally, (code below)...
>
>
> 1: if there's a match for a term I supply in a line
> that does not contain a tab, then display the line,
> and proceed to step 2...
>
> 2: when step 1 is true, display all empty lines and,
> lines that begin with a tab - until - a line is found,
> that contains an alphanumeric char in its 1st element,
> in that event proceed to step 3, else stay in step 2.
>
>
> 3: when step 2 finds an alphanumeric char in its 1st element
> start over beginning at step 1.
>
>
> Comments/suggestions always welcome. Here's the relevant
> portion of the code:
>
>
> (defvar n 0)
>
> ; while reading from standard-input in a loop...
>
> let (
> (x (length (string-trim '(#\Space) line)))
> (y (search s (string-downcase line))))
>
> (case n
>
> ; when n = 0:
> ;
> ; - line length must be greater than zero
> ; - search term must be found in 'line'
> ; - line must not contain a tab
> ; so: write line, & set n = 1
>
>
> ((n 0) (and (> x 0) (numberp y) (char/= (char line 0) #\Tab)
> (write-line line)
> (setf n 1)))
>
>
> ; when n = 1:
> ;
> ; - line can be only one of, zero length, or begin w/ tab
> ; so: write line, & set n = 2
>
>
> ((n 1) (or (eql x 0) (char= (char line 0) #\Tab)
> (write-line line)
> (setf n 2)))
>
>
> ; when n = 2:
> ;
> ; - line length must be greater than zero
> ; - 1st char of line must be alpha-numeric
> ; so: set n = 0
> ;
> ; but if not?
> ; I cant not yet account for that - here's where I'm stuck,
> ; how to create an 'else', all my attempts are not working
> ; thus far
>
>
> ((n 2) (and (> x 0) (t (alphanumericp (char line 0)))
> (setf n 0)))
>
>
> ) ; end case...
Using MatzLisp (Ruby):
$filename = ARGV.shift
def read_block file
result = []
pos = nil
while !file.eof?
pos = file.pos
line = file.readline.chomp
if line =~ /^ *[[:alnum:]]/
file.seek( pos )
break
end
result << line
end
result
end
def find_records key
records = []
open( $filename ){|file|
while !file.eof?
line = file.readline.chomp
next if line =~ /^\t/
line.strip!
if line =~ /^[[:alnum:]]/
keys = line.split( / *, */ ).map{|s| s.upcase}
if keys.include?( key.upcase )
record = [ line ]
record << read_block( file )
records << record.flatten
end
end
end
}
records
end
p find_records( "fruit" )
p find_records( "oranges" )
p find_records( "orange" )
|
|
0
|
|
|
|
Reply
|
William
|
2/8/2011 9:08:10 PM
|
|
Here's what I came up with for Ruby:
def topic(t)
x = 0
STDIN.read.split("\n").each do |s|
if x == 1
if (s.index(/\t/) == 0) || (s.strip.chop.size < 1)
puts s
next
end
end
if
s.downcase.match(/(^|,)[[:space:]]*#{Regexp.escape(t)}[[:space:]]*(,|$)/)
puts s
x = 1
else
x = 0
end
end
end
William James wrote:
> Using MatzLisp (Ruby):
>
>
> $filename = ARGV.shift
>
> def read_block file
> result = []
> pos = nil
> while !file.eof?
> pos = file.pos
> line = file.readline.chomp
> if line =~ /^ *[[:alnum:]]/
> file.seek( pos )
> break
> end
> result << line
> end
> result
> end
>
> def find_records key
> records = []
> open( $filename ){|file|
> while !file.eof?
> line = file.readline.chomp
> next if line =~ /^\t/
> line.strip!
> if line =~ /^[[:alnum:]]/
> keys = line.split( / *, */ ).map{|s| s.upcase}
> if keys.include?( key.upcase )
> record = [ line ]
> record << read_block( file )
> records << record.flatten
> end
> end
> end
> }
> records
> end
>
>
> p find_records( "fruit" )
> p find_records( "oranges" )
> p find_records( "orange" )
>
>
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 9:19:31 PM
|
|
On Feb 8, 10:19=A0pm, mss <m...@dev.null> wrote:
> Here's what I came up with for Ruby:
>
> def topic(t)
>
> =A0 =A0x =3D 0
>
> =A0 =A0STDIN.read.split("\n").each do |s|
> =A0 =A0 =A0 if x =3D=3D 1
> =A0 =A0 =A0 =A0 =A0if (s.index(/\t/) =3D=3D 0) || (s.strip.chop.size < 1)
> =A0 =A0 =A0 =A0 =A0 =A0 puts s
> =A0 =A0 =A0 =A0 =A0 =A0 next
> =A0 =A0 =A0 =A0 =A0end
> =A0 =A0 =A0 end
> =A0 =A0 =A0 if
> =A0 =A0 =A0 s.downcase.match(/(^|,)[[:space:]]*#{Regexp.escape(t)}[[:spac=
e:]]*(,|$)/)
> =A0 =A0 =A0 =A0 =A0puts s
> =A0 =A0 =A0 =A0 =A0x =3D 1
> =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 =A0x =3D 0
> =A0 =A0 =A0 end
> =A0 =A0end
>
> end
>
>
>
>
>
>
>
>
>
> William James wrote:
> > Using MatzLisp (Ruby):
>
> > $filename =3D ARGV.shift
>
> > def read_block file
> > =A0 result =3D []
> > =A0 pos =3D nil
> > =A0 while !file.eof?
> > =A0 =A0 pos =3D file.pos
> > =A0 =A0 line =3D file.readline.chomp
> > =A0 =A0 if line =3D~ /^ *[[:alnum:]]/
> > =A0 =A0 =A0 file.seek( pos )
> > =A0 =A0 =A0 break
> > =A0 =A0 end
> > =A0 =A0 result << line
> > =A0 end
> > =A0 result
> > end
>
> > def find_records key
> > =A0 records =3D []
> > =A0 open( $filename ){|file|
> > =A0 =A0 while !file.eof?
> > =A0 =A0 =A0 line =3D file.readline.chomp
> > =A0 =A0 =A0 next if line =3D~ /^\t/
> > =A0 =A0 =A0 line.strip!
> > =A0 =A0 =A0 if line =3D~ /^[[:alnum:]]/
> > =A0 =A0 =A0 =A0 keys =3D line.split( / *, */ ).map{|s| s.upcase}
> > =A0 =A0 =A0 =A0 if keys.include?( key.upcase )
> > =A0 =A0 =A0 =A0 =A0 record =3D [ line ]
> > =A0 =A0 =A0 =A0 =A0 record << read_block( file )
> > =A0 =A0 =A0 =A0 =A0 records << record.flatten
> > =A0 =A0 =A0 =A0 end
> > =A0 =A0 =A0 end
> > =A0 =A0 end
> > =A0 }
> > =A0 records
> > end
>
> > p find_records( "fruit" )
> > p find_records( "oranges" )
> > p find_records( "orange" )
>
> --
> later on,
> Mike
>
> http://www.topcat.hypermart.net/index.html
That is pretty impressive given that we still don't know what we are
supposed to parse :)
Cheers
--
Marco
|
|
0
|
|
|
|
Reply
|
Marco
|
2/8/2011 10:08:47 PM
|
|
Marco Antoniotti wrote:
> That is pretty impressive given that we still don't know what we are
> supposed to parse :)
Chuckle, my bad Marco. The specs along with parsers
in several languages are here:
<http://www.topcat.hypermart.net/topic.html>
If you can help with the lisp version, feel free to jump in.
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 10:14:20 PM
|
|
mss <mss@dev.null> writes:
> Chuckle, my bad Marco. The specs along with parsers
> in several languages are here:
>
> <http://www.topcat.hypermart.net/topic.html>
What a terrible spec, another 'standardized' DSL with no reason for
existence. Is there some real-world situation that requires you to use
that format? If not, then it's better to use something reasonable
instead. This being comp.lang.lisp, "something reasonable" is probably
S-expressions, but other alternatives include json, yaml, etc.
|
|
0
|
|
|
|
Reply
|
Paul
|
2/8/2011 10:34:20 PM
|
|
Paul Rubin wrote:
> What a terrible spec, another 'standardized' DSL with no reason for
> existence. Is there some real-world situation that requires you to use
> that format? If not, then it's better to use something reasonable
> instead. This being comp.lang.lisp, "something reasonable" is probably
> S-expressions, but other alternatives include json, yaml, etc.
Then the spec is not for you - problem sloved no?
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 10:37:05 PM
|
|
mss <mss@dev.null> writes:
> Then the spec is not for you - problem sloved no?
If you seek programming advice on a newsgroup then you will probably
receive some. The advice in this case is to modify the spec rather than
implementing it directly. Perhaps that advice is not for you - problem
sloved [sic] no?
|
|
0
|
|
|
|
Reply
|
Paul
|
2/8/2011 10:58:05 PM
|
|
Paul Rubin wrote:
> If you seek programming advice on a newsgroup then you will probably
> receive some. The advice in this case is to modify the spec rather than
> implementing it directly. Perhaps that advice is not for you - problem
> sloved [sic] no?
The spec is fine, its a simple thing, that's all it has to be,
and that's all its meant to be.
Its not a matter of not appreciating your input, but you
haven't really offered much more than flippant remarks
(in your initial response at least).
I'm always willing learn, and grateful for those whom
take the time to explain what's on their minds. Yet, the
spirit in which you offer up your thoughts makes me wary.
I'm not into impressing others with great displays,
I just want to build a parser for the spec in Lisp, and
learn some Lisp along the way.
So, what you'd do differently?
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 11:27:25 PM
|
|
On Feb 8, 1:19=A0pm, mss <m...@dev.null> wrote:
> Here's what I came up with for Ruby:
>
> def topic(t)
>
> =A0 =A0x =3D 0
>
> =A0 =A0STDIN.read.split("\n").each do |s|
> =A0 =A0 =A0 if x =3D=3D 1
> =A0 =A0 =A0 =A0 =A0if (s.index(/\t/) =3D=3D 0) || (s.strip.chop.size < 1)
> =A0 =A0 =A0 =A0 =A0 =A0 puts s
> =A0 =A0 =A0 =A0 =A0 =A0 next
> =A0 =A0 =A0 =A0 =A0end
> =A0 =A0 =A0 end
> =A0 =A0 =A0 if
> =A0 =A0 =A0 s.downcase.match(/(^|,)[[:space:]]*#{Regexp.escape(t)}[[:spac=
e:]]*(,|$)/)
> =A0 =A0 =A0 =A0 =A0puts s
> =A0 =A0 =A0 =A0 =A0x =3D 1
> =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 =A0x =3D 0
> =A0 =A0 =A0 end
> =A0 =A0end
>
> end
>
>
>
>
>
> William James wrote:
> > Using MatzLisp (Ruby):
>
> > $filename =3D ARGV.shift
>
> > def read_block file
> > =A0 result =3D []
> > =A0 pos =3D nil
> > =A0 while !file.eof?
> > =A0 =A0 pos =3D file.pos
> > =A0 =A0 line =3D file.readline.chomp
> > =A0 =A0 if line =3D~ /^ *[[:alnum:]]/
> > =A0 =A0 =A0 file.seek( pos )
> > =A0 =A0 =A0 break
> > =A0 =A0 end
> > =A0 =A0 result << line
> > =A0 end
> > =A0 result
> > end
>
> > def find_records key
> > =A0 records =3D []
> > =A0 open( $filename ){|file|
> > =A0 =A0 while !file.eof?
> > =A0 =A0 =A0 line =3D file.readline.chomp
> > =A0 =A0 =A0 next if line =3D~ /^\t/
> > =A0 =A0 =A0 line.strip!
> > =A0 =A0 =A0 if line =3D~ /^[[:alnum:]]/
> > =A0 =A0 =A0 =A0 keys =3D line.split( / *, */ ).map{|s| s.upcase}
> > =A0 =A0 =A0 =A0 if keys.include?( key.upcase )
> > =A0 =A0 =A0 =A0 =A0 record =3D [ line ]
> > =A0 =A0 =A0 =A0 =A0 record << read_block( file )
> > =A0 =A0 =A0 =A0 =A0 records << record.flatten
> > =A0 =A0 =A0 =A0 end
> > =A0 =A0 =A0 end
> > =A0 =A0 end
> > =A0 }
> > =A0 records
> > end
>
> > p find_records( "fruit" )
> > p find_records( "oranges" )
> > p find_records( "orange" )
>
> --
> later on,
> Mike
>
> http://www.topcat.hypermart.net/index.html- Hide quoted text -
In this Ruby code you appear to have two states - "MATCHED_BLOCK"
"NON_MATCHED_BLOCK"
In your Common Lisp code you appear to have three states. What are the
three states of the Common Lisp code?
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/8/2011 11:27:41 PM
|
|
TheFlyingDutchman wrote:
> In this Ruby code you appear to have two states - "MATCHED_BLOCK"
> "NON_MATCHED_BLOCK"
>
> In your Common Lisp code you appear to have three states. What are the
> three states of the Common Lisp code?
Good catch...
I don't want three states, trying to whittle down to only two.
But I cant seem to nail it...
What ought I to be doing instead
(beware word-wrap)
(defun loadblock(s)
(defvar n 0)
(loop for line = (read-line *standard-input* nil)
while line
do
(let
((x (length (string-trim '(#\Space) line)))
(y (search s (string-downcase line)))); end let
(cond
((and (= n 0) (> x 0) (numberp y) (char/= (char line 0) #\Tab))
(write-line line)
(setf n 1))
((and (= n 1) (or (= x 0) (and ((> x 0) (char= (char line 0) #\Tab)))))
(write-line line)
(setf n 0))
); end cond
); end do
) ; end loop
) ; end loadblock
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/8/2011 11:40:20 PM
|
|
On Feb 8, 3:40=A0pm, mss <m...@dev.null> wrote:
> TheFlyingDutchman wrote:
> > In this Ruby code you appear to have two states - =A0"MATCHED_BLOCK"
> > "NON_MATCHED_BLOCK"
>
> > In your Common Lisp code you appear to have three states. What are the
> > three states of the Common Lisp code?
>
> Good catch...
>
> I don't want three states, trying to whittle down to only two.
> But I cant seem to nail it...
>
> What ought I to be doing instead
>
> (beware word-wrap)
>
> (defun loadblock(s)
>
> =A0 =A0(defvar n 0)
>
> =A0 =A0(loop for line =3D (read-line *standard-input* nil)
>
> =A0 =A0 =A0 while line
>
> =A0 =A0 =A0 do
>
> =A0 =A0 =A0 =A0 =A0(let
> =A0 =A0 =A0 =A0 =A0 =A0 ((x (length (string-trim '(#\Space) line)))
> =A0 =A0 =A0 =A0 =A0 =A0 (y (search s (string-downcase line)))); end let
>
> =A0 =A0 =A0 =A0 =A0(cond
>
> =A0 =A0 =A0 =A0 =A0 =A0 ((and (=3D n 0) (> x 0) (numberp y) (char/=3D (ch=
ar line 0) #\Tab))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(write-line line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(setf n 1))
>
> =A0 =A0 =A0 =A0 =A0 =A0((and (=3D n 1) (or (=3D x 0) (and ((> x 0) (char=
=3D (char line 0) #\Tab)))))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(write-line line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(setf n 0))
>
> =A0 =A0 =A0 =A0 =A0); end cond
>
> =A0 =A0 =A0 ); end do
>
> =A0 =A0) ; end loop
>
> ) ; end loadblock
>
As in your Ruby code, you only want to set the state when you have
just read a "Orange, Fruit" type line. At that point you check if it
is a match:
yes - state =3D 1 (MATCHED_BLOCK)
no - state =3D 0 (NON_MATCHED_BLOCK)
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/9/2011 12:11:22 AM
|
|
This seems to work. However
1) I changed n to state and made some constants for state values and
then couldn't resist changing other one character variable names.
2) I don't know how to run this with SBCL with a file as standard
input so changed it to read a file on disk.
3) This doesn't look at any line as being an error. If the state is
matched, whatever follows until a non-matched header is reached, is
printed.
I don't know if you want to exclude any lines for being bogus.
4) Added #\Return to trim due to bug in SBCL for Windows.
(defconstant no_match 0)
(defconstant match 1)
(defun loadblock(search_string)
(let ( ( state no_match )
fInput
)
(setq fInput (open "test_uu.txt"))
(loop for line = (read-line fInput nil)
while line
do
(let
((trimmed_line_length
(length (string-trim '(#\Space #\Return) line)))
(string_match_position (search search_string
(string-downcase line)))) ; end let
; do we have a header line?
(if (and (> trimmed_line_length 0) (char/= (char line 0) #
\Tab))
; is it a match?
(if (not (null string_match_position))
(setf state match)
(setf state no_match)))
(if (= state match)
(write-line line))
); end let
); end loop
(close fInput)
) ; end let
) ; end loadblock
(write-line "apples --------------------")
(loadblock "apples")
(write-line "oranges --------------------")
(loadblock "oranges")
(write-line "fruit ----------------------")
(loadblock "fruit")
(write-line "bread --------------------")
(loadblock "bread")
(write-line "----------------------------")
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/9/2011 1:21:12 AM
|
|
Removed once-used variables and made it as close to using *standard-
input* as possible
; line not needed if *standard-input* works
(defvar -standard-input- (open "test_uu.txt"))
(defconstant +NO_MATCH+ 0)
(defconstant +MATCH+ 1)
(defun loadblock(search_string)
(let (
( state +NO_MATCH+ )
)
(loop for line = (read-line -standard-input- nil) ; should be
*standard-input*
while line
do
; do we have a header line?
(if (and (> (length (string-trim '(#\Space #\Return) line))
0)
(char/= (char line 0) #\Tab))
; is it a match?
(if (search search_string (string-downcase line))
(setf state +MATCH+)
(setf state +NO_MATCH+)))
(if (= state +MATCH+)
(write-line line))
); end loop
) ; end let
) ; end loadblock
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/9/2011 5:13:36 AM
|
|
> =A0 =A0 =A0 =A0 =A0; do we have a header line?
> =A0 =A0 =A0 =A0 =A0(if (and (> (length (string-trim '(#\Space #\Return) l=
ine))
> 0)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (char/=3D (char line 0) #\Tab))
The and tests should be the reverse for efficiency:
; do we have a header line?
(if (and (char/=3D (char line 0) #\Tab)
(> (length (string-trim '(#\Space #\Return) line))
0))
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/9/2011 5:45:29 AM
|
|
mss <mss@dev.null> writes:
> Here's my code. Its not fully formatted/indented as per Lisp
> conventions to give my self some elbow room (but it will be
> eventually).
I am sorry to say, but you are impudently prodding along a path that can
lead only to whatever you already know. If you keep this up, you will
end up finishing your program without having understood even the first
thing about Lisp. To you, it will be a programing language like any other
you already know, just with this funny and hard-to-get-right notation.
We lispers don't format/indent our code, our editors do it for us. We
also don't edit code line by line, but rather as complete sexp's. We
determine if we have got all parenthesis right by looking at the
indentation produced by our editors. Many of us don't even close our
parens by hand - we just have editor commands that take us a layer
outwards and forward - so we never even get to a point where our
parenthesis could become unbalanced. And that is just the editing of
code I am talking about here. Lisp allows to reason about programing on a
wholly different level from what could be useful in "mainstream"
languages. No enlightenment can come from toying around, one has to make
a conscious effort to learn and understand.
The sad thing is, very good pointers were provided to you from the very
start. As far as I can tell, you haven't even read the first chapter of
PCL (not counting the introduction). Why do you insist on wasting our
time, when you clearly don't intend to learn anything?
> ); end case
>
> ); end do
>
> ) ; end loop
>
> ) ; end function
>
> ;
--
A change in perspective is worth 80 IQ points. --- Alan Kay
|
|
0
|
|
|
|
Reply
|
Edmunds
|
2/9/2011 10:31:09 AM
|
|
TheFlyingDutchman wrote:
>> � � � � �; do we have a header line?
>> � � � � �(if (and (> (length (string-trim '(#\Space #\Return) line))
>> 0)
>> � � � � � � � � � (char/= (char line 0) #\Tab))
>
> The and tests should be the reverse for efficiency:
>
> ; do we have a header line?
> (if (and (char/= (char line 0) #\Tab)
> (> (length (string-trim '(#\Space #\Return) line))
> 0))
>
Very nice...
Stay tuned, I've incorporated your changes,
& will post them shortly!
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/9/2011 10:59:20 AM
|
|
mss <mss@dev.null> writes:
> Paul Rubin wrote:
>
>> If you seek programming advice on a newsgroup then you will probably
>> receive some. The advice in this case is to modify the spec rather than
>> implementing it directly. Perhaps that advice is not for you - problem
>> sloved [sic] no?
>
> The spec is fine, its a simple thing, that's all it has to be,
> and that's all its meant to be.
>
> Its not a matter of not appreciating your input, but you
> haven't really offered much more than flippant remarks
> (in your initial response at least).
>
> I'm always willing learn, and grateful for those whom
> take the time to explain what's on their minds. Yet, the
> spirit in which you offer up your thoughts makes me wary.
> I'm not into impressing others with great displays,
> I just want to build a parser for the spec in Lisp, and
> learn some Lisp along the way.
>
> So, what you'd do differently?
This reminds me of one of Erik's famous Perl rants, especially
"[...] Perl was created to solve those problems that were caused by
real and artificial stupidity -- file formats created by morons, log
files that were almost completely useless, idiotic incompatibilities
between programs, etc, whereas Common Lisp grew out of the problems of
artificial intelligence.[...]"
Parts skipped for not becoming too abusive :-)
Nicolas
|
|
0
|
|
|
|
Reply
|
Nicolas
|
2/9/2011 11:02:46 AM
|
|
Edmunds Cers wrote:
> I am sorry to say, but you are impudently prodding along a path that can
> lead only to whatever you already know. If you keep this up, you will
> end up finishing your program without having understood even the first
> thing about Lisp. To you, it will be a programing language like any other
> you already know, just with this funny and hard-to-get-right notation.
>
> We lispers don't format/indent our code, our editors do it for us. We
> also don't edit code line by line, but rather as complete sexp's. We
> determine if we have got all parenthesis right by looking at the
> indentation produced by our editors. Many of us don't even close our
> parens by hand - we just have editor commands that take us a layer
> outwards and forward - so we never even get to a point where our
> parenthesis could become unbalanced. And that is just the editing of
> code I am talking about here. Lisp allows to reason about programing on a
> wholly different level from what could be useful in "mainstream"
> languages. No enlightenment can come from toying around, one has to make
> a conscious effort to learn and understand.
>
> The sad thing is, very good pointers were provided to you from the very
> start. As far as I can tell, you haven't even read the first chapter of
> PCL (not counting the introduction). Why do you insist on wasting our
> time, when you clearly don't intend to learn anything?
You've jumped to conclusions Edmunds...
Advice: If its a waste of your time, then simply ignore
my posts & your irritation is gone.
I'll learn Lisp how & when, & in the manner that best
befits me, thank you kindly sir. Edmunds, I hope we
can be friends in the spirit of sharing knowledge,
if not, well, that's unfortunate, but I persevere
never-the-less. btw... I have read PCL.
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/9/2011 11:17:15 AM
|
|
TheFlyingDutchman wrote:
> The and tests should be the reverse for efficiency:
>
> ; do we have a header line?
> (if (and (char/= (char line 0) #\Tab)
> (> (length (string-trim '(#\Space #\Return) line))
> 0))
Thank you so much for taking the time to work
with me. I've really learnt alot with your help...
(The draft of the project is posted below)
I did not make the change you cited above.
Consider this...
The string should be checked for having length
greater than zero - before - checking for tab.
Also (very educational for me), I didn't know
that (let) could wrap a loop! As of last night,
I was on the same track as you, but had not quite
worked out.
There's one final step I must work out...
multiple tags are comma-delimited ie:
cat, dog, doghouse
So I still have some work to do, I must split
the tag string, else, false matches can occur,
for instance, searching for a tag containing 'd',
will match both 'dog, and 'doghouse'.
But I'm learning more all the time.
Once again, my earnest thanks to every one that has
offered their help. The way I learn is by asking questions,
reading/writing code, & scratching my head allot =)
At any rate, I'm sure enough humbled.
#!/usr/bin/env clisp
#|
Common Lisp TOPIC database parser
http://www.topcat.hypermart.net/index.html
Special thanks to:
TheFlyingDutchman, Rainer Joswig, Edmunds Cers, Rob Warnock, Thomas A. Russ,
Pascal J. Bourguignon, vanekl, Teemu Likonen, Antony, Frank Goenninger
nix invocation: clisp script.lsp $@ < file.input 2>> error.log
win invocation: clisp script.lsp $% < file.input 2>> error.log
|#
; ---------------------------------------------------------------------------
(defun indices()
(loop for line = (read-line *standard-input* nil)
while line
do (when (and (plusp (length (string-trim '(#\Space) line)))
(char/= (char line 0) #\Tab))
(write-line line)))
)
; ---------------------------------------------------------------------------
(defun loadblock(tag)
(defconstant +NO_MATCH+ 0)
(defconstant +MATCH+ 1)
(let((state +NO_MATCH+))
(loop for line = (read-line *standard-input* nil)
while line
do
; do we have a tag line?
(if (and (> (length (string-trim '(#\Space #\Return) line)) 0)
(char/= (char line 0) #\Tab))
; does it match?
(if (search tag (string-downcase line))
(setf state +MATCH+)
(setf state +NO_MATCH+)))
(if (= state +MATCH+)
(write-line line))
); end loop
); end let
)
; ---------------------------------------------------------------------------
(defun blurb()
(write "usage/syntax panel will be placed here")
)
; ---------------------------------------------------------------------------
(defun main()
(defvar tag (format nil "~{~(~a~)~^ ~}" *args*))
(cond ((= (length tag) 0) (blurb))
((string= tag "-i") (indices))
((loadblock tag)))
)
; ---------------------------------------------------------------------------
(main)
; eof
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/9/2011 11:33:41 AM
|
|
On Feb 9, 3:33=A0am, mss <m...@dev.null> wrote:
> TheFlyingDutchman wrote:
> > The and tests should be the reverse for efficiency:
>
> > =A0 =A0 =A0 =A0 =A0; do we have a header line?
> > =A0 =A0 =A0 =A0 =A0(if (and (char/=3D (char line 0) #\Tab)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (> (length (string-trim '(#\Space #=
\Return) line))
> > 0))
>
>
> I did not make the change you cited above.
>
> Consider this...
>
> The string should be checked for having length
> greater than zero - before - checking for tab.
Right. I would have gotten bitten by that in the test I ran were it
not for the fact that SBCL for Windows never gives you a 0 length line
from read-line. It always has at least #\Return in it.
>
> There's one final step I must work out...
>
> multiple tags are comma-delimited ie:
>
> cat, dog, doghouse
>
> So I still have some work to do, I must split
> the tag string, else, false matches can occur,
> for instance, searching for a tag containing 'd',
> will match both 'dog, and 'doghouse'.
If you only want full matches, that is, "dog" does not match
"doghouse" and "fruit" does not match "fruits" then this code might do
what you are looking for:
; from comp.lang.lisp archives: Yossarian
(defun split-string (delimiter string)
"Returns a list containing items in 'string' split from
occurrences of 'delimiter'."
(loop with l =3D (length delimiter)
for n =3D 0 then (+ pos l)
for pos =3D (search delimiter string :start2 n)
if pos collect (subseq string n pos)
else collect (subseq string n)
while pos
)
)
;--------------------------------------------------------------
(defun Matches (search_string string)
(let ( (tokenList (split-string "," string)) )
(loop for keyword in tokenList
do
(if (string=3D (string-trim '(#\Space) keyword) search_string)
(return-from Matches t)
))
nil
)
)
;--------------------------------------------------------------
(defun loadblock(search_string stream) ; eg. (loadblock "fruit"
*standard-input*)
(let* (
( MATCH 1 )
( NO_MATCH 0 )
( strLine "")
( state NO_MATCH )
)
(loop for line =3D (read-line stream nil)
while line
do
; due to SBCL Windows bug:
(setq strLine (string-trim '(#\Return) line))
; do we have a header line?
(if (and (> (length (string-trim '(#\Space #\Return) line))
0)
(char/=3D (char line 0) #\Tab))
; is it a match?
(if (Matches search_string (string-downcase strLine))
(setf state MATCH)
(setf state NO_MATCH)
)
)
(if (=3D state MATCH)
(write-line line))
); end loop
) ; end let
) ; end loadblock
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/9/2011 1:29:20 PM
|
|
On 2011-02-09 06:17:15 -0500, mss said:
> I'll learn Lisp how & when, & in the manner that best
> befits me, thank you kindly sir.
Then we'll help you how & when & in the manner that best befits us,
which is to say, going forward we're quite likely to treat you as a
stubborn nub, on his way to becoming yet another c.l.l troll.
When you ask others for help, it behooves you to take their advice, or
future requests for help are likely to be ignored.
Just to be 100% clear, you need to learn the basics of the language
before attempting to port a program for some random, ill-conceived file
format. If you learn the basics of the language, you'll discover, as
others have told you, that that odd file format isn't necessary for
storing data using lisp and/or that if you absolutely must read files
in that format, there are better ways to parse it than naively
translating an existing program from another language. That's why you
need to read PCL or one of the other introductory texts that have been
suggested.
warmest regards,
Ralph
--
Raffael Cavallaro
|
|
0
|
|
|
|
Reply
|
Raffael
|
2/9/2011 2:25:45 PM
|
|
>
> (defun main()
>
> =A0 =A0 (defvar tag =A0(format nil "~{~(~a~)~^ ~}" *args*))
>
> =A0 =A0 (cond ((=3D (length tag) 0) (blurb))
> =A0 =A0 =A0 =A0 =A0 ((string=3D tag "-i") (indices))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ((loadblock tag)))
>
> )
Both (indices) and (loadblock) loop all the way through *standard-
input*. As you read through *standard-input* with read-line, the file-
position will advance. In order for the second read loop to work I
think you are going to have to reset the file-position back to 0. With
a regular file stream, closing and then opening the file would do
that. Don't know if that works for *standard-input* or if there is an
alternative way to do it.
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/9/2011 2:32:44 PM
|
|
Ahh, thanks. I'll get these into the project asap...
Lisp was some really great methods for dealing with
loops, simply blows my mind at breadth of ways:
<http://www.gigamonkeys.com/book/loop-for-black-belts.html>
TheFlyingDutchman wrote:
> If you only want full matches, that is, "dog" does not match
> "doghouse" and "fruit" does not match "fruits" then this code might do
> what you are looking for:
>
> ; from comp.lang.lisp archives: Yossarian
> (defun split-string (delimiter string)
> "Returns a list containing items in 'string' split from
> occurrences of 'delimiter'."
> (loop with l = (length delimiter)
> for n = 0 then (+ pos l)
> for pos = (search delimiter string :start2 n)
> if pos collect (subseq string n pos)
> else collect (subseq string n)
> while pos
> )
> )
> ;--------------------------------------------------------------
> (defun Matches (search_string string)
> (let ( (tokenList (split-string "," string)) )
> (loop for keyword in tokenList
> do
> (if (string= (string-trim '(#\Space) keyword) search_string)
> (return-from Matches t)
> ))
> nil
> )
> )
> ;--------------------------------------------------------------
> (defun loadblock(search_string stream) ; eg. (loadblock "fruit"
> *standard-input*)
> (let* (
> ( MATCH 1 )
> ( NO_MATCH 0 )
> ( strLine "")
> ( state NO_MATCH )
> )
> (loop for line = (read-line stream nil)
> while line
> do
> ; due to SBCL Windows bug:
> (setq strLine (string-trim '(#\Return) line))
> ; do we have a header line?
> (if (and (> (length (string-trim '(#\Space #\Return) line))
> 0)
> (char/= (char line 0) #\Tab))
> ; is it a match?
> (if (Matches search_string (string-downcase strLine))
> (setf state MATCH)
> (setf state NO_MATCH)
> )
> )
> (if (= state MATCH)
> (write-line line))
> ); end loop
> ) ; end let
> ) ; end loadblock
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/9/2011 3:37:17 PM
|
|
TheFlyingDutchman wrote:
>>
>> (defun main()
>>
>> � � (defvar tag �(format nil "~{~(~a~)~^ ~}" *args*))
>>
>> � � (cond ((= (length tag) 0) (blurb))
>> � � � � � ((string= tag "-i") (indices))
>> � � � � � � � � � ((loadblock tag)))
>>
>> )
>
> Both (indices) and (loadblock) loop all the way through *standard-
> input*. As you read through *standard-input* with read-line, the file-
> position will advance. In order for the second read loop to work I
> think you are going to have to reset the file-position back to 0. With
> a regular file stream, closing and then opening the file would do
> that. Don't know if that works for *standard-input* or if there is an
> alternative way to do it.
Err... I'm not sure I understand you here.
I want to loop through the entire stream (once per invocation of the
script), because matching tags may not be contiguous/adjacent:
house
block line
block line
boat
block line
block line
shop, house
block line
block line
Or maybe you're referring to (cond) instead?
My understanding of (cond) is taken from:
<http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node84.html>
'The first clause whose test evaluates to non-nil is selected; all other
clauses are ignored, and the consequents of the selected clause are
evaluated in order (as an implicit progn).'
Or maybe still, I've misunderstood completely?
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/9/2011 3:47:41 PM
|
|
mss <mss@dev.null> writes:
You can forget about puting end comments:
>> ); end loop
>> ) ; end let
>> ) ; end loadblock
I did that too when I first started writing in Lisp, because it was my
coding style in all other language (under influence from Modula-2).
BUT, Lisp is more concise a language, therefore there's really no need
to mark the end of blocks because blocks are short enough to fit one
screenful (or perhaps nowadays, I should say short enough to fit the
macula even).
You can write:
(defun matches (search-string string)
(loop
:with token-list = (split-string "," string)
:for keyword :in token-list
:thereis (string= (string-trim '(#\Space) keyword) search-string)))
By default LOOP returns NIL.
But you could also write:
(defun matches (search-string string)
(find search-string (split-string "," string)
:test (function string=)
:key (lambda (keyword) (string-trim '(#\Space) keyword))))
or:
(defun matches (search-string string)
(find-if (lambda (keyword) (string= (string-trim '(#\Space) keyword) search-string))
(split-string "," string)))
which shows you how useless ");end thing" are.
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
Pascal
|
2/9/2011 4:18:42 PM
|
|
Pascal J. Bourguignon wrote:
> mss <mss@dev.null> writes:
>
> You can forget about puting end comments:
>
>>> ); end loop
>>> ) ; end let
>>> ) ; end loadblock
>
> I did that too when I first started writing in Lisp, because it was my
> coding style in all other language (under influence from Modula-2).
>
> BUT, Lisp is more concise a language, therefore there's really no need
> to mark the end of blocks because blocks are short enough to fit one
> screenful (or perhaps nowadays, I should say short enough to fit the
> macula even).
>
> You can write:
>
> (defun matches (search-string string)
> (loop
> :with token-list = (split-string "," string)
> :for keyword :in token-list
> :thereis (string= (string-trim '(#\Space) keyword) search-string)))
>
> By default LOOP returns NIL.
>
> But you could also write:
>
> (defun matches (search-string string)
> (find search-string (split-string "," string)
> :test (function string=)
> :key (lambda (keyword) (string-trim '(#\Space) keyword))))
>
> or:
>
> (defun matches (search-string string)
> (find-if (lambda (keyword) (string= (string-trim '(#\Space) keyword) search-string))
> (split-string "," string)))
>
> which shows you how useless ");end thing" are.
True enough, I find I'm having to 'un-learn'
some things, & re-learn then anew.
Its really a great thing discovering all that
Lisp can do!
Tell me, why do you think of the book titled:
Winston and Horn's "Lisp" ?
I've been waiting for it (impatiently) to arrive
for two weeks now...
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/9/2011 5:02:43 PM
|
|
mss <mss@dev.null> writes:
> Tell me, why do you think of the book titled:
>
> Winston and Horn's "Lisp" ?
>
> I've been waiting for it (impatiently) to arrive
> for two weeks now...
The third edition seemed pretty nice to me, though by the time I got it,
I had already read Paradigms of AI Programming and Practical Common
Lisp, so I didn't study it very closely. It covers CLOS and other useful
things.
I've heard the first and second editions are pretty antiquated, but I've
never seen them.
Zach
|
|
0
|
|
|
|
Reply
|
Zach
|
2/9/2011 5:04:34 PM
|
|
mss <mss@dev.null> writes:
> Edmunds Cers wrote:
>> The sad thing is, very good pointers were provided to you from the very
>> start. As far as I can tell, you haven't even read the first chapter of
>> PCL (not counting the introduction). Why do you insist on wasting our
>> time, when you clearly don't intend to learn anything?
>
> You've jumped to conclusions Edmunds...
>
> Advice: If its a waste of your time, then simply ignore
> my posts & your irritation is gone.
>
> I'll learn Lisp how & when, & in the manner that best
> befits me, thank you kindly sir. Edmunds, I hope we
> can be friends in the spirit of sharing knowledge,
> if not, well, that's unfortunate, but I persevere
> never-the-less. btw... I have read PCL.
Sometimes its hard not to jump to conclusions.
As a long time reader (but rare poster) to this group, there is a common
pattern.
Someone new comes to the group, enthusiastic about Lisp, and asks advice
about something, usually giving some code they have written.
The first round of advice is usually a list of good books teaching Lisp,
some useful improvements to their code, and some other (seemingly)
tedious advice about how they should format their code, choice of
variable names, and give fine distinctions that need to be observed
in writing code.
Ignoring the latter, the person focuses in on translating concepts they
have used in other languages into Lisp. They feel there is plenty of
time to deal with fine points later.
However, when asking questions, people in the group seem to be obsessed
with these fine points, while the newcomer is more interested in why it
seems to so hard to express in Lisp those things that seem much easier
in other languages.
Gradually they start to feel that Lisp is not a very expressive
language, and loose interest in it. They carry with them a strong
dislike for Lisp. Some even remain here a while posting negative
remarks.
People that like Lisp become frustrated that Lisp was never given a fair
evaluation. The way one writes and structures their code can help avoid
common pitfalls, not all of which are unique to Lisp. Some are just
taken for granted in some other languages, such as the complexity of
tracking the values of local variables.
Each language brings with it a set of basic features and ways of
combining these features into programs. Although any languages can be
used to solve a given problem, a given solution might be difficult in
one and complex in another. When ones grab-bag of approaches from a
language doesn't fit in the new language, it is tempting to say its the
fault of the new language.
However, the ultimate test of whether a language is useful to you, is
whether it can simply and efficiently solve the problems you want to
solve. This is why many times people here ask for a formal problem
statement rather than just help with the way others have chosen to solve
their problem. Much of the benefit of Lisp (to me anyway) is that
rather then supplying a single framework that works on a class of
problems but fails in others, it supplies a easy way to construct a
framework in which to solve a given problem, and is reusable for a whole
class of similar problems. This sometimes makes the solution of a
simple example problem seem overly verbose. Most people, like me, who
use lisp even in simple scripts, write and collect packages that supply
such frameworks. I find my Common Lisp scripts are about the same size,
and often shorter than my equivalent scripts in other languages, and
easier for me to maintain.
Its the ease of maintenance that is crucial to me. Most scripts start
life as solutions to a particular problem, and grow as the are adapted
to more general problems. Lisp is particularly easy to restructure, and
add functionality. With languages like Perl, I found that when a
certain level of complexity was reached the script needed to be
rewritten from scratch, and there was a level of complexity beyond which
things became very difficult. Python is better than Perl at evolving
functionality, has a great grab-bag of features, but is difficult to
restructure, even in Emacs. Of course these conclusions are very
subjective, and probably don't apply to everyone. I also have control
over how I store my data, although I tend not to use s-expressions and I
can't just avoid XML.
When I started to learn Lisp I shared some of the above frustrations.
However, I took the advice of quickly adopting the common formatting
rules. I had already used Emacs for C++. This made reading other
peoples code much easier. It was the reading of other peoples code that
had the biggest impact on my understanding of how to write Lisp. This
group was (and is) very helpful in the threads that take a programming
problem, and look at multiple ways of implementing it, often reaching
simpler and more elegant solutions. It is also useful in learning why
things are the way they are.
--
Barry Fishman
|
|
0
|
|
|
|
Reply
|
Barry
|
2/9/2011 5:19:06 PM
|
|
Raffael Cavallaro wrote:
> On 2011-02-09 06:17:15 -0500, mss said:
>
>> I'll learn Lisp how & when, & in the manner that best
>> befits me, thank you kindly sir.
>
> Then we'll help you how & when & in the manner that best befits us,
> which is to say, going forward we're quite likely to treat you as a
> stubborn nub, on his way to becoming yet another c.l.l troll.
>
> When you ask others for help, it behooves you to take their advice, or
> future requests for help are likely to be ignored.
>
> Just to be 100% clear, you need to learn the basics of the language
> before attempting to port a program for some random, ill-conceived file
> format. If you learn the basics of the language, you'll discover, as
> others have told you, that that odd file format isn't necessary for
> storing data using lisp and/or that if you absolutely must read files
> in that format, there are better ways to parse it than naively
> translating an existing program from another language. That's why you
> need to read PCL or one of the other introductory texts that have been
> suggested.
Yes indeed, I both understand the good-will & appreciate the help
I've been offered. Further, I respect the time the more
seasoned here have put in learning the language.
To one & all:
Thank you for your help. I'm learning Lisp by-and-by.
Its evident to all here, I don't yet possess a fluency in Lisp,
& good advice does not fall on death ears on my end. But
with respect to the 'ill-conceived file format' it simply
serves as a vehicle for me to LEARN Lisp. I can convert
my efforts in another language towards Lisp & gain more
understanding. See?
Bottom line: I try to respect others, & would never try
to approach another with the intent of belittling them.
Yet when I sense disrespect from others towards myself,
I'll deal with it.
Thank you for reading.
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/9/2011 5:40:11 PM
|
|
This is an excellent post.
I'm want to learn, but can only do it, well, in the way I learn,
whatever that is...
Honestly don't want to ruffle any feathers, but I can jump
to conclusions too: I have visions of long-time Lisp users
berating my every move. Cant they/I just relax & roll with it?
It *will* take me a very long time to synthesize the
idioms Lisp offers. I have no formal training in anything
excepting the hard knocks of life =)
What can I say except, that I came here trying to learn,
but some folks keep getting upset - I'll work on reading
more, but it takes time for me.
And with that, I'll get off my soap-box now.
Barry Fishman wrote:
>
> Sometimes its hard not to jump to conclusions.
>
> As a long time reader (but rare poster) to this group, there is a common
> pattern.
>
> Someone new comes to the group, enthusiastic about Lisp, and asks advice
> about something, usually giving some code they have written.
>
> The first round of advice is usually a list of good books teaching Lisp,
> some useful improvements to their code, and some other (seemingly)
> tedious advice about how they should format their code, choice of
> variable names, and give fine distinctions that need to be observed
> in writing code.
>
> Ignoring the latter, the person focuses in on translating concepts they
> have used in other languages into Lisp. They feel there is plenty of
> time to deal with fine points later.
>
> However, when asking questions, people in the group seem to be obsessed
> with these fine points, while the newcomer is more interested in why it
> seems to so hard to express in Lisp those things that seem much easier
> in other languages.
>
> Gradually they start to feel that Lisp is not a very expressive
> language, and loose interest in it. They carry with them a strong
> dislike for Lisp. Some even remain here a while posting negative
> remarks.
>
>
> People that like Lisp become frustrated that Lisp was never given a fair
> evaluation. The way one writes and structures their code can help avoid
> common pitfalls, not all of which are unique to Lisp. Some are just
> taken for granted in some other languages, such as the complexity of
> tracking the values of local variables.
>
> Each language brings with it a set of basic features and ways of
> combining these features into programs. Although any languages can be
> used to solve a given problem, a given solution might be difficult in
> one and complex in another. When ones grab-bag of approaches from a
> language doesn't fit in the new language, it is tempting to say its the
> fault of the new language.
>
> However, the ultimate test of whether a language is useful to you, is
> whether it can simply and efficiently solve the problems you want to
> solve. This is why many times people here ask for a formal problem
> statement rather than just help with the way others have chosen to solve
> their problem. Much of the benefit of Lisp (to me anyway) is that
> rather then supplying a single framework that works on a class of
> problems but fails in others, it supplies a easy way to construct a
> framework in which to solve a given problem, and is reusable for a whole
> class of similar problems. This sometimes makes the solution of a
> simple example problem seem overly verbose. Most people, like me, who
> use lisp even in simple scripts, write and collect packages that supply
> such frameworks. I find my Common Lisp scripts are about the same size,
> and often shorter than my equivalent scripts in other languages, and
> easier for me to maintain.
>
> Its the ease of maintenance that is crucial to me. Most scripts start
> life as solutions to a particular problem, and grow as the are adapted
> to more general problems. Lisp is particularly easy to restructure, and
> add functionality. With languages like Perl, I found that when a
> certain level of complexity was reached the script needed to be
> rewritten from scratch, and there was a level of complexity beyond which
> things became very difficult. Python is better than Perl at evolving
> functionality, has a great grab-bag of features, but is difficult to
> restructure, even in Emacs. Of course these conclusions are very
> subjective, and probably don't apply to everyone. I also have control
> over how I store my data, although I tend not to use s-expressions and I
> can't just avoid XML.
>
> When I started to learn Lisp I shared some of the above frustrations.
> However, I took the advice of quickly adopting the common formatting
> rules. I had already used Emacs for C++. This made reading other
> peoples code much easier. It was the reading of other peoples code that
> had the biggest impact on my understanding of how to write Lisp. This
> group was (and is) very helpful in the threads that take a programming
> problem, and look at multiple ways of implementing it, often reaching
> simpler and more elegant solutions. It is also useful in learning why
> things are the way they are.
>
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/9/2011 5:58:37 PM
|
|
Zach Beane wrote:
> mss <mss@dev.null> writes:
>
>> Tell me, why do you think of the book titled:
>>
>> Winston and Horn's "Lisp" ?
>>
>> I've been waiting for it (impatiently) to arrive
>> for two weeks now...
>
> The third edition seemed pretty nice to me, though by the time I got it,
> I had already read Paradigms of AI Programming and Practical Common
> Lisp, so I didn't study it very closely. It covers CLOS and other useful
> things.
>
> I've heard the first and second editions are pretty antiquated, but I've
> never seen them.
Well, this is a good sign. CLOS... gosh, I'm miles from that goal yet!
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/9/2011 6:00:46 PM
|
|
On Feb 9, 7:47=A0am, mss <m...@dev.null> wrote:
> TheFlyingDutchman wrote:
>
> >> (defun main()
>
> >> (defvar tag (format nil "~{~(~a~)~^ ~}" *args*))
>
> >> (cond ((=3D (length tag) 0) (blurb))
> >> ((string=3D tag "-i") (indices))
> >> ((loadblock tag)))
>
> >> )
>
> > Both (indices) and (loadblock) loop all the way through *standard-
> > input*. =A0As you read through *standard-input* with read-line, the fil=
e-
> > position will advance. In order for the second read loop to work I
> > think you are going to have to reset the file-position back to 0. With
> > a regular file stream, closing and then opening the file would do
> > that. Don't know if that works for *standard-input* or if there is an
> > alternative way to do it.
>
> Err... I'm not sure I understand you here.
> Or maybe you're referring to (cond) instead?
>
> My understanding of (cond) is taken from:
> ini
> <http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node84.html>
>
> 'The first clause whose test evaluates to non-nil is selected; all other
> clauses are ignored, and the consequents of the selected clause are
> evaluated in order (as an implicit progn).'
>
> Or maybe still, I've misunderstood completely?
No, my bad. I looked at the cond and thought that it had two
conditions and the second one was going to execute both indices and
loadblock.
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/9/2011 11:21:00 PM
|
|
On Feb 8, 11:14=A0pm, mss <m...@dev.null> wrote:
> Marco Antoniotti wrote:
> > That is pretty impressive given that we still don't know what we are
> > supposed to parse :)
>
> Chuckle, my bad Marco. The specs along with parsers
> in several languages are here:
>
> <http://www.topcat.hypermart.net/topic.html>
>
> If you can help with the lisp version, feel free to jump in.
>
Ok. Here it is, although (1) it may be buggy and cleanable and (2) it
will *NEVER* swat away the SLDJ pests buzzing around here :)
(defstruct topic
tags
block)
(defun load-topics (topic-file &rest tags)
(with-open-file (tf topic-file
:direction :input)
(let ((topic-blocks ()))
(labels ((start ()
(loop for line =3D (read-line tf nil nil)
do (format t ">> ~S~%" line)
while (and line
(or (string=3D "" line)
(every #'whitespace-char-p
line)))
finally (if line
(parse-tags line)
(finish-topic-file))))
(parse-tags (line)
(let ((parsed-tags (split-sequence '(#\,) line ; May
need to load this.
:coalesce-
separators t)))
(if (intersection parsed-tags tags :test #'string-
equal)
(parse-collect-block parsed-tags)
(skip-block))))
(skip-block ()
(loop for line =3D (read-line tf nil nil)
while line
unless (or (string=3D "" line)
(every #'whitespace-char-p line))
when (char/=3D #\Tab (char line 0))
do (loop-finish)
finally (if line
(parse-tags line)
(finish-topic-file))))
(parse-collect-block (parsed-tags)
(loop for line =3D (read-line tf nil nil)
while line
unless (or (string=3D "" line)
(every #'whitespace-char-p line))
if (char=3D #\Tab (char line 0))
collect (subseq line 1) into topic-block
else do (loop-finish)
finally (cond (line
(push (make-topic
:tags parsed-tags
:block topic-block)
topic-blocks)
(parse-tags line))
(t
(finish-topic-file)))))
(finish-topic-file ()
(return-from load-topics topic-blocks))
)
(start)))))
Cheers
--
Marco
|
|
0
|
|
|
|
Reply
|
Marco
|
2/10/2011 12:24:15 PM
|
|
TheFlyingDutchman wrote:
>> Or maybe still, I've misunderstood completely?
>
> No, my bad. I looked at the cond and thought that it had two
> conditions and the second one was going to execute both indices and
> loadblock.
Shoot, no biggie Dutch.
Okay, 1st more or less complete version up
at my site for GNU CLISP (see sig link).
Appericate it, & look forward to learning
more.
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/10/2011 1:53:16 PM
|
|
This is a great effort Marco, (thank you for sharing).
Let me study this awhile, I'm still new to Lisp
as you know. So, It will take me awhile. =)
Question for you (& others):
How did you guys discover Lisp?
Marco Antoniotti wrote:
> Ok. Here it is, although (1) it may be buggy and cleanable and (2) it
> will *NEVER* swat away the SLDJ pests buzzing around here :)
>
>
> (defstruct topic
> tags
> block)
>
> (defun load-topics (topic-file &rest tags)
> (with-open-file (tf topic-file
> :direction :input)
> (let ((topic-blocks ()))
> (labels ((start ()
> (loop for line = (read-line tf nil nil)
> do (format t ">> ~S~%" line)
> while (and line
> (or (string= "" line)
> (every #'whitespace-char-p
> line)))
> finally (if line
> (parse-tags line)
> (finish-topic-file))))
>
> (parse-tags (line)
> (let ((parsed-tags (split-sequence '(#\,) line ; May
> need to load this.
> :coalesce-
> separators t)))
> (if (intersection parsed-tags tags :test #'string-
> equal)
> (parse-collect-block parsed-tags)
> (skip-block))))
>
> (skip-block ()
> (loop for line = (read-line tf nil nil)
> while line
> unless (or (string= "" line)
> (every #'whitespace-char-p line))
> when (char/= #\Tab (char line 0))
> do (loop-finish)
> finally (if line
> (parse-tags line)
> (finish-topic-file))))
>
> (parse-collect-block (parsed-tags)
> (loop for line = (read-line tf nil nil)
> while line
> unless (or (string= "" line)
> (every #'whitespace-char-p line))
> if (char= #\Tab (char line 0))
> collect (subseq line 1) into topic-block
> else do (loop-finish)
> finally (cond (line
> (push (make-topic
> :tags parsed-tags
> :block topic-block)
> topic-blocks)
> (parse-tags line))
> (t
> (finish-topic-file)))))
>
> (finish-topic-file ()
> (return-from load-topics topic-blocks))
> )
> (start)))))
>
> Cheers
> --
> Marco
>
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/10/2011 1:56:27 PM
|
|
On Feb 10, 2:56=A0pm, mss <m...@dev.null> wrote:
> This is a great effort Marco, (thank you for sharing).
>
> Let me study this awhile, I'm still new to Lisp
> as you know. So, It will take me awhile. =3D)
Feel free to ask questions. Essentially the idea is to use LABELS to
build a Finite State Automata (or a Recursive Descent Parser :) ).
Each "label" (a 'letrec' in other functional languages) names a
"state".
>
> Question for you (& others):
>
> How did you guys discover Lisp?
VLisp on a Z8000 (which then became LeLisp), then onto Scheme and
Franz Lisp (yep; there was such a thing) and finally half-heartedly
but lazily to Common Lisp, starting with the original KCL. Nowadays I
mostly live, for the joy of some brits, in Lispworks.
Never touched a Lisp Machine (which, in retrospect, and here is a HUGE
flame bait :), is a good thing :) ).
Cheers
--
Marco
>
>
>
>
>
>
>
>
>
> Marco Antoniotti wrote:
> > Ok. =A0Here it is, although (1) it may be buggy and cleanable and (2) i=
t
> > will *NEVER* swat away the SLDJ pests buzzing around here :)
>
> > (defstruct topic
> > =A0 tags
> > =A0 block)
>
> > (defun load-topics (topic-file &rest tags)
> > =A0 (with-open-file (tf topic-file
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 :direction :input)
> > =A0 =A0 (let ((topic-blocks ()))
> > =A0 =A0 =A0 (labels ((start ()
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop for line =3D (read-line tf nil=
nil)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0do (format t ">> ~S~%" l=
ine)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while (and line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (or=
(string=3D "" line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 (every #'whitespace-char-p
> > line)))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (if line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
(parse-tags line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
(finish-topic-file))))
>
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(parse-tags (line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((parsed-tags (split-sequence '=
(#\,) line ; May
> > need to load this.
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 :coalesce-
> > separators t)))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(if (intersection parsed-tags ta=
gs :test #'string-
> > equal)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(parse-collect-block par=
sed-tags)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(skip-block))))
>
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(skip-block ()
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop for line =3D (read-line tf nil=
nil)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unless (or (string=3D ""=
line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (ev=
ery #'whitespace-char-p line))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0when (char/=3D #\Tab (ch=
ar line 0))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0do (loop-finish)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (if line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
(parse-tags line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
(finish-topic-file))))
>
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(parse-collect-block (parsed-tags)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop for line =3D (read-line tf nil=
nil)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unless (or (string=3D ""=
line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (ev=
ery #'whitespace-char-p line))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (char=3D #\Tab (char =
line 0))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0collect (subseq line 1) =
into topic-block
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else do (loop-finish)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (cond (line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 (push (make-topic
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 =A0:tags parsed-tags
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 =A0:block topic-block)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 topic-blocks)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 (parse-tags line))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0(t
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 (finish-topic-file)))))
>
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(finish-topic-file ()
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(return-from load-topics topic-block=
s))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0)
> > =A0 =A0 =A0 =A0 (start)))))
>
> > Cheers
> > --
> > Marco
>
> --
> later on,
> Mike
>
> http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
Marco
|
2/10/2011 2:15:24 PM
|
|
mss <mss@dev.null> writes:
> How did you guys discover Lisp?
There is an excellent survey including many prominent Lispers here:
http://wiki.alu.org/The%20Road%20to%20Lisp%20Survey
--
A change in perspective is worth 80 IQ points. --- Alan Kay
|
|
0
|
|
|
|
Reply
|
Edmunds
|
2/10/2011 2:23:29 PM
|
|
mss <mss@dev.null> writes:
> This is a great effort Marco, (thank you for sharing).
>
> Let me study this awhile, I'm still new to Lisp
> as you know. So, It will take me awhile. =)
>
> Question for you (& others):
>
> How did you guys discover Lisp?
http://www.cliki.net/The%20Road%20to%20Lisp%20Survey
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
Pascal
|
2/10/2011 8:03:51 PM
|
|
Marco Antoniotti <marcoxa@gmail.com> writes:
> On Feb 8, 11:14 pm, mss <m...@dev.null> wrote:
>> Marco Antoniotti wrote:
>> > That is pretty impressive given that we still don't know what we are
>> > supposed to parse :)
>>
>> Chuckle, my bad Marco. The specs along with parsers
>> in several languages are here:
>>
>> <http://www.topcat.hypermart.net/topic.html>
>>
>> If you can help with the lisp version, feel free to jump in.
>>
>
> Ok. Here it is, although (1) it may be buggy and cleanable and (2) it
> will *NEVER* swat away the SLDJ pests buzzing around here :)
>
I took the liberty of cleaning it up a bit, although I did not test it:
(defstruct topic
tags
block)
(defun load-topics (topic-file &rest tags)
(with-open-file (tf topic-file :direction :input)
(load-topics-from-stream tf tags)))
(defun load-topics-from-stream (tf tags)
(let ((topic-blocks '())
(line nil)
(blank-line nil)
(indented-line nil))
(labels ((consume ()
(when (null (setq line (read-line tf nil nil)))
(return-from load-topics-from-stream
(nreverse topic-blocks)))
(setq blank-line (every #'whitespace-char-p line))
(setq indented-line (and (not blank-line)
(char= #\Tab (char line 0)))))
(consume-until-tags ()
(loop do (consume) while (or blank-line indented-line)))
(consume-topic (tags)
(loop do (consume)
when indented-line
collect (subseq line 1) into topic-block
while (or blank-line indented-line)
finally (collect-topic tags topic-block)))
(collect-topic (tags block)
(push (make-topic :tags tags :block block) topic-blocks)))
(loop
(consume-until-tags)
(let ((parsed-tags (split-sequence #\, line :coalesce-separators t)))
(when (intersection parsed-tags tags :test #'string-equal)
(consume-topic parsed-tags)))))))
Ariel
|
|
0
|
|
|
|
Reply
|
Ariel
|
2/10/2011 10:59:24 PM
|
|
On Feb 10, 4:24=A0am, Marco Antoniotti <marc...@gmail.com> wrote:
> On Feb 8, 11:14=A0pm, mss <m...@dev.null> wrote:
>
> > Marco Antoniotti wrote:
> > > That is pretty impressive given that we still don't know what we are
> > > supposed to parse :)
>
> > Chuckle, my bad Marco. The specs along with parsers
> > in several languages are here:
>
> > <http://www.topcat.hypermart.net/topic.html>
>
> > If you can help with the lisp version, feel free to jump in.
>
> Ok. =A0Here it is, although (1) it may be buggy and cleanable and (2) it
> will *NEVER* swat away the SLDJ pests buzzing around here :)
>
> (defstruct topic
> =A0 tags
> =A0 block)
>
> (defun load-topics (topic-file &rest tags)
> =A0 (with-open-file (tf topic-file
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 :direction :input)
> =A0 =A0 (let ((topic-blocks ()))
> =A0 =A0 =A0 (labels ((start ()
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop for line =3D (read-line tf nil n=
il)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0do (format t ">> ~S~%" lin=
e)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while (and line
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (or (=
string=3D "" line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 (every #'whitespace-char-p
> line)))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (if line
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(p=
arse-tags line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(f=
inish-topic-file))))
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(parse-tags (line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((parsed-tags (split-sequence '(#=
\,) line ; May
> need to load this.
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 :coalesce-
> separators t)))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(if (intersection parsed-tags tags=
:test #'string-
> equal)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(parse-collect-block parse=
d-tags)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(skip-block))))
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(skip-block ()
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop for line =3D (read-line tf nil n=
il)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while line
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unless (or (string=3D "" l=
ine)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (ever=
y #'whitespace-char-p line))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0when (char/=3D #\Tab (char=
line 0))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0do (loop-finish)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (if line
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(p=
arse-tags line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(f=
inish-topic-file))))
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(parse-collect-block (parsed-tags)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop for line =3D (read-line tf nil n=
il)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while line
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unless (or (string=3D "" l=
ine)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (ever=
y #'whitespace-char-p line))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (char=3D #\Tab (char li=
ne 0))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0collect (subseq line 1) in=
to topic-block
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else do (loop-finish)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (cond (line
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 (push (make-topic
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0:tags parsed-tags
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0:block topic-block)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 topic-blocks)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 (parse-tags line))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0(t
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 (finish-topic-file)))))
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(finish-topic-file ()
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(return-from load-topics topic-blocks)=
)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0)
> =A0 =A0 =A0 =A0 (start)))))
>
I found whitespace-char-p on the Lispworks site. Is that the source of
the one you are using?
http://www.lispworks.com/documentation/lw51/LWRM/html/lwref-385.htm
-----------
Description
This predicate recognizes [whitespace1] , as described in the
standard:
"Space and non-graphic characters that only moved the print position."
If sys:*extended-spaces* is t , U+3000 Ideographic Space is also
considered whitespace.
------------
I Googled whitespace1 but didn't find what it covers.
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/11/2011 7:55:49 AM
|
|
On Feb 10, 11:59=A0pm, Ariel Badichi <vermilionr...@gmail.com> wrote:
> Marco Antoniotti <marc...@gmail.com> writes:
> > On Feb 8, 11:14=A0pm, mss <m...@dev.null> wrote:
> >> Marco Antoniotti wrote:
> >> > That is pretty impressive given that we still don't know what we are
> >> > supposed to parse :)
>
> >> Chuckle, my bad Marco. The specs along with parsers
> >> in several languages are here:
>
> >> <http://www.topcat.hypermart.net/topic.html>
>
> >> If you can help with the lisp version, feel free to jump in.
>
> > Ok. =A0Here it is, although (1) it may be buggy and cleanable and (2) i=
t
> > will *NEVER* swat away the SLDJ pests buzzing around here :)
>
> I took the liberty of cleaning it up a bit, although I did not test it:
>
> (defstruct topic
> =A0 tags
> =A0 block)
>
> (defun load-topics (topic-file &rest tags)
> =A0 (with-open-file (tf topic-file :direction :input)
> =A0 =A0 (load-topics-from-stream tf tags)))
>
> (defun load-topics-from-stream (tf tags)
> =A0 (let ((topic-blocks '())
> =A0 =A0 =A0 =A0 (line nil)
> =A0 =A0 =A0 =A0 (blank-line nil)
> =A0 =A0 =A0 =A0 (indented-line nil))
> =A0 =A0 (labels ((consume ()
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(when (null (setq line (read-line tf nil n=
il)))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(return-from load-topics-from-stream
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(nreverse topic-blocks)))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(setq blank-line (every #'whitespace-char-=
p line))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(setq indented-line (and (not blank-line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 (char=3D #\Tab (char line 0)))))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0(consume-until-tags ()
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop do (consume) while (or blank-line in=
dented-line)))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0(consume-topic (tags)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop do (consume)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0when indented-line
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0collect (subseq line 1) into t=
opic-block
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while (or blank-line indented-=
line)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (collect-topic tags to=
pic-block)))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0(collect-topic (tags block)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(push (make-topic :tags tags :block block)=
topic-blocks)))
> =A0 =A0 =A0 (loop
> =A0 =A0 =A0 =A0(consume-until-tags)
> =A0 =A0 =A0 =A0(let ((parsed-tags (split-sequence #\, line :coalesce-sepa=
rators t)))
> =A0 =A0 =A0 =A0 =A0(when (intersection parsed-tags tags :test #'string-eq=
ual)
> =A0 =A0 =A0 =A0 =A0 =A0(consume-topic parsed-tags)))))))
>
> Ariel
Yep. It looks better.
Cheers
--
Marco
|
|
0
|
|
|
|
Reply
|
Marco
|
2/11/2011 8:40:09 AM
|
|
On Feb 11, 8:55=A0am, TheFlyingDutchman <zzbba...@aol.com> wrote:
> On Feb 10, 4:24=A0am, Marco Antoniotti <marc...@gmail.com> wrote:
>
>
>
>
>
>
>
> > On Feb 8, 11:14=A0pm, mss <m...@dev.null> wrote:
>
> > > Marco Antoniotti wrote:
> > > > That is pretty impressive given that we still don't know what we ar=
e
> > > > supposed to parse :)
>
> > > Chuckle, my bad Marco. The specs along with parsers
> > > in several languages are here:
>
> > > <http://www.topcat.hypermart.net/topic.html>
>
> > > If you can help with the lisp version, feel free to jump in.
>
> > Ok. =A0Here it is, although (1) it may be buggy and cleanable and (2) i=
t
> > will *NEVER* swat away the SLDJ pests buzzing around here :)
>
> > (defstruct topic
> > =A0 tags
> > =A0 block)
>
> > (defun load-topics (topic-file &rest tags)
> > =A0 (with-open-file (tf topic-file
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 :direction :input)
> > =A0 =A0 (let ((topic-blocks ()))
> > =A0 =A0 =A0 (labels ((start ()
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop for line =3D (read-line tf nil=
nil)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0do (format t ">> ~S~%" l=
ine)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while (and line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (or=
(string=3D "" line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 (every #'whitespace-char-p
> > line)))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (if line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
(parse-tags line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
(finish-topic-file))))
>
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(parse-tags (line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((parsed-tags (split-sequence '=
(#\,) line ; May
> > need to load this.
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 :coalesce-
> > separators t)))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(if (intersection parsed-tags ta=
gs :test #'string-
> > equal)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(parse-collect-block par=
sed-tags)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(skip-block))))
>
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(skip-block ()
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop for line =3D (read-line tf nil=
nil)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unless (or (string=3D ""=
line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (ev=
ery #'whitespace-char-p line))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0when (char/=3D #\Tab (ch=
ar line 0))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0do (loop-finish)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (if line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
(parse-tags line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
(finish-topic-file))))
>
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(parse-collect-block (parsed-tags)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(loop for line =3D (read-line tf nil=
nil)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unless (or (string=3D ""=
line)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (ev=
ery #'whitespace-char-p line))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (char=3D #\Tab (char =
line 0))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0collect (subseq line 1) =
into topic-block
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else do (loop-finish)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0finally (cond (line
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 (push (make-topic
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 =A0:tags parsed-tags
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 =A0:block topic-block)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 topic-blocks)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 (parse-tags line))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0(t
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 (finish-topic-file)))))
>
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(finish-topic-file ()
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(return-from load-topics topic-block=
s))
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0)
> > =A0 =A0 =A0 =A0 (start)))))
>
> I found whitespace-char-p on the Lispworks site. Is that the source of
> the one you are using?
Ooops. Yes. You are right.
Now. This is what drives newbies (and old farts) crazy. There is NO
reason for the absence of WHITESPACE-CHAR-P from the ANSI spec (*)
Cheers
--
Marco
(*) No. Any answer mentioning ITS, TOPS-20, Runic Encoding, EBCDIC,
FIELDATA and Romulan scripts does not hold water.
>
> http://www.lispworks.com/documentation/lw51/LWRM/html/lwref-385.htm
> -----------
> Description
> This predicate recognizes [whitespace1] , as described in the
> standard:
> "Space and non-graphic characters that only moved the print position."
> If sys:*extended-spaces* is t , U+3000 Ideographic Space is also
> considered whitespace.
> ------------
>
> I Googled whitespace1 but didn't find what it covers.
|
|
0
|
|
|
|
Reply
|
Marco
|
2/11/2011 8:48:38 AM
|
|
Marco Antoniotti <marcoxa@gmail.com> writes:
> Now. This is what drives newbies (and old farts) crazy. There is NO
> reason for the absence of WHITESPACE-CHAR-P from the ANSI spec (*)
>
> (*) No. Any answer mentioning ITS, TOPS-20, Runic Encoding, EBCDIC,
> FIELDATA and Romulan scripts does not hold water.
I was about to mention just ASCII.
1- #\Vt, #\Ht, etc are only semi-standard.
2- what is considered a white space depends on the file format.
For example, if you are parsing programming languages, in FORTRAN,
#\newline won't be a white space, but if you're pasing Pascal, then it
will.
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
Pascal
|
2/11/2011 9:17:21 AM
|
|
On Feb 11, 10:17=A0am, "Pascal J. Bourguignon" <p...@informatimago.com>
wrote:
> Marco Antoniotti <marc...@gmail.com> writes:
> > Now. =A0This is what drives newbies (and old farts) crazy. =A0There is =
NO
> > reason for the absence of WHITESPACE-CHAR-P from the ANSI spec (*)
>
> > (*) No. Any answer mentioning ITS, TOPS-20, Runic Encoding, EBCDIC,
> > FIELDATA and Romulan scripts does not hold water.
>
> I was about to mention just ASCII.
>
> 1- #\Vt, #\Ht, etc are only semi-standard.
> 2- what is considered a white space depends on the file format.
>
> For example, if you are parsing programming languages, in FORTRAN,
> #\newline won't be a white space, but if you're pasing Pascal, then it
> will.
Still too much rationalization. Sorry :)
(defconstant +whitespace-characters+ <implementation dependent
including #\Space>)
(defun whitespace-char-p (c) (find c +whitespace-characters+))
Should have been in the ANSI. Hey, we have far worse "implementation
dependent" stuff in the spec (plus the stupid case mess; another of
those "thou shalt not mention TOPS-20" topics :) )
Cheers
--
Marco
|
|
0
|
|
|
|
Reply
|
Marco
|
2/11/2011 10:09:20 AM
|
|
Marco Antoniotti <marcoxa@gmail.com> writes:
> (defun whitespace-char-p (c) (find c +whitespace-characters+))
>
> Should have been in the ANSI.
Sure. As well as the closure of ALL the one liners you can generate from CL.
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
Pascal
|
2/11/2011 10:14:57 AM
|
|
On Feb 11, 11:14=A0am, "Pascal J. Bourguignon" <p...@informatimago.com>
wrote:
> Marco Antoniotti <marc...@gmail.com> writes:
> > =A0 =A0(defun whitespace-char-p (c) (find c +whitespace-characters+))
>
> > Should have been in the ANSI. =A0
>
> Sure. =A0As well as the closure of ALL the one liners you can generate fr=
om CL.
Exactly my point! :) That way there would be no time-consuming
swatting of SLDJ buzzers. :)
Cheers
--
Marco
|
|
0
|
|
|
|
Reply
|
Marco
|
2/11/2011 10:30:31 AM
|
|
On 2011-02-11 10:09:20 +0000, Marco Antoniotti said:
> (defconstant +whitespace-characters+ <implementation dependent
> including #\Space>)
>
> (defun whitespace-char-p (c) (find c +whitespace-characters+))
Shouldn't be a constant.
|
|
0
|
|
|
|
Reply
|
Tim
|
2/11/2011 10:34:18 AM
|
|
On Feb 11, 11:34=A0am, Tim Bradshaw <t...@tfeb.org> wrote:
> On 2011-02-11 10:09:20 +0000, Marco Antoniotti said:
>
> > =A0 =A0(defconstant +whitespace-characters+ <implementation dependent
> > including #\Space>)
>
> > =A0 =A0(defun whitespace-char-p (c) (find c +whitespace-characters+))
>
> Shouldn't be a constant.
Yep. I stand corrected.
Cheers
--
Marco
|
|
0
|
|
|
|
Reply
|
Marco
|
2/11/2011 11:12:30 AM
|
|
Marco Antoniotti wrote:
> Feel free to ask questions. Essentially the idea is to use LABELS to
> build a Finite State Automata (or a Recursive Descent Parser :) ).
> Each "label" (a 'letrec' in other functional languages) names a
> "state".
Yes I will, I've just began to study it, work was long yesterday...
I also read on wikipeadia more about Recursive Descent Parsers,
a very good read I thought:
<http://en.wikipedia.org/wiki/Recursive_descent_parser>
> VLisp on a Z8000 (which then became LeLisp), then onto Scheme and
> Franz Lisp (yep; there was such a thing) and finally half-heartedly
> but lazily to Common Lisp, starting with the original KCL. Nowadays I
> mostly live, for the joy of some brits, in Lispworks.
>
> Never touched a Lisp Machine (which, in retrospect, and here is a HUGE
> flame bait :), is a good thing :) ).
That's an interesting history Marco. Slowly I build my history
(still a newbie). Yes I've come across a few articles describing
Lisp Machines, they must have been quite powerful.
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/11/2011 12:38:56 PM
|
|
Edmunds Cers wrote:
> There is an excellent survey including many prominent Lispers here:
> http://wiki.alu.org/The%20Road%20to%20Lisp%20Survey
Yes, this was very interesting Edmunds, lots of folks
from different walks of life...
I installed two small Emacs clones last night, they're
entitled: Chet's Emacs, & mg. My thinking is to take
small steps on the editing side of things...
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/11/2011 12:42:24 PM
|
|
Pascal J. Bourguignon wrote:
> http://www.cliki.net/The%20Road%20to%20Lisp%20Survey
This is good reading: I personally enjoy reading about
the cultures of a given 'tribe' of Lisp users!
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/11/2011 12:45:04 PM
|
|
mss <mss@dev.null> writes:
> I also read on wikipeadia more about Recursive Descent Parsers,
> a very good read I thought:
>
> <http://en.wikipedia.org/wiki/Recursive_descent_parser>
Then you might be interested in a classically recursive reader for your
TOPIC format. (Instead of the state-machine like approach used by
Marco's reader).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defpackage cers.topic
(:use common-lisp split-sequence)
(:export read-topic-db print-topic-blocks))
(in-package cers.topic)
(defun print-topic-blocks (topic topic-db)
(loop as topic-entry in topic-db
do (format
t "~{~%~A~}"
(cadr (assoc-if (lambda (topics)
(member topic topics :test #'equal))
(list topic-entry))))))
(defun read-topic-db (stream)
(loop while (peek-char t stream nil)
collect (read-topic stream)))
(defun read-topic (stream)
(list (read-topic-line stream)
(loop while (peek-char nil stream nil)
as block = (read-block-line stream)
while block
collect block)))
(defun read-topic-line (stream)
(loop as line = (read-line stream)
unless (equal line "")
return (parse-topics line)))
(defun parse-topics (line)
(unless (every (lambda (char)
(or (char<= #\A char #\Z)
(char<= #\a char #\z)
(char<= #\0 char #\9)
(char= char #\Space)
(char= char #\,)))
line)
(error "Forbidden character in topic name."))
(split-sequence #\, line :remove-empty-subseqs t))
(defun read-block-line (stream)
(loop
unless (or (eql (peek-char nil stream nil) #\Tab)
(eql (peek-char nil stream nil) #\Newline))
return nil
do (let ((line (read-line stream)))
(unless (equal line "")
(return (subseq line 1))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
--
A change in perspective is worth 80 IQ points. --- Alan Kay
|
|
0
|
|
|
|
Reply
|
Edmunds
|
2/11/2011 1:15:48 PM
|
|
Wow...
You guys are so far in advance of where I'm at, its unreal.
And I thought I was doing great with regular expressions, then
Lisp enters my consciousness (I've been jarred awake!)... truly
there are not many limits it appears what this language can do.
Yes sir, I certainly will study this, it will take me quite
awhile Edmunds to be able to converse in Lisp with you all
on more than a rudimentary, child-like level, bear with me here.
Edmunds Cers wrote:
> mss <mss@dev.null> writes:
>
>> I also read on wikipeadia more about Recursive Descent Parsers,
>> a very good read I thought:
>>
>> <http://en.wikipedia.org/wiki/Recursive_descent_parser>
>
> Then you might be interested in a classically recursive reader for your
> TOPIC format. (Instead of the state-machine like approach used by
> Marco's reader).
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> (defpackage cers.topic
> (:use common-lisp split-sequence)
> (:export read-topic-db print-topic-blocks))
>
> (in-package cers.topic)
>
> (defun print-topic-blocks (topic topic-db)
> (loop as topic-entry in topic-db
> do (format
> t "~{~%~A~}"
> (cadr (assoc-if (lambda (topics)
> (member topic topics :test #'equal))
> (list topic-entry))))))
>
> (defun read-topic-db (stream)
> (loop while (peek-char t stream nil)
> collect (read-topic stream)))
>
> (defun read-topic (stream)
> (list (read-topic-line stream)
> (loop while (peek-char nil stream nil)
> as block = (read-block-line stream)
> while block
> collect block)))
>
> (defun read-topic-line (stream)
> (loop as line = (read-line stream)
> unless (equal line "")
> return (parse-topics line)))
>
> (defun parse-topics (line)
> (unless (every (lambda (char)
> (or (char<= #\A char #\Z)
> (char<= #\a char #\z)
> (char<= #\0 char #\9)
> (char= char #\Space)
> (char= char #\,)))
> line)
> (error "Forbidden character in topic name."))
> (split-sequence #\, line :remove-empty-subseqs t))
>
> (defun read-block-line (stream)
> (loop
> unless (or (eql (peek-char nil stream nil) #\Tab)
> (eql (peek-char nil stream nil) #\Newline))
> return nil
> do (let ((line (read-line stream)))
> (unless (equal line "")
> (return (subseq line 1))))))
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/11/2011 1:45:15 PM
|
|
mss wrote:
> Wow...
>
> You guys are so far in advance of where I'm at, its unreal.
> And I thought I was doing great with regular expressions, then
> Lisp enters my consciousness (I've been jarred awake!)... truly
> there are not many limits it appears what this language can do.
Okay, I'm starting from scratch (not with the TOPIC parser, Dutch
handled that perfectly - conveying to me in Lisp via terms & code
I could wrap my mind around). But w/ respect to learning Lisp.
Yeah Edmunds, I admit I did tear through the book PCL perhaps
faster than I should've. So now, I'll 'cool-the-jets', & start
re-reading from the beginning. Here we go...
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/11/2011 1:58:10 PM
|
|
mss wrote:
> the TOPIC parser...
btw Dutch if you see this, one small change I made
to (indices) & (loadblock) that will likely add a
tiny measure latency is:
'(#\Space #\Return #\Newline)
but, this ought to account for line endings in
all OS's of Mac/Win/Nix as well
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/11/2011 2:10:09 PM
|
|
On Feb 9, 8:18=A0am, "Pascal J. Bourguignon" <p...@informatimago.com>
wrote:
>
> =A0 =A0 (defun matches (search-string string)
> =A0 =A0 =A0 (loop
> =A0 =A0 =A0 =A0 =A0:with token-list =3D (split-string "," string)
> =A0 =A0 =A0 =A0 =A0:for keyword :in token-list
> =A0 =A0 =A0 =A0 =A0:thereis (string=3D (string-trim '(#\Space) keyword) s=
earch-string)))
>
> By default LOOP returns NIL.
This seems to work without the ":" in front of the loop keywords. What
is the reason for adding the ":" ?
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/12/2011 8:00:32 AM
|
|
On 2011-02-12 08:00:32 +0000, TheFlyingDutchman said:
> This seems to work without the ":" in front of the loop keywords. What
> is the reason for adding the ":" ?
The reason I used to do it was to avoid package clutter. Once, that
used to matter for real: the D-machines could only have 16-bits worth
of symbols, and it was possible to run out if you tried.
|
|
0
|
|
|
|
Reply
|
Tim
|
2/12/2011 9:30:39 AM
|
|
Tim Bradshaw <tfb@tfeb.org> writes:
> On 2011-02-12 08:00:32 +0000, TheFlyingDutchman said:
>
>> This seems to work without the ":" in front of the loop keywords. What
>> is the reason for adding the ":" ?
>
> The reason I used to do it was to avoid package clutter. Once, that
> used to matter for real: the D-machines could only have 16-bits worth
> of symbols, and it was possible to run out if you tried.
My reason is that since LOOP 'keywords' are not exported from CL, they
will be interned in the current package, and unfortunately they're
common enough to be exported from other packages that will then cause
name collisions when (and if) they are later used. So using symbols
from the keyword package avoid this aggravation.
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
Pascal
|
2/12/2011 9:48:00 AM
|
|
On Sat, 12 Feb 2011 10:48:00 +0100, Pascal J. Bourguignon wrote:
> Tim Bradshaw <tfb@tfeb.org> writes:
>
>> On 2011-02-12 08:00:32 +0000, TheFlyingDutchman said:
>>
>>> This seems to work without the ":" in front of the loop keywords. What
>>> is the reason for adding the ":" ?
>>
>> The reason I used to do it was to avoid package clutter. Once, that
>> used to matter for real: the D-machines could only have 16-bits worth
>> of symbols, and it was possible to run out if you tried.
>
> My reason is that since LOOP 'keywords' are not exported from CL, they
> will be interned in the current package, and unfortunately they're
> common enough to be exported from other packages that will then cause
> name collisions when (and if) they are later used. So using symbols
> from the keyword package avoid this aggravation.
Also, some people use different syntax highlighting for keywords, so
using them inside loop (and iter) may be a useful visual aid to
highlight the structure of the loop.
Tamas
|
|
0
|
|
|
|
Reply
|
Tamas
|
2/12/2011 10:40:05 AM
|
|
>
> Or maybe you're referring to (cond) instead?
>
> My understanding of (cond) is taken from:
>
> <http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node84.html>
>
> 'The first clause whose test evaluates to non-nil is selected; all other
> clauses are ignored, and the consequents of the selected clause are
> evaluated in order (as an implicit progn).'
>
One thing about your cond:
(cond ((= (length tag) 0) (blurb))
((string= tag "-i") (indices))
((loadblock tag)))
You last condition test is (loadblock tag), which appears to work out
OK. But I believe this is normally written as a condition of just t,
with (loadblock tag) a function to execute:
(cond ((= (length tag) 0) (blurb))
((string= tag "-i") (indices))
(t (loadblock tag)))
|
|
0
|
|
|
|
Reply
|
TheFlyingDutchman
|
2/12/2011 12:24:04 PM
|
|
On 2011-02-12 12:24:04 +0000, TheFlyingDutchman said:
> You last condition test is (loadblock tag), which appears to work out
> OK. But I believe this is normally written as a condition of just t,
> with (loadblock tag) a function to execute:
>
> (cond ((= (length tag) 0) (blurb))
> ((string= tag "-i") (indices))
> (t (loadblock tag)))
Yes, this "works" because (cond ... (form)) evaluates form to find out
whether the following forms should be evaluated, and if there are none
it returns the result of form. It's dangerous because something like:
(cond (form)
(other-form ...))
will evaluate other-form (and possibly then ...) if form evaluates to NIL.
|
|
0
|
|
|
|
Reply
|
Tim
|
2/12/2011 1:17:12 PM
|
|
TheFlyingDutchman wrote:
> One thing about your cond:
> (cond ((= (length tag) 0) (blurb))
> ((string= tag "-i") (indices))
> ((loadblock tag)))
>
> You last condition test is (loadblock tag), which appears to work out
> OK. But I believe this is normally written as a condition of just t,
> with (loadblock tag) a function to execute:
>
> (cond ((= (length tag) 0) (blurb))
> ((string= tag "-i") (indices))
> (t (loadblock tag)))
Sure enough, in fact wondered about that too...
I'll make that change. And another slight change as
well that makes sense when used in a shell environment,
(& if there's a more proper way to exit w/ an error level
please let me know Dutch):
(defun main()
(defvar tag (format nil "~{~(~a~)~^ ~}" ext:*args*))
(cond ((= (length tag) 0) (blurb) (return-from main 1))
((string= tag "-i") (indices))
(t (loadblock tag)))
(return-from main 0)
)
(exit (main))
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/12/2011 1:48:58 PM
|
|
mss <mss@dev.null> writes:
> TheFlyingDutchman wrote:
>
>> One thing about your cond:
>> (cond ((= (length tag) 0) (blurb))
>> ((string= tag "-i") (indices))
>> ((loadblock tag)))
>>
>> You last condition test is (loadblock tag), which appears to work out
>> OK. But I believe this is normally written as a condition of just t,
>> with (loadblock tag) a function to execute:
>>
>> (cond ((= (length tag) 0) (blurb))
>> ((string= tag "-i") (indices))
>> (t (loadblock tag)))
>
> Sure enough, in fact wondered about that too...
>
> I'll make that change. And another slight change as
> well that makes sense when used in a shell environment,
> (& if there's a more proper way to exit w/ an error level
> please let me know Dutch):
>
> (defun main()
It's customary to put a space between a token and the openning
parenthesis.
> (defvar tag (format nil "~{~(~a~)~^ ~}" ext:*args*))
zero, one, two, many.
I can't count the number of times this defvar is wrong!
1- since it is not toplevel, the following references to tag won't be
expected to be to a special variable, but to a lexical variable.
2- since there is no such lexical variable, the compiler will have to
signal an error. An implementation could choose to generate code as
if it was for a special variable. Or not.
3- since it is defvar, once the variable has been defined, it will never
be changed again.
4- you've named the special variable without earmuffs. Therefore
inconsistencies will occur with all other lexical variables named
tag, depending on when/if the other functions are compiled.
etc.
> (cond ((= (length tag) 0) (blurb) (return-from main 1))
> ((string= tag "-i") (indices))
> (t (loadblock tag)))
>
> (return-from main 0)
There's no need for RETURN-FROM. Just return 0.
> (exit (main))
(defun main (arguments)
;; notice how it is NOT implementation dependant, avoiding reference
;; to implementation dependant variables!
;; this allows you to test and debug this function in other
;; implementations.
(let ((tag (format nil "~{~(~a~)~^ ~}" arguments)))
(cond
((zerop (length tag))
(blurb)
1)
((string= tag "-i")
(indices)
0)
(t
(load-block tag) ; notice how we separate words in symbol
; names with dashes for better readability.
0))))
(ext:exit (main ext:*argv*))
Now, your processing of the argument list is awful. Your shell
implementation made a great effort to parse the command line into
separate words, you should take advantage of it.
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
Pascal
|
2/12/2011 2:08:08 PM
|
|
Pascal J. Bourguignon wrote:
> (defun main (arguments)
> ;; notice how it is NOT implementation dependant, avoiding reference
> ;; to implementation dependant variables!
> ;; this allows you to test and debug this function in other
> ;; implementations.
> (let ((tag (format nil "~{~(~a~)~^ ~}" arguments)))
> (cond
> ((zerop (length tag))
> (blurb)
> 1)
> ((string= tag "-i")
> (indices)
> 0)
> (t
> (load-block tag) ; notice how we separate words in symbol
> ; names with dashes for better readability.
> 0))))
Yes, that's a *very clear* way of expressing it...
This has taught me allot comparing your code to mine.
> (ext:exit (main ext:*argv*))
Accessing argv/argc looks to be implementation-specific :/
This works with CLISP:
(ext:exit (main ext:*args*))
> Now, your processing of the argument list is awful. Your shell
> implementation made a great effort to parse the command line into
> separate words, you should take advantage of it.
On the surface, I understand your words here Pascal, but thinking
more about it, I don't see why you think I need to, because what I
am doing is concatenating the args together only preserving a space
between args & eliminating quotation marks:
tag = argv1 argv2 etc...
From the shell:
$ clisp topic.lisp $* < file.input
Perhaps I still don't understand your final paragraph...
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss
|
2/12/2011 4:18:26 PM
|
|
mss <mss@dev.null> writes:
>> (ext:exit (main ext:*argv*))
>
> Accessing argv/argc looks to be implementation-specific :/
>
> This works with CLISP:
>
> (ext:exit (main ext:*args*))
Yes. Sorry, I made a typo here.
>> Now, your processing of the argument list is awful. Your shell
>> implementation made a great effort to parse the command line into
>> separate words, you should take advantage of it.
>
> On the surface, I understand your words here Pascal, but thinking
> more about it, I don't see why you think I need to, because what I
> am doing is concatenating the args together only preserving a space
> between args & eliminating quotation marks:
>
> tag = argv1 argv2 etc...
>
> From the shell:
>
> $ clisp topic.lisp $* < file.input
>
> Perhaps I still don't understand your final paragraph...
First, let's make a little script as an exercise.
Let's write a script that will print each of its arguments on a
separate line:
------------------------------------------------------------------------
#!/usr/bin/clisp -ansi -q -E ISO-8859-1
;;;; -*- mode:lisp; coding:iso-8859-1 -*-
(defun main (arguments)
(dolist (arg arguments)
(write-line arg))
0)
(ext:exit (main ext:*args*))
------------------------------------------------------------------------
[pjb@kuiper :0.0 ~]$ /tmp/sep1 hello "common lisp" 'world!'
hello
common lisp
world!
Now, try to write the same, using your concatenated arguments:
------------------------------------------------------------------------
#!/usr/bin/clisp -ansi -q -E ISO-8859-1
;;;; -*- mode:lisp; coding:iso-8859-1 -*-
(defun main (arguments)
???
0)
(ext:exit (main (format nil "~{~A~^ ~}" ext:*args*)))
------------------------------------------------------------------------
Next, the first rule of script writing is "little script will grow big".
That's the reason why you don't want to write script in scripting
language. But it also mean that any script that has N options (0≤N),
will eventually need N+1 options. So you should write it from the start
in such a way that adding new options will be easy.
A naive, but good enough way to do that would be:
(let ((files '())
(option-i nil)
(option-x nil))
(dolist (option arguments)
(cond
((string= "-i" option) (setf option-i t))
((string= "-x" option) (setf option-x t))
(t (push option files))))
(do-work (reverse files) :i option-i :x option-x))
But then, you may want to deal with "standard" options such as
-h|--help, -v|--verbose, -V|--version, and you may want to have a higher
level way to specify these options with variants, and possibly parse
options such as --output=file, etc. So the best way is to use a
library.
See my define-option in:
http://git.informatimago.com/viewgit/index.php?a=viewblob&p=public/bin&h=6a37dd5966274aa5717063baef49b5c24c3fddc1&hb=0a4f64e32c8eba60df17cf809db135d51c9b467e&f=script.lisp
or Didier's CLON library http://www.lrde.epita.fr/~didier/software/lisp/clon.php
there are several others too.
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
Pascal
|
2/13/2011 3:51:01 AM
|
|
Thank you for this Pascal, there's allot here
I'll place in my notes...
Starting (slowly) to learn a few things =)
Pascal J. Bourguignon wrote:
>> Perhaps I still don't understand your final paragraph...
>
>
> First, let's make a little script as an exercise.
>
> Let's write a script that will print each of its arguments on a
> separate line:
>
> ------------------------------------------------------------------------
> #!/usr/bin/clisp -ansi -q -E ISO-8859-1
> ;;;; -*- mode:lisp; coding:iso-8859-1 -*-
> (defun main (arguments)
> (dolist (arg arguments)
> (write-line arg))
> 0)
> (ext:exit (main ext:*args*))
> ------------------------------------------------------------------------
>
> [pjb@kuiper :0.0 ~]$ /tmp/sep1 hello "common lisp" 'world!'
> hello
> common lisp
> world!
>
>
> Now, try to write the same, using your concatenated arguments:
>
> ------------------------------------------------------------------------
> #!/usr/bin/clisp -ansi -q -E ISO-8859-1
> ;;;; -*- mode:lisp; coding:iso-8859-1 -*-
> (defun main (arguments)
> ???
> 0)
> (ext:exit (main (format nil "~{~A~^ ~}" ext:*args*)))
> ------------------------------------------------------------------------
>
>
>
> Next, the first rule of script writing is "little script will grow big".
> That's the reason why you don't want to write script in scripting
> language. But it also mean that any script that has N options (0???N),
> will eventually need N+1 options. So you should write it from the start
> in such a way that adding new options will be easy.
>
> A naive, but good enough way to do that would be:
>
> (let ((files '())
> (option-i nil)
> (option-x nil))
> (dolist (option arguments)
> (cond
> ((string= "-i" option) (setf option-i t))
> ((string= "-x" option) (setf option-x t))
> (t (push option files))))
> (do-work (reverse files) :i option-i :x option-x))
>
>
> But then, you may want to deal with "standard" options such as
> -h|--help, -v|--verbose, -V|--version, and you may want to have a higher
> level way to specify these options with variants, and possibly parse
> options such as --output=file, etc. So the best way is to use a
> library.
>
> See my define-option in:
>
> http://git.informatimago.com/viewgit/index.php?a=viewblob&p=public/bin&h=6a37dd5966274aa5717063baef49b5c24c3fddc1&hb=0a4f64e32c8eba60df17cf809db135d51c9b467e&f=script.lisp
>
> or Didier's CLON library http://www.lrde.epita.fr/~didier/software/lisp/clon.php
> there are several others too.
>
--
later on,
Mike
http://www.topcat.hypermart.net/index.html
|
|
0
|
|
|
|
Reply
|
mss (26)
|
2/13/2011 7:31:13 PM
|
|
|
74 Replies
157 Views
(page loaded in 0.769 seconds)
Similiar Articles: parsing a text file - comp.soft-sys.matlabI am new to parsing text. I m having .txt files having many paras of the similar kind of data given below: SEPA40 KWAL 161625 /3540E15A 016162513":... quick problem - parsing text, calculation function... - comp ...This should be a relatively quick one... Basically I have a text field (input), into which I paste the contents of an email (it is a form response fr... Simple parsing text , but not for newbie - comp.lang.awk ...Hi gurus, I am new to awk -- but I have sone Perl background (sorry for Perl notation in example below) I am trying to do the following in awk ... Indirect object referencing (PDF parsing) - comp.text.pdf ...While trying to understand PDF spec, I've failed to find anywhere answer to this. Are indirect object references used only inside dictionary objects,... need help parsing PDF documents - comp.text.pdfHi, i'm currently writing a routine in PHP to extract text parts from within a PDF to build up an index and make a search in there. So far so good. ... Parsing table in rtf file - comp.lang.perl.miscI read up all I could find on the rtf parsing and tokenizing modules and came to the conclusion that they were good for text data but not well suited to tabular data. Help? I'm getting the Error Message - "The download cannot ...compile Py2.6 on SL - comp.lang.python... character in a tag in an HTML document it is parsing. ... both attribute-syntax and dict-syntax should continue ... Very fast delimited record parsing with boost - comp.lang.c++ ...Very fast delimited record parsing with boost - comp.lang.c++ ... quick problem - parsing text, calculation function... - comp ... Fastest way to parse strings from a very ... Parsing Log records with regular expressions - comp.lang.ruby ...I have a log file which is text based which has records in two formats of the following form ` A|B|C|D\n A|B|C|D|E\n \n Exception\n \n \tstack... convert date in different timezones into default timezone, getting ...... countries ) , hence I am receiving CODE Exception in thread "main" java.text.ParseException: Unparseable date: " maandag 19 november 2001 5:48" while parsing String ... Parsing Email data into Filemaker - comp.databases.filemaker ...importing from a web csv - comp.databases.filemaker... use a script to parse the text into ... They paste the email into a ... Excel sheet into tables in FM7 - comp ... Extract specific text from file using sed - comp.unix.shell ...XML tag attribute extraction using awk - comp.lang.awk... extraction using awk - comp.lang.awk parsing XML file with sed - comp.unix.shell [Grep,Awk,Sed]Parsing text ... Default Decimal separator for float parsing and printing - comp ...Re: Decimal seperator - Tech-Archive.net: The source for usenet news Re: Default Decimal separator for float parsing and printing... Users enter text into an input and ... parsing XML file with sed - comp.unix.shellExtract specific text from file using sed - comp.unix.shell ... parsing a text file - comp.soft-sys.matlab parsing XML file with sed - comp.unix.shell XML tag attribute ... How to get only numbers from a row using match() and regex? - comp ...Hi, I am using gawk for text parsing. Now I have a simple problem. I have a string looking like this: "Found 3 log items" What I want to do is to ex... Parsing Text Files - How to parse simple tab separated text files ...Parsing Text Files How to parse simple text files with Perl. From Kirk Brown, former About.com Guide Java Practices -> Parse textThere are various ways of parsing text. The usual tools are : String.split methods; StringTokenizer and StreamTokenizer classes; Scanner class; Pattern and Matcher ... 7/21/2012 7:48:53 PM
|