Freerefill Posted September 30, 2009 Posted September 30, 2009 Back to my stock of unusual questions. My batch routine can accept strings from the user, which are in essence LISP code. Naturally, these strings can be evaluated, and the LISP code can be ran. The problem is, what if the user inputs an incorrectly formatted command? Suppose instead of "(vl-cmdf "circle" (getpoint) 5)" they type "I love to sing-a, about the moon-a in the June-a in the spring-a". I need a way to determine if what they type is valid LISP code (hence the title of this thread). I've done some thinking, and there are only two ways that even begin to solve this problem, but neither of them are fully satisfactory. The first is testing if the string can be read as a valid list, a sort of (listp (read )) idea. This will work if the command is formatted properly, since all commands entered this way, when passed through the 'read' function, will return a list. However, this will always return true if the user typed a list, which means it won't check to see if it's valid code. The other method is using the eval function, which pretty much does exactly what I'm trying to achieve, only I don't want the code to actually be evaluated. I just want it checked to see if it CAN be evaluated. It's a small bug in retrospect, especially since one typo could throw off the whole works (suppose someone misspelled "circle", it would still be valid LISP code but it wouldn't run properly), but it's got my curiosity ablaze. Any ideas? Quote
Lee Mac Posted September 30, 2009 Posted September 30, 2009 Good question, but there are a few restrictions that I can see... Of course, you could check for a valid list using: (vl-consp (read <string> )) But, as you say, this would only determine if the user has entered a list. My second thought was something along the lines of: (vl-catch-all-error-p (vl-catch-all-apply 'eval (list (read <string>)))) And check to see if it threw an error, but of course, this would mean evaluating the code in question... Quote
Glen Smith Posted September 30, 2009 Posted September 30, 2009 Well if there are more than 10 charecters without one of them being a parenthesis, it's obviously not valid LISP code. Could you try evaluating it once in a test loop and if it fails, return it as invalid? Sorry I don't really have a good answer, just had to be a smart alec. Glen Quote
Lee Mac Posted September 30, 2009 Posted September 30, 2009 I doubt you can check for errors without evulating the code - otherwise I reckon the VLIDE would have a function like that built in.. But, if you evaluate it, not only will it do what its programmed to do - you will also fall up on any user inputs it may have... Quote
Freerefill Posted September 30, 2009 Author Posted September 30, 2009 We can all see it going one of two ways. Checking to see that it's a list, checking to see that it has an equal number of open and closed parentheses, et cetera, et cetera. Basically, breaking it apart and building up a valid check by the pieces. Or, from the top down: using the eval function but capturing all the "activity" so nothing is actually being done. The latter does seem like the cleaner and easier option, as the former seems to me that it would require checking against long lists of valid options, to the point of being all but impossible to accomplish. I wonder.. would it be possible to write the code to a script, run the script, then undo all the activity? I read somewhere that a single "undo" will undo all operations in a script. That would allow an evaluation (thus, a test) and, ultimately, no changes were made. I think it would have to be a script, as there would be no way to tell how many changes were made if it was straight LISP. What do you think? *EDIT* A single undo might not work. Who knows, maybe nothing was actually done. Quote
Lee Mac Posted September 30, 2009 Posted September 30, 2009 Why use a script? If you were to test the code, then undo the changes, just use vla-StartUndoMark/EndUndoMark or (command "_.undo" "_begin")/(... "_end") But, to check for errors, you would have the code wrapped in the vla-catch-all-apply statement, so, I suppose you would only use the "undo" if an error was flagged. Quote
Freerefill Posted September 30, 2009 Author Posted September 30, 2009 I'd use a script because I didn't know about those other commands, but I sure as heck do now! o.o If you wrap the code in a (setq variable (vla-catch-all-apply ...)), then wrap THAT in those fancy undo bits.. couldn't you then check the status of "variable" to see if it's an error? Or would the "undo" bits not work if there's nothing to undo? Quote
Freerefill Posted September 30, 2009 Author Posted September 30, 2009 By jove, I think that's it. (defun c:tst_lispp() (setq code (getstring "\nEnter Visual LISP code: ")) (lispp code) ) (defun lispp(input / chkvar) (vl-cmdf "_.undo" "_begin") (setq chkvar (vl-catch-all-apply 'eval (list (read input)))) (vl-cmdf "_.undo" "_end" "_.undo" "") (vl-catch-all-error-p chkVar) ) Much obliged everyone, my curiosity is happy now. ^.^ Quote
Lee Mac Posted September 30, 2009 Posted September 30, 2009 Why undo it if there's no error? Surely then the code has done what it was meant to? Quote
Freerefill Posted September 30, 2009 Author Posted September 30, 2009 The idea is simply to check to see if the string can be evaluated. Actual evaluation doesn't happen at this step, but at later steps. If I didn't specify that at the start, I apologize. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.