Parsing another lisp-ish language

Q&A's, tips, howto's
Locked
axtens
Posts: 28
Joined: Mon Apr 06, 2009 12:23 pm
Location: Perth, WA Australia
Contact:

Parsing another lisp-ish language

Post by 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:

Code: Select all

(sai (ITEFORLITLITLITLIT 999999999 1 1 (SAYOPRCAP (SAYVALFOR ...) "thing"))(sayvar goose))
and changing it into this:

Code: Select all

<@ 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:

Code: Select all

<@ 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.

Code: Select all

(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
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Re: Parsing another lisp-ish language

Post by cormullion »

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
Posts: 28
Joined: Mon Apr 06, 2009 12:23 pm
Location: Perth, WA Australia
Contact:

Re: Parsing another lisp-ish language

Post by axtens »

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

Code: Select all

               (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
Posts: 28
Joined: Mon Apr 06, 2009 12:23 pm
Location: Perth, WA Australia
Contact:

Re: Parsing another lisp-ish language

Post by axtens »

Nope. Dead end.

Code: Select all

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
Posts: 13
Joined: Sat Dec 26, 2009 12:05 am

Re: Parsing another lisp-ish language

Post by kks »

Try this

Code: Select all

...
   (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:

Code: Select all

(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:

Code: Select all

<@ sai><@ ITEFORLITLITLITLIT>999999999|1|1|<@ SAYOPRCAP><@ SAYVALFOR>...</@>|thing</@></@><@ sayvar>goose</@></@>
Is this what you want?

axtens
Posts: 28
Joined: Mon Apr 06, 2009 12:23 pm
Location: Perth, WA Australia
Contact:

Re: Parsing another lisp-ish language

Post by axtens »

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.

Locked