integer parsing

Started by BrickCaster, July 05, 2004, 06:31:40 PM

Previous topic - Next topic

BrickCaster

every language has its pitfalls.

the code is supposed to print a simple rotation matrix:


 (if
    (= apos 000) (print "1 0 0 0 1 0 0 0 1")
    (= apos 090) (print "0 0 1 0 1 0 -1 0 0")
    (= apos 180) (print "-1 0 0 0 1 0 0 0 -1")
    (= apos 270) (print "0 0 -1 0 1 0 1 0 0")
  )


pretty code alignment is not always a wise idea.

after carefully reading the doc it turned out that 090 is an octal number!

indeed 090 is the octal number 0.

i found that rather unpleasant.

at least an error message could point the bad number format.

Lutz

#1
(parse "(= apos 090)") => ("(" "=" "apos" "090" ")")



Parsing, translating and evaluating are 3 disinct phases in newLISP, not interwoven like in a traditional interpreter. The parser should never given an error. When the token "090" is translated into some internal binary presentation, newLISP tries to "make the best out of it".



The only thing I would propose is parsing "090" into two tokens "0" and "90". This would be similar to the case:



(parse "123abc") => ("123" "abc")



(parse "090") => ("0" "90") ;; after changing parser



It would not avoid the problem you ran into and you would have:



(= apos 090) interpreted as (= apos 0 90), which would always evaluate to nil.



But breaking the token where the legal octal string ends would be a more consistent approach when parsing numbers.



Lutz



ps: see also the manual description for 'integer'

BrickCaster

#2
Quote
It would not avoid the problem you ran into and you would have:



(= apos 090) interpreted as (= apos 0 90), which would always evaluate to nil.



But breaking the token where the legal octal string ends would be a more consistent approach when parsing numbers.


the problem is not here in my opinion.

consistency means 090 is a decimal number.

consistency would rather command octals have a syntax similar to hex numbers, something like 0c77.

Lutz

#3
A leading 0 for octals is pretty standard in most programming languages. Perl, Python and C/C++,  to name the most popular, all use this convention and many programmers coming to newLISP know these languages. They also flag an error on 090 as "invalid octal", but for the reasons mentioned in my previous post, I don't want to do this.



Whenever you have doubts, how something gets parsed in newLISP you can use the functions 'parse' 'integer' and 'float' to find out.



BTW, what kind of application are you working on? There are some bit handling functions in the language which might help you. There is also a way to handle binary numbers, i.e.:



(integer "101" 0 2) => 5



Lutz

BrickCaster

#4
well, i use newLISP for prototyping some useless functions.

only time will say if the functions are actually usefull and how they eventually are.

the functions manipulate LEGO bricks, represent them as cubes, and test if they overlap and if they connect:

(constant 'black   0)
(constant 'blue    1)
(constant 'green   2)
(constant 'red     4)
(constant 'brown   6)
(constant 'grey    7)
(constant 'dark    8)
(constant 'yellow 14)
(constant 'white  15)
(constant 'trans  32)


(context 'BRICK)

(set 'num '3001)
(set 'col MAIN:red)

(set 'apos 0)
(set 'xpos 0)
(set 'ypos 0)
(set 'zpos 0)

(set 'xmin -40)
(set 'xmax  40)
(set 'ymin   0)
(set 'ymax  24)
(set 'zmin -20)
(set 'zmax  20)

(define (overlap? b)
  (if
    (>= xmin b:xmax) nil
    (<= xmax b:xmin) nil
    (>= ymin b:ymax) nil
    (<= ymax b:ymin) nil
    (>= zmin b:zmax) nil
    (<= zmax b:zmin) nil
    true
  )
)

(define (connect? b)
  (if
    (>= xmin b:xmax) nil
    (<= xmax b:xmin) nil
    (>= zmin b:zmax) nil
    (<= zmax b:zmin) nil
    (= ymin b:ymax)  true
    (= ymax b:ymin)  true
    nil
  )
)

(define (move dx dz)
  (inc 'xpos dx) (inc 'xmin dx) (inc 'xmax dx)
  (inc 'zpos dz) (inc 'zmin dz) (inc 'zmax dz)
)
(define (elevate dy)
  (inc 'ypos dy) (inc 'ymin dy) (inc 'ymax dy)
)

(define (rotate-0)
  (inc 'apos 90)
  (if (= apos 360) (set 'apos 0))
  (let (xneg (- xpos)) (set 'xpos zpos) (set 'zpos xneg))
  (let (nmin (- xmin) nmax (- xmax))
    (set 'xmin zmin) (set 'xmax zmax)
    (set 'zmin nmax) (set 'zmax nmin)
  )
)

(define (rotate-c x0 z0)
  (move (- x0) (- z0)) (rotate-0) (move x0 z0)
)

(define (display)
  (print 1)    (print " ")
  (print col)  (print " ")
  (print xpos) (print " ")
  (print ypos) (print " ")
  (print zpos) (print " ")
  (if
    (= apos   0) (print "1 0 0 0 1 0 0 0 1")
    (= apos  90) (print "0 0 1 0 1 0 -1 0 0")
    (= apos 180) (print "-1 0 0 0 1 0 0 0 -1")
    (= apos 270) (print "0 0 -1 0 1 0 1 0 0")
  )
  (print " ")
  (print num) (print ".dat")
  (print "rn")
)




the "display" output is valid entry for LEGO-CAD software that can be found here: http://www.ldraw.org/">//http://www.ldraw.org/



"1 0 0 0 1 0 0 0 1" is not binary number but the identity matrix:



1 0 0

0 1 0

0 0 1



newLISP has matrix operations and that is also a welcomed plus :-)



i guess prototyping languages are ideal for such experiments, when you are not sure what you want to do, but you know how to do it.

newLISP is open-minded :-)

Lutz

#5
Thanks for the legodraw link, very interesting, I am an old Lego fan. There is also this Lego robotics set they have and which always caught my attention, but I never had the opportunity to try it out.



Tip for your code:



>>>>

(print " ")

(print num) (print ".dat")

(print "rn")

>>>>



'print' and 'println' can take multiple arguments, you can make your code shorter/quicker by doing:



(println " " num ".dat")



The 'println' will also adjust to the platform it is running on; on Win32 it will terminate the line with "rn" and on Linux/UNIX "n"



Lutz