Parsing another lisp-ish language

Started by axtens, January 16, 2010, 12:20:15 AM

Previous topic - Next topic

axtens

G'day everyone



I'm writing a translator which will take a Lisp-ish way of writing a language and outputting it in a more XML-ish form.



This means taking this:
(sai (ITEFORLITLITLITLIT 999999999 1 1 (SAYOPRCAP (SAYVALFOR ...) "thing"))(sayvar goose))

and changing it into this:
<@ sai><@ ITEFORLITLITLITLIT>999999999|1|1|<@ SAYOPRCAP><@ SAYVALFOR>...</@>|thing</@></@><@ sayvar>goose</@></@>

My problem is that the code below almost works, except that it converts to this:
<@ sai><@ ITEFORLITLITLITLIT>999999999|1|1|<@ SAYOPRCAP><@ SAYVALFOR>...</@>|thing</@></@>|<@ sayvar>goose</@></@>

In case you missed it, the difference is the presence of the bar character just before the <@ sayvar>goose, which is clearly "the wrong thing"



Given the recursive nature of the 'proc' define, why am I always getting the bar appearing? The rule, BTW, is that SAI's arguments (and a few others) are never bar separated, but all others have arguments separated by bar.



Kind regards,

Bruce.

P.S. Windows version of newLisp. Development version. UTF-8 EXE.


(setq res "")
(define (proc procode)
(local (codelen code separator elider)
(begin
(setq codelen (length procode))
(for (i 0 (- codelen 1) 1)
(begin
(setq code (procode i))
(when (= i 0) (setq res (append res "<@ " (string code) ">" )))
;at this point, check to see whether OMT and SAI things are used
;if so, set the separator to empty string
(setq elider (find (upper-case (string code)) '("OMT" "SAO" "OSA" "SAI" "OSI" "SAW" "OSW")))
(if (nil? elider)
(setq separator "|")
(setq separator "")
)
(when (> i 0 )
(if
(list? code) (proc code)
(atom? code) (setq res (append res (string code) )  )
)
(if (< i (- codelen 1))
(begin
(setq res (append res separator ))
)
)
)
(when (= i (- codelen 1))
(setq res (append res "</@>" ))
)
)
)
)
)
)

(setq code "(sai (ITEFORLITLITLITLIT 999999999 1 1 (SAYOPRCAP (SAYVALFOR ...) "thing"))(sayvar goose))")
(setq parsed (read-expr code))(println $0)
(proc parsed)
(print res)
(exit)

cormullion

#1
Hi - I had a go at running this, but nothing leaped out to say "this is why"...  Sorry.



Perhaps you could make a simplified version of the code to see if there are any logic errors in it? And perhaps you could try stepping through the debugger with it - that's often a good way to spot what's happening.

axtens

#2
I think I've got it partly figured out. Still have to come up with a solution, though.


              (when (> i 0 )
                  (if    
                     (list? code) (proc code)
                     (atom? code) (setq res (append res (string code) )  )
                  )
                  (if (< i (- codelen 1))
                     (begin
                        (setq res (append res separator ))
                     )
                  )
               )


When one returns from the 'proc' routine, control falls to the end of the (when) thus missing the separator stuff.



Is that really the problem? I just don't know.



Bruce.

axtens

#3
Nope. Dead end.



s(setq res "")
(define (proc procode)
   (local (codelen code separator elider)
      (begin
         (setq codelen (length procode))
         (for (i 0 (- codelen 1) 1)
            (begin
               (setq code (procode i))
               (when (= i 0) (setq res (append res "<@ " (string code) ">" )))
               ;at this point, check to see whether OMT and SAI things are used
               ;if so, set the separator to empty string
               (setq elider (find (upper-case (string code)) '("OMT" "SAO" "OSA" "SAI" "OSI" "SAW" "OSW")))
               (if (nil? elider)
                  (setq separator "|")
                  (setq separator "")
               )
               (when (> i 0 )
                  (if    
                     (list? code) (proc code)
                     (atom? code) (setq res (append res (string code) )  )
                  )
)
                (when (> i 0)
 (if (< i (- codelen 1))
                        (setq res (append res separator ))
                     )
                )
                (when (= i (- codelen 1))
                  (setq res (append res "</@>" ))
                )
            )      
         )
      )
   )
)

(setq code "(sai (ITEFORLITLITLITLIT 999999999 1 1 (SAYOPRCAP (SAYVALFOR ...) "thing"))(sayvar goose))")
(setq parsed (read-expr code))(println $0)
(proc parsed)
(print res)
(exit)

kks

#4
Try this

...
   (local (h codelen code separator elider)   # add `h` (head of current list)
      ...
      (when (= i 0) (setq h code   # set `h` here
               res (append res "<@ " (string code) ">" )))
      ...
      (setq elider (find (upper-case (string h)) '("OMT" "SAO" "OSA" "SAI" "OSI" "SAW" "OSW")))   # change `code` to `h`
      ...


Here is the full code:

(setq res "")
(define (proc procode)
(local (h codelen code separator elider)
(begin
(setq codelen (length procode))
(for (i 0 (- codelen 1) 1)
(begin
(setq code (procode i))
(when (= i 0) (setq h code  res (append res "<@ " (string code) ">" )))
;at this point, check to see whether OMT and SAI things are used
;if so, set the separator to empty string
(setq elider (find (upper-case (string h)) '("OMT" "SAO" "OSA" "SAI" "OSI" "SAW" "OSW")))
(if (nil? elider)
(setq separator "|")
(setq separator "")
)
(when (> i 0 )
(if    
(list? code) (proc code)
(atom? code) (setq res (append res (string code) )  )
)
(if (< i (- codelen 1))
(begin
(setq res (append res separator ))
)
)
)
(when (= i (- codelen 1))
(setq res (append res "</@>" ))
)
)      
)
)
)
)

(setq code "(sai (ITEFORLITLITLITLIT 999999999 1 1 (SAYOPRCAP (SAYVALFOR ...) "thing"))(sayvar goose))")
(setq parsed (read-expr code))(println $0)
(proc parsed)
(print res)
(exit)


The result is:

<@ sai><@ ITEFORLITLITLITLIT>999999999|1|1|<@ SAYOPRCAP><@ SAYVALFOR>...</@>|thing</@></@><@ sayvar>goose</@></@>


Is this what you want?

axtens

#5
kks,



Yes, that's marvellous. Thanks very much. I can now get on with the rest of the project (and figure out why your fix works.)



Kind regards,

Bruce.