<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-2873917929184567506</atom:id><lastBuildDate>Tue, 13 Oct 2009 07:17:08 +0000</lastBuildDate><title>Wild Stabs In The Dark</title><description>Inane ramblings from a desert island...</description><link>http://jazariah.blogspot.com/</link><managingEditor>noreply@blogger.com (Patagonian Toothfish)</managingEditor><generator>Blogger</generator><openSearch:totalResults>45</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-1744445293136028022</guid><pubDate>Mon, 18 Aug 2008 15:22:00 +0000</pubDate><atom:updated>2008-08-19T20:53:06.237+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>brightsword</category><category domain='http://www.blogger.com/atom/ns#'>brightsword.eden</category><category domain='http://www.blogger.com/atom/ns#'>computer science</category><title>Almost a full-blown LISP interpreter :)</title><description>&lt;p&gt;[9th August 2008]&lt;/p&gt;  &lt;p&gt;So I've been playing with the Eden library again, and I finished putting in some very cool functionality while watching China put on a phenomenal show for the Olympic Games Opening Ceremony...&lt;/p&gt;  &lt;p&gt;Eden now supports &lt;code&gt;cons&lt;/code&gt;! So we can build and return lists now, such as the following examples:&lt;/p&gt; &lt;code&gt;   &lt;p&gt;(cons 'maple' (list 'birch' 'oak' 'larch')) =&amp;gt; ('maple' 'birch' 'oak' 'larch')      &lt;br /&gt;(list 'maple' (list 'birch' 'oak' 'larch')) =&amp;gt; ('maple' ('birch' 'oak' 'larch'))&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;&lt;code&gt;Date&lt;/code&gt; is now a first class atom-type, so we can do things like:&lt;/p&gt; &lt;code&gt;   &lt;p&gt;(defun next_sunday (x? f?)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (prog       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (setq d (if (nil-p x) today x))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (date (+ d (- 7 (day_of_week d))) f)))&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;To make the programmer's life easier, we also supports optional arguments to &lt;code&gt;defun&lt;/code&gt;! To designate the formal parameter as optional, append it with a question mark. All formal parameters after the first optional one are implicitly optional. If no argument is bound to an optional parameter, it is initialised with &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Of course, &lt;code&gt;+&lt;/code&gt; now handles dates and time-spans :)&lt;/p&gt;  &lt;p&gt;[Ten days later]&lt;/p&gt;  &lt;p&gt;OK. &lt;code&gt;cons&lt;/code&gt; works, as do &lt;code&gt;car&lt;/code&gt;, &lt;code&gt;cdr&lt;/code&gt; and all the test functions like &lt;code&gt;listp&lt;/code&gt; (which has an alias, &lt;em&gt;a-la&lt;/em&gt; Scheme, of &lt;code&gt;list?&lt;/code&gt;), &lt;code&gt;atom?&lt;/code&gt; and &lt;code&gt;nil?&lt;/code&gt;.&lt;/p&gt;  &lt;p&gt;I've spent the last few days re-implementing the evaluation engine to dynamically support new native functions using reflection and cleaning up various odd-bits (yes, I was watching the Olympic Games and it did reduce my productivity a bit). &lt;/p&gt; &lt;code&gt;   &lt;p&gt;(defun make-list (x)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (cond       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((list? x) x)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (t (cons x nil))))&lt;/p&gt;    &lt;p&gt;(defun append (l x)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (cond       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((atom? l) (cons l (make-list x)))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((nil? l) (make-list x))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (t (cons (car l) (append (cdr l) x)))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ))&lt;/p&gt;    &lt;p&gt;(defun reverse (l)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (cond       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((nil? l) l)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((atom? l) nil)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((list? (car l)) (append (reverse (cdr l)) (list (reverse (car l)))))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (t       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (append (reverse (cdr l)) (car l))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ))&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;allows us to call&lt;/p&gt;  &lt;p&gt;&lt;code&gt;(reverse (list 'a' 'b' (list 'c' 'd') 'e' 'f'))&lt;/code&gt;, which returns with &lt;code&gt;(f e (d c) b a)&lt;/code&gt; as we expect!&lt;/p&gt;  &lt;p&gt;In addition to optional parameters, easy-to-integrate native functions, properly stacked evaluation of (mutually) recursive functions, scoped parameters and variables, and multiple-statement defun definitions, we have all the makings of a full-blown, yet neat and compact LISP interpreter! &lt;/p&gt;  &lt;p&gt;Next, I think I'll get it to support lambdas and mapcar! &lt;/p&gt;  &lt;p&gt;While I'm at it, let me stress on the importance of writing unit tests, specially while developing foundational pieces like this one.&lt;/p&gt;  &lt;p&gt;I've been using the native testing framework in Visual Studio 2008, and it's a breeze to be able to run off a whole suite of tests to make sure that a fix I put in for one bug didn't break something else somewhere.&lt;/p&gt;  &lt;p&gt;Furthermore, as the tests get more and more complex and involved, it's comforting to know that the system is just growing stronger every time a feature gets added without anything being broken! I now have over 200 test expressions which are run after every major recompile, assuring that all the functionality is working as it should be...&lt;/p&gt;  &lt;p&gt;Stay tuned!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-1744445293136028022?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/08/almost-full-blown-lisp-interpreter.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-2438499200132435311</guid><pubDate>Thu, 07 Aug 2008 15:21:00 +0000</pubDate><atom:updated>2008-08-19T20:54:10.129+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>brightsword</category><category domain='http://www.blogger.com/atom/ns#'>brightsword.eden</category><category domain='http://www.blogger.com/atom/ns#'>computer science</category><title>Post 6: Expression Evaluator - Finale</title><description>&lt;p&gt;We have, in the previous posts, seen how to build an expression evaluator and integrate it into our calling environment.&lt;/p&gt;  &lt;p&gt;The concepts we have discussed provide a solid basis for an evaluation engine that can be extended further.&lt;/p&gt;  &lt;p&gt;For example, we could support custom functions with a &lt;code&gt;defun&lt;/code&gt; function:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;code&gt;(defun &amp;lt;function name&amp;gt; &amp;lt;list of formal parameters&amp;gt; &amp;lt;function body&amp;gt;)&lt;/code&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It's easy to see how we could implement the defun function as a known function, which would store the body and formal parameter list in a hash table indexed by the function name. We could then modify the Apply function to bind values to the formal parameters and evaluate the body.&lt;/p&gt;  &lt;p&gt;We could support variable binding with the &lt;code&gt;setq&lt;/code&gt; function:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;code&gt;(setq &amp;lt;var_name&amp;gt; &amp;lt;expr&amp;gt;)&lt;/code&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We could do this by storing the value of the expression in a global symbol table indexed by the var_name, and modifying the &lt;code&gt;Apply&lt;/code&gt; function to do look for the value of a variable first in the scoped symbol table and then the global one.&lt;/p&gt;  &lt;p&gt;We could support conditional operations with the &lt;code&gt;cond&lt;/code&gt; function, which returns the result associated with the first test expression that evaluates to 'true':&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;code&gt;(cond ((test_1) (result_1))&amp;#160; ... ((test_n) (result_n)))&lt;/code&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We could even expand our processing to perform evaluation of the function name:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;code&gt;((cond ((&amp;gt; w 20) &amp;quot;square&amp;quot;) (t &amp;quot;cube&amp;quot;)) p)&lt;/code&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;so that we get the value of &lt;code&gt;(square p)&lt;/code&gt; if &lt;code&gt;w &amp;gt; 20&lt;/code&gt; and &lt;code&gt;(cube p)&lt;/code&gt; otherwise!&lt;/p&gt;  &lt;p&gt;With a few more modifications, we can support recursive functions such as the classic expression for a factorial&lt;/p&gt; &lt;code&gt;   &lt;blockquote&gt;     &lt;p&gt;(defun decr (x) (- x 1))        &lt;br /&gt;(defun fact (x) (cond ((&amp;gt; x 0) (* x (fact (decr x)))) (t 1)))&lt;/p&gt;   &lt;/blockquote&gt; &lt;/code&gt;  &lt;p&gt;Executing the above strings in order would allow us to compute factorials of any integer from that point on!&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;code&gt;double fact10 = 10.ToString().Evaluate(null);&lt;/code&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Cool?&lt;/p&gt;  &lt;p&gt;&lt;a href="mailto://johnaz@brightsword.com" target="_blank"&gt;Contact me&lt;/a&gt; if you would like to get your hands on this library!&lt;/p&gt;  &lt;p&gt;One last thing - in honour of my newest niece who was born just as the first full implementation of this project was completed, I'm calling this library Eden. We'll be likely releasing BrightSword.Eden as a free download from the &lt;a href="http://www.brightsword.com" target="_blank"&gt;company home page&lt;/a&gt; soon.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-2438499200132435311?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/08/post-6-expression-evaluator-finale.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-7204085485568151748</guid><pubDate>Sat, 02 Aug 2008 04:29:00 +0000</pubDate><atom:updated>2008-08-03T11:37:28.990+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>brightsword</category><category domain='http://www.blogger.com/atom/ns#'>brightsword.eden</category><category domain='http://www.blogger.com/atom/ns#'>computer science</category><title>Post 5: Expression Evaluator - Integration</title><description>&lt;p&gt;So far, we've used &amp;quot;constant&amp;quot; s-expressions as examples for evaluation, and that's pretty cool, but it is, of course, a great deal more interesting to be able to compute expression values when the expression contains variables bound to values at run-time.&lt;/p&gt;  &lt;p&gt;For example, the formula for computing the Body Mass Index of a healthy human is given by the following formula:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;BMI = (Weight in Kilograms / (Height in Meters) x (Height in Meters))&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;or as an s-expression&lt;/p&gt;  &lt;p&gt;&lt;code&gt;(div weight (prod height height))&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;If we were able to pass in the values for weight and height for various people, we could get the expression evaluator to compute the BMI.&lt;/p&gt;  &lt;p&gt;To accomplish this, we make a few modifications to the &lt;code&gt;Evaluate&lt;/code&gt; function, and pass in an addition symbol table with values for the variables.&lt;/p&gt; &lt;code&gt;   &lt;p&gt;public static Expression Evaluate(this Expression _this, Dictionary&amp;lt;string, object&amp;gt; Symbols)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; switch (_this.Children.Count)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case 0:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; /* atomic value */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (_this.Token)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ...&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.ValidName:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (_this.TokenValue.ToLower())       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ... other &amp;quot;known&amp;quot; tokens &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _this.SetValue(Symbols[_this.TokenValue]);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch (KeyNotFoundException)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _this.RegisterMissingSymbol(_this.TokenValue);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.Text:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.ValidNumber:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SingleQuotedText:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.DoubleQuotedText:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _this.SetValue(_this.TokenValue);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new EvaluatorException(_this, &amp;quot;Evaluate Error: Unknown Token!&amp;quot;);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return _this;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ...      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;} &lt;/p&gt; &lt;/code&gt;  &lt;p&gt;To call our evaluator from some other code, we could do the following:&lt;/p&gt; &lt;code&gt;   &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; string strExpression = ... get the string from a resource or database&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Dictionary&amp;lt;string, object&amp;gt; Symbols = new Dictionary&amp;lt;string, object&amp;gt;();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Symbols[&amp;quot;height&amp;quot;] = ... input from a form or database;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Symbols[&amp;quot;weight&amp;quot;] = ... input from a form or database; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; double BMI = strExpression.Evaluate(Symbols).ValueAsNumber;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;Now if the customer wanted the formula changed on the fly to the non metric version, all we need to do is change the expression to be evaluated to&lt;/p&gt;  &lt;p&gt;&lt;em&gt;BMI = ( Weight in Pounds / ( Height in inches ) x ( Height in inches ) ) x 703&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;or&lt;/p&gt;  &lt;p&gt;&lt;code&gt;(prod (div weight (prod height height) 703)&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;and the compiled version of the code doesn't change at all!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-7204085485568151748?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/08/post-5-expression-evaluator-integration.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-3012825926617658252</guid><pubDate>Fri, 01 Aug 2008 02:04:00 +0000</pubDate><atom:updated>2008-08-03T11:37:28.991+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>brightsword</category><category domain='http://www.blogger.com/atom/ns#'>brightsword.eden</category><category domain='http://www.blogger.com/atom/ns#'>computer science</category><title>Post 4: Expression Evaluator - Object Typing</title><description>&lt;p&gt;We have seen how the evaluation engine recursively evaluates an expression tree and associates a value with each &lt;code&gt;Expression&lt;/code&gt; object. We have also seen how the values associated with the &lt;code&gt;Expression&lt;/code&gt; object are examined only by the individual function processors. Let's look at the function processor for the &amp;quot;+&amp;quot; function again&lt;/p&gt; &lt;code&gt;   &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; case &amp;quot;+&amp;quot;:&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Functor.SetValue(Arguments.Aggregate(0.0d, (result, x) =&amp;gt; result += x.Evaluate().ValueAsNumber);&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Functor.SetNil();&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt; &lt;/code&gt;  &lt;p&gt;We notice the generic &lt;code&gt;Aggregate&lt;/code&gt; function on &lt;code&gt;Arguments&lt;/code&gt; returns a &lt;code&gt;double&lt;/code&gt;, and consequently the lambda expression returns a &lt;code&gt;double&lt;/code&gt;, using the native &lt;code&gt;+=&lt;/code&gt; operator to operate on &lt;code&gt;double&lt;/code&gt; values. This means that we have to somehow express the value of the &lt;code&gt;Expression x&lt;/code&gt; as a double. Further, we need to ensure that the value associated with the &lt;code&gt;Functor&lt;/code&gt; is henceforth interpretable as a double.&lt;/p&gt;  &lt;p&gt;We also need to handle the case where it cannot be expressed as a number, and we'll deal with that in a moment.&lt;/p&gt;  &lt;p&gt;We can also imagine other scalar types - like strings and boolean values - of immense importance when we want to do comparison expressions like:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;code&gt;(&amp;gt; a b)&lt;/code&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We therefore create a &lt;code&gt;Variant&lt;/code&gt; class (again a throwback to my C/C++ days) where a class can encapsulate a given value and represent it, if possible, in various types. In our case, we are going to support strings, numbers (doubles) and booleans, so our variant class looks something like:&lt;/p&gt; &lt;code&gt;   &lt;p&gt;public class VariantValue      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public E_VALUETYPE ValueType { get; protected internal set; } &lt;/p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public object UntypedValue { get; protected internal set; }     &lt;br /&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public virtual bool IsNumber      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CastToNumber(this.UntypedValue);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return true;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return false;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected static double CastToNumber(object value)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return System.Convert.ToDouble(value);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new InvalidCastException(&amp;quot;Cannot express (&amp;quot; + value.ToString() + &amp;quot;) as a Number&amp;quot;);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public virtual double ValueAsNumber      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return CastToNumber(this.UntypedValue);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return double.NaN;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; set      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.UntypedValue = value;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.ValueType = E_VALUETYPE.Number;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; #region Boolean ...&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; #region String ...&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected internal virtual VariantValue SetValue(bool value) { this.ValueAsBoolean = value; return this; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; protected internal virtual VariantValue SetValue(double value) { this.ValueAsNumber = value; return this; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; protected internal virtual VariantValue SetValue(string value) { this.ValueAsString = value; return this; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected internal virtual VariantValue SetNil() ...&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected internal virtual VariantValue SetValue(VariantValue value) ... &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected internal virtual VariantValue SetValue(object value) ...      &lt;br /&gt;} &lt;/p&gt; &lt;/code&gt;  &lt;p&gt;We can see how the &lt;code&gt;VariantValue&lt;/code&gt; class stores the raw value in the &lt;code&gt;UntypedValue&lt;/code&gt; property and tries to represent it as a Number, Boolean or String when required. This is important because a value can have more than one representation.&lt;/p&gt;  &lt;p&gt;The &lt;code&gt;Is...&lt;/code&gt; accessor properties allow callers to query if the value can be represented in the appropriate type. &lt;/p&gt;  &lt;p&gt;The &lt;code&gt;ValueAs...&lt;/code&gt; accessor properties return the value as the appropriate type if possible. They will never throw any exceptions. They are helped by the internal &lt;code&gt;CastTo...&lt;/code&gt; functions, which &lt;em&gt;do &lt;/em&gt;throw exceptions. When we examine the &lt;code&gt;SetValue(object)&lt;/code&gt; function, we'll see how the exceptions play a crucial role in helping us decide how best to represent a generic object.&lt;/p&gt;  &lt;p&gt;The &lt;code&gt;ValueAs...&lt;/code&gt; mutator properties save the raw value in the &lt;code&gt;UntypedValue&lt;/code&gt; property. Since the type of the value is known to them, they also store the type information in the &lt;code&gt;ValueType&lt;/code&gt; property. &lt;/p&gt;  &lt;p&gt;The code below is the &lt;code&gt;SetValue(object)&lt;/code&gt; function. It is called when the type-specific version of &lt;code&gt;SetValue&lt;/code&gt; cannot be called (for example when the value is obtained from a symbol table - look at the section on integration).&lt;/p&gt;  &lt;p&gt;We successively attempt to coerce the value into one of the three known types, using the exceptions thrown from the &lt;code&gt;CastTo...&lt;/code&gt; functions to signal that coercion was unsuccessful.&lt;/p&gt; &lt;code&gt;   &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected internal virtual VariantValue SetValue(object value)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (value == null) { return SetNil(); } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // [true] can be coerced to a number if we don't do this      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ((value is long) || (value is double))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.ValueAsNumber = CastToNumber(value); return this;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (value is bool)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.ValueAsBoolean = CastToBoolean(value); return this;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.ValueAsNumber = CastToNumber(value);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.ValueAsBoolean = CastToBoolean(value);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.ValueAsString = CastToString(value);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.UntypedValue = value;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.ValueType = E_VALUETYPE.Uninitialized; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;Since every &lt;code&gt;Expression&lt;/code&gt; object is associated with a value, we can make life easy and simply derive the &lt;code&gt;Expression&lt;/code&gt; class from the &lt;code&gt;VariantValue&lt;/code&gt; class. We are effectively saying that an &lt;code&gt;Expression&lt;/code&gt; &lt;em&gt;is a&lt;/em&gt; &lt;code&gt;VariantValue&lt;/code&gt;.&lt;/p&gt; &lt;code&gt;   &lt;p&gt;public class Expression : VariantValue&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160; ...&lt;/p&gt;  &lt;/code&gt;  &lt;p&gt;We're close to putting the finishing touches on our expression evaluator. The last post in this series will deal with integration with the calling environment, allowing us to use the evaluator within the context of any other application.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-3012825926617658252?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/08/post-4-expression-evaluator-object.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-3533297027355511553</guid><pubDate>Thu, 31 Jul 2008 02:03:00 +0000</pubDate><atom:updated>2008-08-03T11:37:28.991+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>brightsword</category><category domain='http://www.blogger.com/atom/ns#'>brightsword.eden</category><category domain='http://www.blogger.com/atom/ns#'>computer science</category><title>Post 3: Expression Evaluator - The Expression Class and Evaluation</title><description>&lt;p&gt;The &lt;code&gt;Expression&lt;/code&gt; Class is a n-ary tree representation of a given S-Expression.&lt;/p&gt;  &lt;p&gt;In its simplest form, the class would look something like:&lt;/p&gt; &lt;code&gt;   &lt;p&gt;public class Expression      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; protected Expression m_Parent = null;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public virtual Expression Parent { get { return m_Parent; } } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected List&amp;lt;Expression&amp;gt; m_Children = new List&amp;lt;Expression&amp;gt;();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public virtual List&amp;lt;Expression&amp;gt; Children { get { return m_Children; } } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected string m_TokenValue = String.Empty;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public string TokenValue { get { return m_TokenValue; } } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; ... other housekeeping properties ...&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;At this point in the evaluation cycle, we have simply created a different representation of the S-Expression. &lt;/p&gt;  &lt;p&gt;We actually perform the evaluation of each node by recursively evaluating each of the children and merging their results. The obvious questions here are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;How exactly do we merge the results? &lt;/li&gt;    &lt;li&gt;How do we evaluate the children? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It would also be important to discuss the issue of the &lt;em&gt;type&lt;/em&gt; of the result.&lt;/p&gt;  &lt;p&gt;Let's go back to a simple S-Expression &lt;/p&gt; &lt;code&gt;   &lt;blockquote&gt;     &lt;p&gt;(+ 1 2 3 4)&lt;/p&gt;   &lt;/blockquote&gt; &lt;/code&gt;  &lt;p&gt;The Expression tree generated would be:&lt;/p&gt; &lt;code&gt;   &lt;ul&gt;     &lt;li&gt;Root (1 Child)        &lt;ul&gt;         &lt;li&gt;&amp;gt;&amp;gt; (5 Children)            &lt;ul&gt;             &lt;li&gt;&amp;quot;+&amp;quot; (0 Children) &lt;/li&gt;              &lt;li&gt;&amp;quot;1&amp;quot; (0 Children) &lt;/li&gt;              &lt;li&gt;&amp;quot;2&amp;quot; (0 Children) &lt;/li&gt;              &lt;li&gt;&amp;quot;3&amp;quot; (0 Children) &lt;/li&gt;              &lt;li&gt;&amp;quot;4&amp;quot; (0 Children) &lt;/li&gt;           &lt;/ul&gt;         &lt;/li&gt;       &lt;/ul&gt;     &lt;/li&gt;   &lt;/ul&gt; &lt;/code&gt;  &lt;p&gt;In order to apply meaning to the expression, we define the convention that the first child represents some operation which has to be performed on all its siblings in order, which when applied, results in the value associated with the first child. Further, we define that the value of a node is the value of the first child.&lt;/p&gt;  &lt;p&gt;In our example case, we define that the value of the Root node is the value of the anonymous &amp;quot;&amp;gt;&amp;gt;&amp;quot; node, which in turn is the value of the &amp;quot;+&amp;quot; node, which in turn is the value resulting from applying the &amp;quot;+&amp;quot; function on &amp;quot;1&amp;quot;, &amp;quot;2&amp;quot;, &amp;quot;3&amp;quot; and &amp;quot;4&amp;quot;.&lt;/p&gt;  &lt;p&gt;We notice that we have now answered the first question &amp;quot;How do we merge the results&amp;quot;.&lt;/p&gt;  &lt;p&gt;To answer the second question, let's take a closer look at the &lt;code&gt;Evaluate&lt;/code&gt; function of the &lt;code&gt;Expression&lt;/code&gt; class, shown here in its simplified form: &lt;/p&gt; &lt;code&gt;   &lt;p&gt;public Expression Evaluate()      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; switch (this.Children.Count)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case 0:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; /* atomic value */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (this.Token)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SExprStart:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.ValidName:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.Text:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.ValidNumber:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SingleQuotedText:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.DoubleQuotedText:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.SetValue(this.TokenValue);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new EvaluatorException(this, &amp;quot;Evaluate Error: Unknown Token!&amp;quot;);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return _this;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case 1:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; /* s-expr or root node */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.SetValue(this.Children[0].Evaluate());       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; /* function call */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // apply first child to the remaining children       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.SetValue(Apply(this.Children[0], this.Children.Skip(1).ToList()));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;We can see the straightforward processing of the Root and Atom cases. The &lt;code&gt;default&lt;/code&gt; case deals with the situation where the first child needs to be &amp;quot;applied&amp;quot; on the other children. &lt;code&gt;Apply&lt;/code&gt; is the most elaborate function in this project, but it's quite simple really. If all we did was addition, this is what &lt;code&gt;Apply()&lt;/code&gt; would look like:&lt;/p&gt; &lt;code&gt;   &lt;blockquote&gt;     &lt;p&gt;private static Expression Apply(Expression Functor, List&amp;lt;Expression&amp;gt; Arguments)        &lt;br /&gt;{         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; string strFunc = Functor.TokenValue;         &lt;br /&gt;&lt;/p&gt;      &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; switch (strFunc.ToLower())        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #region SUM/CONCAT         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case &amp;quot;+&amp;quot;:         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case &amp;quot;add&amp;quot;:         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case &amp;quot;sum&amp;quot;:         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Functor.SetValue(Arguments.Aggregate(0.0d, (result, x) =&amp;gt; result += x.Evaluate().ValueAsNumber);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { } &lt;/p&gt;      &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Functor.SetNil();        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #endregion &lt;/p&gt;      &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }        &lt;br /&gt;}&lt;/p&gt;   &lt;/blockquote&gt; &lt;/code&gt;  &lt;p&gt;The lambda expressions and List extension functions in C# make writing the processor sections a breeze. It's easy to see how the first child's value (the &lt;code&gt;Functor&lt;/code&gt; argument to &lt;code&gt;Apply&lt;/code&gt;)&amp;#160; is set to the sum of the other children (the &lt;code&gt;Arguments&lt;/code&gt; argument to &lt;code&gt;Apply&lt;/code&gt;). &lt;/p&gt;  &lt;p&gt;We are only left with one major issue to discuss - that of the value &lt;em&gt;type&lt;/em&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-3533297027355511553?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/07/post-3-expression-evaluator-expression.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-393824189807423540</guid><pubDate>Wed, 30 Jul 2008 10:01:00 +0000</pubDate><atom:updated>2008-08-03T11:37:28.991+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>brightsword</category><category domain='http://www.blogger.com/atom/ns#'>brightsword.eden</category><category domain='http://www.blogger.com/atom/ns#'>computer science</category><title>Post 2: Expression Evaluator - Building an Expression Tree</title><description>&lt;p&gt;The &lt;code&gt;Parse&lt;/code&gt; function described in the previous posts allows us to specify a &lt;code&gt;ParseEventHandler&lt;/code&gt; delegated function which will be called-back by the parser.&lt;/p&gt;  &lt;p&gt;We use this function to monitor the parsing of an expression string, and build a corresponding expression tree, which can then be evaluated. This is one of several approaches we could take for the evaluation process - alternatively, we could proceed with the evaluation &lt;em&gt;in-situ&lt;/em&gt;, with a makeshift stack. I took this approach because it allows us to re-use the expression strings without having the re-parse - which is something we'll need to support user-defined functions.&lt;/p&gt;  &lt;p&gt;The building of the expression tree is straightforward. We require a simple class to keep track of the Root node of the expression, and the Current node - which represents the S-Expression being parsed currently.&lt;/p&gt;  &lt;p&gt;We write a simple &lt;code&gt;ParseEventHandler&lt;/code&gt; delegate, which hooks the SExprStart state to signify the creation of a sub-tree, and the Atom state to signify leaf nodes of the expression tree. We pass along a &lt;code&gt;ParserContext&lt;/code&gt; object to keep a reference to the Root and the Current nodes of the expression tree.&lt;/p&gt; &lt;code&gt;   &lt;p&gt;public class ParserContext      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public Expression Root { get; private set; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public Expression Current { get; set; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public ParserContext(Expression Root)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.Root = Root;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.Current = Root;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;The &lt;code&gt;ParseEventHandler&lt;/code&gt; function is simple and elegant. All we're doing here is listening for three events:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;SExprStart : Signifying a new S-Expression child. Our handler creates a child and sets it as the current parent, so future nodes will get bound to it. &lt;/li&gt;    &lt;li&gt;SExprFinish: Signifying the completion of the current S-Expression. Our handler &amp;quot;pops the stack&amp;quot;, as it were, and marks the parent node as the current parent. &lt;/li&gt;    &lt;li&gt;Atom: Signifying a leaf-node child of the current parent. Simply creates and attaches a leaf-node, leaving the current parent intact. &lt;/li&gt; &lt;/ul&gt; &lt;code&gt;   &lt;p&gt;protected static void ParseEventHandler(ParseEventArgs e)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ParserContext pctx = e.ParserContext as ParserContext;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (pctx == null) return; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; switch (e.Token)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SExprStart:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pctx.Current = new Expression(pctx.Current, &amp;quot;&amp;gt;&amp;gt;&amp;quot;, e.State, e.Token);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SExprFinish:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pctx.Current = pctx.Current.Parent;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; switch (e.State)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_PARSESTATE.Atom:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression exIgnore = pctx.Current.NewChild(e.TokenValue, e.State, e.Token);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_PARSESTATE.Failure:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new ParseException(String.Format(&amp;quot;*** FAILURE {0}] : [ {1} ], {2}, {3}&amp;quot;, e.ErrorDescription, e.TokenValue, e.State, e.Token));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;} &lt;/p&gt; &lt;/code&gt;  &lt;p&gt;To actually call the parser, all we do is pass in a reference to the handler and context instance:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;Expression Root = new Expression();&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;Parser.Parse(pszExpression, new ParseEventHandler(ParseEventHandler), new ParserContext(Root));&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&lt;code&gt;// ... at this point, Root has been built up, or parsing has failed and thrown an exception &lt;/code&gt;&lt;/p&gt;  &lt;p&gt;We'll discuss the &lt;code&gt;Expression&lt;/code&gt; class in detail in the next post.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-393824189807423540?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/07/post-2-expression-evaluator-building.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-8769809160966658375</guid><pubDate>Wed, 30 Jul 2008 07:11:00 +0000</pubDate><atom:updated>2008-08-02T12:44:48.362+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>family</category><title>Eden is Born!</title><description>&lt;p&gt;Eden Trinity Azariah was born today in Moncton, Canada to my brother and sister-in-law!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/john.azariah/SJPz3SypdGI/AAAAAAAAESc/lpOMXc4xiiQ/s1600-h/IMG_4346%5B1%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="431" alt="IMG_4346" src="http://lh5.ggpht.com/john.azariah/SJPz-9tGzJI/AAAAAAAAESg/0wYBbR29zNE/IMG_4346_thumb.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Mom and baby are doing well!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/john.azariah/SJP0I7DswqI/AAAAAAAAESk/4MWzGzXCRwA/s1600-h/IMG_4358%5B1%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="431" alt="IMG_4358" src="http://lh5.ggpht.com/john.azariah/SJP0LFdthoI/AAAAAAAAESo/Xu39eCOujlg/IMG_4358_thumb.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Big sister Tabitha couldn't be happier!&lt;/p&gt;  &lt;p&gt;Welcome, baby Eden!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-8769809160966658375?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/07/eden-is-born.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-1372160782098087555</guid><pubDate>Fri, 25 Jul 2008 02:01:00 +0000</pubDate><atom:updated>2008-08-03T11:37:28.991+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>brightsword</category><category domain='http://www.blogger.com/atom/ns#'>brightsword.eden</category><category domain='http://www.blogger.com/atom/ns#'>computer science</category><title>Post 1: Expression Evaluator - The Parser</title><description>&lt;p&gt;We can take the classic state-machine approach to build the S-Expression parser, and use the C# event constructs to perform appropriate callbacks as we encounter specific states.&lt;/p&gt;  &lt;p&gt;The &lt;code&gt;Parser&lt;/code&gt; class contains a single static function which can parse a string and call the handler at appropriate points for further processing. A &lt;em&gt;context&lt;/em&gt; object is passed through along to the handler for its use.&lt;/p&gt;  &lt;p&gt;The &lt;code&gt;Parse&lt;/code&gt; function consists of a single loop that walks the string from beginning to end, using the &lt;code&gt;Tokenizer&lt;/code&gt; helper class to break up the string into lexically interesting chunks, and transitioning the state machine through the various states. We'll discuss &lt;code&gt;Tokenizer::NextToken&lt;/code&gt; in detail next.&lt;/p&gt;  &lt;p&gt;The state machine has the following states: &lt;/p&gt; &lt;code&gt;   &lt;ul&gt;     &lt;li&gt;Start &lt;/li&gt;      &lt;li&gt;Finish &lt;/li&gt;      &lt;li&gt;SExprStart &lt;/li&gt;      &lt;li&gt;SExprFinish &lt;/li&gt;      &lt;li&gt;AtomOrSExpr &lt;/li&gt;      &lt;li&gt;Atom &lt;/li&gt;      &lt;li&gt;Failure &lt;/li&gt;   &lt;/ul&gt; &lt;/code&gt;  &lt;p&gt;Each of these states is of interest to the caller of the &lt;code&gt;Parse&lt;/code&gt; function, as each state represents effectively a result of parsing the string.&lt;/p&gt;  &lt;p&gt;The &lt;code&gt;Parse&lt;/code&gt; results for a simple string are given - it's easy to walk through the body of the &lt;code&gt;Parse&lt;/code&gt; function and see why the results came out the way they did:&lt;/p&gt; &lt;code&gt;   &lt;p&gt;Input String: (test &amp;quot;(f1 a b)&amp;quot; (f2 c d)) &lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Start, &lt;/li&gt;      &lt;li&gt;SExprStart, ( &lt;/li&gt;      &lt;li&gt;Atom - ValidName, test &lt;/li&gt;      &lt;li&gt;Atom - DoubleQuotedText, (f1 a b) &lt;/li&gt;      &lt;li&gt;SExprStart, ( &lt;/li&gt;      &lt;li&gt;Atom - ValidName, f2 &lt;/li&gt;      &lt;li&gt;Atom - ValidName, c &lt;/li&gt;      &lt;li&gt;Atom - ValidName, d &lt;/li&gt;      &lt;li&gt;SExprFinish, ) &lt;/li&gt;      &lt;li&gt;SExprFinish, ) &lt;/li&gt;      &lt;li&gt;Finish, &lt;/li&gt;   &lt;/ul&gt; &lt;/code&gt;  &lt;p&gt;The grammar we described earlier define what state we want to be in after encountering a particular token, and this structure is reflected in the state machine. The &lt;code&gt;Tokenizer&lt;/code&gt; also goes a little further and reports if the text it encounters would conform to a valid variable name, or a valid number. This helps us when we want to do some further processing of the parsed results.&lt;/p&gt; &lt;code&gt;   &lt;p&gt;public static E_PARSERESULT Parse(this string psz, ParseEventHandler ParseEventHandler, object context)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; int sStart = 0, sFinish = 0; int expr_nest = 0; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; E_PARSESTATE state = E_PARSESTATE.Start; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; while (sFinish &amp;lt;= psz.Length)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (state)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_PARSESTATE.Start:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; expr_nest = 0; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // dispense the notification.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, state, E_TOKEN.MAX, 0, 0)); &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.AtomOrSExpr;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_PARSESTATE.Finish:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (expr_nest != 0) { state = E_PARSESTATE.Failure; break; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // dispense the notification.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, state, E_TOKEN.MAX, 0, 0)); &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // we're done...      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return E_PARSERESULT.S_OK;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; E_TOKEN tok = Tokenizer.NextToken(psz, sFinish, out sStart, out sFinish); &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (state)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_PARSESTATE.SExprStart:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // SExpr ::= SExprStart (Atom | SExpr)* SExprFinish       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (tok)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SExprStart: // (       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; expr_nest++; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, E_PARSESTATE.SExprStart, tok, sStart, sFinish));      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.AtomOrSExpr;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.EOF:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sFinish = sStart; state = E_PARSESTATE.Finish;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, E_PARSESTATE.SExprStart, tok, sStart, sFinish, &amp;quot;Unexpected token found instead of SExprStart&amp;quot;, 0));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.Failure;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_PARSESTATE.AtomOrSExpr:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (tok)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.DoubleQuotedText:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SingleQuotedText:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, E_PARSESTATE.Atom, tok, sStart+1, sFinish-1));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.AtomOrSExpr;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.ValidName:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.ValidNumber:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.Text:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, E_PARSESTATE.Atom, tok, sStart, sFinish));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.AtomOrSExpr;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SExprStart: // (      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sFinish = sStart; //rewind token       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.SExprStart;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SExprFinish: // )      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sFinish = sStart; //rewind token       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.SExprFinish;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.EOF:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.Finish;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, E_PARSESTATE.Failure, tok, sStart, sFinish, &amp;quot;Unexpected token found without matching SExprFinish&amp;quot;, 0));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.Failure;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_PARSESTATE.SExprFinish:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (tok)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.SExprFinish: // )       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; expr_nest--; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, E_PARSESTATE.SExprFinish, tok, sStart, sFinish));      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = (expr_nest == 0) ? E_PARSESTATE.Finish : E_PARSESTATE.AtomOrSExpr;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_TOKEN.EOF:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sFinish = sStart; state = E_PARSESTATE.Finish;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, E_PARSESTATE.Failure, tok, sStart, sFinish, &amp;quot;Unexpected token found instead of SExprFinish&amp;quot;, 0));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state = E_PARSESTATE.Failure;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case E_PARSESTATE.Failure:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, E_PARSESTATE.Failure, E_TOKEN.MAX, sStart, sFinish, &amp;quot;Parser Failure&amp;quot;, 0));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return E_PARSERESULT.E_FAILURE; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }; // while (curpos &amp;lt; psz.Length) &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParseEventHandler(new ParseEventArgs(psz, context, E_PARSESTATE.Failure, E_TOKEN.MAX, sStart, sFinish));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; return E_PARSERESULT.E_FAILURE;      &lt;br /&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;The &lt;code&gt;Tokenizer&lt;/code&gt; helper class has a bunch of text processing functions which simply make life easier. The primary function, that of tokenizing - or chopping up the input text - is carried out by the &lt;code&gt;NextToken&lt;/code&gt; function:&lt;/p&gt; &lt;code&gt;   &lt;p&gt;public static E_TOKEN NextToken(string psz, int s, out int sTokBegin, out int sTokEnd)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sTokBegin = -1; sTokEnd = psz.Length - 1;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (s &amp;lt; 0) { return E_TOKEN.EOF; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; int sb = SnarfWhiteSpace(psz, s); &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; sTokBegin = sb;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (sb == psz.Length) { return E_TOKEN.EOF; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // (      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (IsOpenParen(psz[sb]))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sTokEnd = ++sb; return E_TOKEN.SExprStart;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // )      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (IsCloseParen(psz[sb]))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sTokEnd = ++sb; return E_TOKEN.SExprFinish;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // '...'      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; int se = sb;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (psz[sb] == '\'')       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return SnarfQuotedText(psz, sb, out sTokBegin, out sTokEnd, psz[sb]) ? E_TOKEN.SingleQuotedText : E_TOKEN.EOF;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb = se; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; // &amp;quot;...&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; se = sb;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (psz[sb] == '&amp;quot;')       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return SnarfQuotedText(psz, sb, out sTokBegin, out sTokEnd, psz[sb]) ? E_TOKEN.DoubleQuotedText : E_TOKEN.EOF;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; sb = se; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sb++; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; bool fOK = true;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for (; (sb &amp;lt; psz.Length) &amp;amp;&amp;amp; fOK; sb++)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; char ch = psz[sb];       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; fOK = (!(IsWhiteSpace(ch) || IsOpenParen(ch) || IsCloseParen(ch)));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!fOK) { --sb; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (sb &amp;lt;= psz.Length)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sTokEnd = sb; sTokBegin = SnarfWhiteSpace(psz, sTokBegin); &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string strToken = psz.Substring(sTokBegin, sTokEnd - sTokBegin); &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (IsValidName(strToken)) { return E_TOKEN.ValidName; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (IsValidNumber(strToken)) { return E_TOKEN.ValidNumber; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return E_TOKEN.Text;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; sTokEnd = sb; return E_TOKEN.EOF;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;The tokenizing approach is a throwback to my C/C++ days, when strings were null-delimited arrays of characters, and traipsing over them using a bunch of indices to keep track of sub-strings were the most efficient way of dealing with them. The &lt;code&gt;NextToken&lt;/code&gt; function is passed in a tentative starting point (typically the point where it left off last) and it returns the next interesting token encountered after that point in the string.&lt;/p&gt;  &lt;p&gt;A few points of note:&lt;/p&gt;  &lt;p&gt;The &lt;code&gt;Tokenizer&lt;/code&gt; class has been made internal to the &lt;code&gt;Parser&lt;/code&gt; class and therefore has no interface footprint. Of course, with the C# partial class structure, we could put it in a separate file but keep it as a part of the Parser class.&lt;/p&gt;  &lt;p&gt;We take care to ensure that the &lt;code&gt;Parser&lt;/code&gt; and &lt;code&gt;Tokenizer&lt;/code&gt; are both static classes (with all static functions, obviously). This is a great way to ensure that there is no state associated with the classes themselves, so the classes are multi-thread ready. &lt;/p&gt;  &lt;p&gt;One sweet syntactic bonus is to write the &lt;code&gt;Parse&lt;/code&gt; function as an extension class of the &lt;code&gt;String&lt;/code&gt; type, so if you include the namespace containing the &lt;code&gt;Parser&lt;/code&gt;, all strings automatically have the &lt;code&gt;Parse&lt;/code&gt; function stuck on to them - very chic!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-1372160782098087555?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/07/post-1-expression-evaluator-parser.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-1777577620297388683</guid><pubDate>Mon, 21 Jul 2008 10:01:00 +0000</pubDate><atom:updated>2008-08-03T11:37:28.992+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>brightsword</category><category domain='http://www.blogger.com/atom/ns#'>Yet Another Bright Idea</category><category domain='http://www.blogger.com/atom/ns#'>brightsword.eden</category><category domain='http://www.blogger.com/atom/ns#'>computer science</category><title>Part 0: Building a Basic Expression Evaluator</title><description>&lt;p&gt;Quite often in our work, we come across situations where we would have to customize some business-logic quickly and on-the-fly. One such situation is when we have a workflow coded up, but the logic for transitioning between states is not fully known or is likely to change when the customers finally decide what they want.&lt;/p&gt;  &lt;p&gt;In some of such situations, we would really love it if we could store the state transition-logic in a form that is easily editable at customization-time and dynamically evaluable to allow the workflow's behaviour to evolve and refine over time.&lt;/p&gt;  &lt;p&gt;Being a classic computer scientist at heart, I decided to see if we could embed a little LISP evaluation engine and perhaps write and store the customization logic as a LISP expression, which would be evaluated at run-time and allow for the flexibility we needed. Then, being a classic masochist, I decided to spend a few days and see if I could build the evaluation engine itself. (Actually, I did google up for an embeddable LISP engine, but found that the gymnastics involved in integrating the engine into our environment wouldn't be worth the trouble!)&lt;/p&gt;  &lt;p&gt;The evaluator we built takes a string s-expression value, and reduces it to a single scalar value. We built it in stages, and I'll describe the building process similarly. Unlike a full blown LISP implementation, all our functions return a single scalar - so there isn't support for the &lt;code&gt;cons&lt;/code&gt; primitive&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The lexical structure for the little language we're building is:&lt;/p&gt; &lt;code&gt;   &lt;ul&gt;     &lt;li&gt;&lt;font size="2"&gt;Program ::= Atom | SExpr&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font size="2"&gt;Atom ::= &lt;em&gt;number &lt;/em&gt;|&lt;em&gt; boolean &lt;/em&gt;| &lt;em&gt;string&lt;/em&gt;&amp;#160;&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font size="2"&gt;SExpr ::= &amp;quot;(&amp;quot; Atom | SExpr &amp;quot;)&amp;quot;&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font size="2"&gt;&lt;em&gt;number &lt;/em&gt;is a pattern conforming to the following IEEE regular expression for a floating point: &lt;em&gt;^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]*\\.?[0-9]+)?$&lt;/em&gt;.&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font size="2"&gt;&lt;em&gt;boolean&lt;/em&gt; is one of the following strings : &lt;em&gt;t&lt;/em&gt;, &lt;em&gt;true&lt;/em&gt;, &lt;em&gt;false&lt;/em&gt;, &lt;em&gt;nil&lt;/em&gt; and &lt;em&gt;f&lt;/em&gt;. Each corresponding to its commonly known, self-explanatory value&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font size="2"&gt;&lt;em&gt;string&lt;/em&gt; is a pattern conforming to an unquoted sequence of non-white-space characters, or a quoted sequence of characters including white-space&lt;/font&gt; &lt;/li&gt;   &lt;/ul&gt; &lt;/code&gt;  &lt;p&gt;&lt;font size="2"&gt;Semantically, we will use the general LISP convention where the &lt;code&gt;car&lt;/code&gt; or first element of the SExpr is the function we want to apply to the &lt;code&gt;cdr&lt;/code&gt; or the remainder of the SExpr. We will also pre-define some of the well-known functions we want to process.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;So for example, we might want to evaluate the following strings and expect the associated results:&lt;/p&gt; &lt;code&gt;   &lt;ul&gt;     &lt;li&gt;(+ 1 2 3 4) =&amp;gt; 10 &lt;/li&gt;      &lt;li&gt;(+ 1 2 (* 3 2)) =&amp;gt; 8 &lt;/li&gt;      &lt;li&gt;(+ &amp;quot;hello&amp;quot; &amp;quot; &amp;quot; &amp;quot;world&amp;quot;) =&amp;gt; &amp;quot;hello world&amp;quot; &lt;/li&gt;      &lt;li&gt;(and (&amp;gt; 4 2 1) (&amp;lt;= 3 4 4 5)) =&amp;gt; true &lt;/li&gt;   &lt;/ul&gt; &lt;/code&gt;  &lt;p&gt;The cool thing to notice is that we want our engine to deal with dynamically typing the values into either numbers, boolean values or strings. The well-known functions also have to be intelligent and decide, for example, when to sum numbers and when to concatenate strings.&lt;/p&gt;  &lt;p&gt;Of course, as the engine evolves, we want to pay special attention to integrating it into an environment from which it could be called, and introduce support for custom functions to supplement the well-known ones. Further improvements would include support for recursive and mutually recursive functions.&lt;/p&gt;  &lt;p&gt;The posts following will outline the approach to building the evaluation engine and providing the support we desire.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-1777577620297388683?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/07/part-0-building-basic-expression.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-3468096372521808750</guid><pubDate>Tue, 24 Jun 2008 06:29:00 +0000</pubDate><atom:updated>2008-08-02T12:42:04.779+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>the antipodes</category><category domain='http://www.blogger.com/atom/ns#'>meandering around</category><category domain='http://www.blogger.com/atom/ns#'>family</category><title>Home!</title><description>&lt;p&gt;After the disappointment of the weekend, we decided we'd look around the area some more, and look at the other houses we had liked, and other options. We're praying hard that we'll find the right home soon!&lt;/p&gt;  &lt;p&gt;We just walked past the agents on Playne Street - picking up brochures, and walked into Dawes First National. The agent gave us brochures of some houses, and then mentioned that a new home had come up for sale in the same neighbourhood of the other two houses we had put offers in on!&lt;/p&gt;  &lt;p&gt;We drove up to the new house and absolutely loved it!&lt;/p&gt;  &lt;p&gt;It's smaller than the other homes, but it has an absolutely gorgeous Australian bush garden out back, and we fell in love with it the moment we saw it. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/john.azariah/SJQIod9sQHI/AAAAAAAAESM/LuWv78OgEBk/s1600-h/26062008424%5B1%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="26062008424" src="http://lh3.ggpht.com/john.azariah/SJQFnC7Gn8I/AAAAAAAAESQ/HcYoqCBvKZI/26062008424_thumb.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;So much so that the negotiations were short and sharp. To cut a long story short, we put in an offer on the house today, and just found out that the offer had been accepted!&lt;/p&gt;  &lt;p&gt;We bought a house today! Can't wait to get it set up and have everyone visit!&lt;/p&gt;  &lt;p&gt;The only bummer was that we would have to wait an extra month for the settlement - the lady selling the house needs to find alternate accommodation - but it means we have a little more time to sort out the finances! &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/john.azariah/SJQIuut1KoI/AAAAAAAAESU/U5O0x_aITm0/s1600-h/26062008454.jpg"&gt;&amp;#160;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="26062008454" src="http://lh5.ggpht.com/john.azariah/SJQFqu4eHGI/AAAAAAAAESY/eBE5IdXiq44/26062008454_thumb.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-3468096372521808750?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/06/home.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-3261815804183711519</guid><pubDate>Sun, 22 Jun 2008 06:50:00 +0000</pubDate><atom:updated>2008-08-02T12:40:06.953+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>the antipodes</category><category domain='http://www.blogger.com/atom/ns#'>meandering around</category><title>House-hunting</title><description>&lt;p&gt;We spent the last week looking around the suburbs for houses.&lt;/p&gt;  &lt;p&gt;Went over to Upwey on Monday to look at some hill homes. The people are indeed very friendly and the place is beautiful, but owning a hill home seems to be a lot of work - lots of risk of bush-fires in the summer, and the yards are quite hard to maintain with all the falling leaves!&lt;/p&gt;  &lt;p&gt;In the meanwhile, the temporary accomodation on Lonsdale Street was turning out to be too expensive, so we've been looking at other short-term rental options. Decided on a place in Brunswick which isn't cheap, but very convenient. &lt;/p&gt;  &lt;p&gt;While Smitha went over to Brunswick to sort out the rental, I headed down to Frankston on Tuesday. We've been talking to some agents by email about interesting houses here - and we had an appointment with one of the agents. This place is quite beautiful and I think this is the better option compared to Upwey.&lt;/p&gt;  &lt;p&gt;Came back to Frankston all this week - looked at over a dozen homes! The agents are quite friendly and the market is a buyer's market but not really desperate to sell. We were able to find a few homes we liked and we took time every evening to stack-rank the houses we had seen.&lt;/p&gt;  &lt;p&gt;Here's a rainbow we caught from the car of one of the real-estate agents as they ferried us around the houses.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/john.azariah/SJQIQIYZ5HI/AAAAAAAAESE/3kjB5Ir49bs/s1600-h/20062008404%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="20062008404" src="http://lh6.ggpht.com/john.azariah/SJQISnTnNhI/AAAAAAAAESI/vMVHFngo_Ow/20062008404_thumb%5B1%5D.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On Saturday, Marcus came along with us to Frankston to check out some of the open houses. We put an offer in on one of the houses we liked most.&lt;/p&gt;  &lt;p&gt;This morning we found out that the house we had put an offer on had counter-signed the offer. Before negotiating, we decided we'd put an offer in on another house in the same neighbourhood. Called up the agent and put in the offer.&lt;/p&gt;  &lt;p&gt;We just found out that the offer on the second home was bested by someone else - by a sliver. I guess this means we aren't going to get either of these houses. We really liked the second home...&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-3261815804183711519?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2007/06/house-hunting.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-8806945871113750146</guid><pubDate>Sat, 21 Jun 2008 06:59:00 +0000</pubDate><atom:updated>2008-08-02T12:36:04.273+05:30</atom:updated><category domain='http://www.blogger.com/atom/ns#'>the antipodes</category><category domain='http://www.blogger.com/atom/ns#'>meandering around</category><title>Goodbye Lonsdale, Hello Brunswick</title><description>&lt;p&gt;The view from the Lonsdale Street place was awesome - here's a sunrise taken from the balcony!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/john.azariah/SJQHLihgkVI/AAAAAAAAER8/VclC6-1SJJg/s1600-h/16062008396%5B9%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="16062008396" src="http://lh3.ggpht.com/john.azariah/SJQHOaAJL5I/AAAAAAAAESA/lPu_rl3BCHM/16062008396_thumb%5B6%5D.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;We moved into the Brunswick Road apartment today. Thanks to Christine for giving us the link to this place!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-8806945871113750146?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/06/goodbye-lonsdale-hello-brunswick.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-7946159665906801947</guid><pubDate>Sat, 14 Jun 2008 13:19:00 +0000</pubDate><atom:updated>2008-08-03T09:57:25.323+05:30</atom:updated><title>14 June 08 - The Travels (and travails) of Marcus</title><description>&lt;p&gt;Bought a weekly Zone 1+2 pass to do the house-hunt next week. Decided that we should go over some of the suburbs to check them out again. &lt;/p&gt;  &lt;p&gt;Called Marcus at 11:00 AM and woke him up! Told him we should head out to the outer suburbs before sundown.&lt;/p&gt;  &lt;p&gt;Went over to the Library and started compiling lists of real-estate agents to call. Came back to the apartment after the library and ate lunch - sandwiches, leftover casserole and fruit. By now it was 1:00 PM, and we were still waiting for Marcus. He finally arrived - and still hadn't had anything to eat. &lt;/p&gt;  &lt;p&gt;Walked over to Flinders Street Station, and popped into Flora's - an Indian restaurant which reinforced every experience I've had of Indian food outside India - for Marcus' lunch. When we finally left Flora's at 2:00 PM and walked across the street to the station, where we found out that the next Belgrave train was at 2:30 - barely 3 hours before dark. I was quite frustrated that the whole day was more-or-less gone before we even started.&lt;/p&gt;  &lt;p&gt;The Saturday schedule on the Belgrave line consists of a Lilydale service, with a synchronized spur service off Ringwood to Belgrave, and it took about 15 minutes longer than the usual hour.&lt;/p&gt;  &lt;p&gt;We got off at Upwey and walked up the street, taking in the cool air, the fresh smell of the trees, the sound of sulphur-crested cockatoos and king parrots as they flew in formation around the trees. Definitely breathtaking in more ways than one!&lt;/p&gt;  &lt;p&gt;The property we wanted to look at was a sharp uphill walk from the station. The place itself was not attractive looking but the view around the area was phenomenal. Both Smitha and Marcus were apprehensive about the region though - given its distance from the city and the remote, hill-country feel. Personally, though, it takes me back to a happier time - back to the wooded hills of New Hampshire and Vermont, and the simple wisdom and charm of the people who live there.&lt;/p&gt;  &lt;p&gt;Stopped off at a real-estate agent's office on the way back to Upwey station, just to get a feel for the people and the available houses. He took us to see a beautiful house - too big and expensive for us - and we decided to head back home. It was already dark even though it was only around 5:30 PM. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/john.azariah/SFYWSI4W0xI/AAAAAAAAES8/n0rpaYj1AKs/s1600-h/14062008394%5B1%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="14062008394" src="http://lh3.ggpht.com/john.azariah/SFYWajjaiZI/AAAAAAAAETA/HN2CIz--AwA/14062008394_thumb%5B1%5D.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;We got off at Spencer Street, headed over to the Crown Casino Food Court for a doner kebab, parted ways with Marcus and headed for home. &lt;/p&gt;  &lt;p&gt;As we walked back home from Parliament Station, we called Tabitha and sang her a Happy Birthday - she was thrilled - and then called and talked to the families at home in India. &lt;/p&gt;  &lt;p&gt;Then we sat down and took stock of the day...&lt;/p&gt;  &lt;p&gt;We'll go over the same checklist of things we're looking for in a home for any of the houses we'll consider - distance from the city, distance from the railway station to the home, distance to church, grocery stores, hospitals, the cost factor, the construction quality, the size of the home, the general value for money and other factors which aren't so tangible like safety, security and the attractiveness of the area.&lt;/p&gt;  &lt;p&gt;That in mind, next week should be interesting - we've lined up at least a dozen agents in the Upwey, Frankston and Berwick areas, and hopefully we'll be able to get a nice home soon!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-7946159665906801947?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/06/14-june-08-travels-and-travails-of.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-1387050055780846583</guid><pubDate>Fri, 13 Jun 2008 13:19:00 +0000</pubDate><atom:updated>2008-06-16T12:58:41.766+05:30</atom:updated><title>13 June 08 - Friday the Thirteenth</title><description>&lt;p&gt;Slept in till 9:30 this morning. Decided to have brunch before heading out to the city - famous Aussie lamb sausages. While I cooked up the sausages, Smitha packed our bags and tidied the place up, because we may have to move to a place in St. Kilda tomorrow morning.&lt;/p&gt;  &lt;p&gt;Yet another day hunting for Internet access. Walked over to &amp;quot;Australia on Collins&amp;quot; - a massive mall on Collins Street - where there's free access for everyone but no power points. Checked mail and sent off a bunch of messages.&lt;/p&gt;  &lt;p&gt;Left around half-past-three for St. Kilda - tram 96 from Bourke Street. It took an awfully long time to finally reach Hotel Esplanade, by which time we had received three increasingly agitated calls from the agent exclaiming she'd been waiting for us! When we finally met her, she exuded such a thorny demeanour that I'd decided that there was no way we were dealing with this woman! Despite her protestations that she was a &amp;quot;precise&amp;quot; woman, she hadn't any details about whether we had to pay bills, and generally speaking, spoke extremely rudely! Called her up from the tram on the way back to decline her graceless offer!&lt;/p&gt;  &lt;p&gt;Met Marcus at our apartment. Went over to the Elephant and Wheelbarrow for a pint of Guinness. It was nice to savour the bitter taste and take in the noise and bustle of an English pub on football night. Walked up and down the streets looking for a place to eat. Finally wandered into the local Greek Restaurant and had a wonderful meal of grilled lamb and chicken, those famous Greek dips - tzatziki, taramasalata, hummus and babaghanouj - with pita bread.&lt;/p&gt;  &lt;p&gt;Wonderful evening!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-1387050055780846583?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/06/13-june-08-friday-thirteenth.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-7958952282615158184</guid><pubDate>Thu, 12 Jun 2008 11:17:00 +0000</pubDate><atom:updated>2008-06-16T12:57:34.580+05:30</atom:updated><title>12 June 08 - Part 1 : Roaming Around The Countryside</title><description>&lt;p&gt;Woke up early today. Walked over to the State Library and tried to get in with the laptop bag. The library staff are capricious about letting in that bag - the last time they let me go in, and today they asked me to check it into a locker because it didn't fit the silly frame.&lt;/p&gt;  &lt;p&gt;Had a coffee at Starbucks and thought I'd get wireless access there - but found out that you need a Telstra connection to get that. Gave up on checking mail today.&lt;/p&gt;  &lt;p&gt;Bought a Zone 1+2 day pass and decided to do some scouting around the area.&lt;/p&gt;  &lt;p&gt;First off towards Belgrave - we'd seen a couple of places out in Upper Fern Tree Gully and Upwey and we wanted to see how long it would take to travel there and back. As the train made its way towards the outer suburbs, we were struck by how quiet the suburbs are. Melbourne itself isn't a bustling city - not like New York or London or even Sydney - but the 'burbs are right quiet!&lt;/p&gt;  &lt;p&gt;Starting at Boronia, we got views of the mountains and the forests that make up the Dandenongs. The train was mostly empty by now - our carriage had a couple of high-school kids listening to music and making out.&lt;/p&gt;  &lt;p&gt;Boronia - Ferntree Gully - Upper Ferntree Gully - Upwey - Tecoma - Belgrave&lt;/p&gt;  &lt;p&gt;The views are amazing! The train runs along the flank of a mountain with the tops of trees below it on one side, and more trees towering up on the other. It would be amazing to live here - if only it wasn't an hour outside the city!&lt;/p&gt;  &lt;p&gt;Belgrave Station Street is a short stretch of little curio shops and restaurants and real-estate agent offices. We have a Fish 'n Chips lunch sold by a friendly but miserly Greek vendor at one of the restaurants on the street. Walked back down to the station after lunch and took the train back to Richmond.&lt;/p&gt;  &lt;p&gt;From Richmond we took the Frankston Line to see that side of the country. It's now around 3:00 and some of the schools seem to be letting out. The train goes on towards Aspendale and the suburbs we think we might to live in.&lt;/p&gt;  &lt;p&gt;Aspendale - Edithvale - Chelsea - Bonbeach - Carrum - Seaford - Kannanook&lt;/p&gt;  &lt;p&gt;The train runs along the Nepean Highway - we get glimpses of the turquoise ocean and the beach. Again - it would be lovely to live here. There are even a few &amp;quot;For Sale&amp;quot; signs up - we need to call Dan, the real-estate agent we've been in touch with from when we were in India.&lt;/p&gt;  &lt;p&gt;The school kids on the train are lively and noisy, and they all seem to live within a few stops of school. There seem to be a lot more people living in these suburbs than on the Belgrave line, I think.&lt;/p&gt;  &lt;p&gt;We reach Frankston and it starts to rain. This area has a rugged maritime beauty to it - sand and sea and gray sky pouring with rain.&lt;/p&gt;  &lt;p&gt;It's only a 20 minute bus-ride to Dandenong City from here and we take the bus from just outside the station. Acres of quiet green farmland go by and the bus weaves in and out of bus-stops marking out the little streets crossing the highway. We reach Dandenong and get in to the station to get to Berwick.&lt;/p&gt;  &lt;p&gt;The 4:20 to Berwick was cancelled - the next one is about 30 minutes later but lands up being delayed a quarter of an hour more. When it arrives it's crowded. Everyone is quite upset with the delays and two school girls on the train are confused about the station they want to get off. The display on the train says that the next station was the one that went by six stations ago! When they finally realize that they needed to get off where we got on, they're hysterical...&lt;/p&gt;  &lt;p&gt;We finally arrive at Berwick and wait at the station for our friend to pick us up...&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-7958952282615158184?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/06/12-june-08-part-1-roaming-around.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-6900573451148564451</guid><pubDate>Wed, 11 Jun 2008 10:58:00 +0000</pubDate><atom:updated>2008-08-03T09:56:25.625+05:30</atom:updated><title>11 June 08 - Wandering around Melbourne</title><description>&lt;p&gt;Woke up around 7:30 AM. Smitha made scrambled eggs and tea for breakfast. &lt;/p&gt;  &lt;p&gt;Walked down to Bourke Street and took the tram to South Melbourne to get to York Street. Went to the Centrelink building but was told there was no need for me to register at all! Silly Marcus. Walked back and took the tram to Parliament. Went to the ATO and signed up for the TFN. Walked down to the apartment and had lunch - ham and cheese and fruit. Opened the bank account. &lt;/p&gt;  &lt;p&gt;Since we had a few hours to kill and a Zone 1 day-pass in our hands, we decided to take a train out of Southern Cross as far as we could on the Frankston line - all the way to Bentleigh. The sun was setting by the time we reached, and we walked up and down the main street, looking at all the closed shops and the lighted, but empty, real-estate offices. It sure gets sleepy outside the city.&lt;/p&gt;  &lt;p&gt;We came back to Southern Cross and took the tram over to Crown Casino to meet Marcus for dinner there. The buffet has a great spread and we were stuffed by the time we left - it was nice to have carved ham slices again. Walked around and down the bank of the Yarra river and waited for the tram back. Walked back to Lonsdale at 11:00 pm but we felt quite safe. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/john.azariah/SJUzZUSF7CI/AAAAAAAAESs/JOR3piUcJzw/s1600-h/11062008379%5B1%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="11062008379" src="http://lh4.ggpht.com/john.azariah/SFYUbcn8MRI/AAAAAAAAESw/sS5iEUgPxEA/11062008379_thumb%5B1%5D.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/john.azariah/SFYUdRJalSI/AAAAAAAAES0/agl-AbqAEQ4/s1600-h/11062008380%5B1%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="11062008380" src="http://lh5.ggpht.com/john.azariah/SFYUf2M3CKI/AAAAAAAAES4/BMsncq3FB9E/11062008380_thumb%5B1%5D.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;It was a long day and we had a blast! &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-6900573451148564451?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/06/11-june-08-wandering-around-melbourne.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-3276831535477811181</guid><pubDate>Tue, 10 Jun 2008 09:54:00 +0000</pubDate><atom:updated>2008-06-16T12:49:08.718+05:30</atom:updated><title>10 June 08 - First Day In Melbourne</title><description>&lt;p&gt;Woke up at 11:00 AM - needed all that sleep, and besides, that's 5:30 AM Indian time! - the rest was most welcome though. &lt;/p&gt;  &lt;p&gt;Walked up to the DIMIA office at the corner of Spring and Lonsdale - got directions to the closest Centrelink Office (York Street or Footscray). Walked back down to Commonwealth Bank and found out details about getting a bank account. Then off to Safeway to do a proper grocery run and get something for lunch.&lt;/p&gt;  &lt;p&gt;Found some wonderful Washington cherries and a couple of apples, rocket lettuce, swiss cheese and ham, crusty sesame rolls and some egg-salad from the deli. Came back to the apartment and made ham &amp;amp; cheese sandwiches for lunch. &lt;/p&gt;  &lt;p&gt;Walked to the State Library after lunch. It's such a pleasure to go back to a proper library and be surrounded by books and music and people reading and studying - I'd quite forgotten the feeling after my college days and I must say I was very happy to be back.&lt;/p&gt;  &lt;p&gt;Stopped off in the QV building and managed to get a post-paid connection with a phone for Smitha and a pre-paid SIM for myself. Now we are no longer incommunicado! Called Marcus who was waiting for us by that time at the apartment. Hung out with Marcus for a while, and then cooked dinner (green-pepper and sausage casserole) and ate. Tasmanian Butter is yummy.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-3276831535477811181?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/06/10-june-08-first-day-in-melbourne.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-8555743264722992240</guid><pubDate>Mon, 09 Jun 2008 07:09:00 +0000</pubDate><atom:updated>2008-06-16T12:39:47.218+05:30</atom:updated><title>Hello From Melbourne</title><description>&lt;p&gt;Arrived in Tullamarine after a couple hours to change planes in Bangkok.&lt;/p&gt;  &lt;p&gt;Thai Airways air service was average in every way - below-average in terms of food - but ok otherwise. The lack of fluency in English really shows in the way the air service staff interact with the passengers. Watched &amp;quot;Horton Hears A Who&amp;quot; and a few episodes of &amp;quot;Prison Break&amp;quot; and got to sleep on the BKK-MEL sector with an extra free seat between us. The good thing I could say was that we landed roughly on time in both Bangkok and Melbourne.&lt;/p&gt;  &lt;p&gt;Melbourne immigration staff was friendly and efficient. Customs and immigration were a breeze, and we stepped out into the cool Melbourne air an hour or so before I thought we would.&lt;/p&gt;  &lt;p&gt;Took a taxi from the airport to Lonsdale Street - cost us 55 bucks but I didn't have a choice! Had to wait on the street with all the baggage for Marcus and the manager of the little studio apartment we're renting. Marcus arrived to meet us after we waited for 20 minutes on the street and the manager soon after. The apartment is on the 12th floor, and is cute and surprisingly comfortable. The view out onto Lonsdale Street and the edge of China Town is beautiful.&lt;/p&gt;  &lt;p&gt;Marcus walked with us to get some basic supplies - eggs, milk and cereal - for tomorrow's breakfast. It's quite cool outside - around 12 degrees C - and Smitha and I were very happy to have a warm bed for the night. &lt;/p&gt;  &lt;p&gt;We'll get to see Melbourne in daylight tomorrow...&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-8555743264722992240?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/06/hello-from-melbourne.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-7488482453716267310</guid><pubDate>Sun, 08 Jun 2008 18:25:00 +0000</pubDate><atom:updated>2008-06-16T13:05:36.440+05:30</atom:updated><title>Leaving From Bangalore</title><description>&lt;p&gt;We're leaving today for Melbourne via Bangkok.&lt;/p&gt;  &lt;p&gt;Got to fly out from the &amp;quot;spanking new&amp;quot; BIAL airport. The drive up here from home was pretty peaceful, since we live on the outside of the Ring Road and don't have to deal with any traffic to get to the airport.&lt;/p&gt;  &lt;p&gt;Goodbyes are always hard, and today was no different. The whole family turned up to send us off (and given the number of times we've said goodbye, to make sure we would finally leave!)&lt;/p&gt;  &lt;p&gt;The airport is nice - not great, but nice. The staff who work here, though, think no end of themselves. &lt;/p&gt;  &lt;p&gt;We had weight issues with at baggage counter, and the Thai Airways manager - an constipated-looking twerp with the face of a squashed beetle - was the most arrogant of all, and was not even courteous enough to look at me when we were trying to point out that the variation was under 10% (a reasonable expectation given the rough and tumble that the scales go though). He walked away when I asked him to escalate the issue, and it turned out that he was the senior-most cretin working the night. Asking them for a feedback form was met with &amp;quot;we have no customer-feedback form&amp;quot;. I was seething by the time I was done with him and we took off the bags, removed about 7 kilos of stuff into a bag which we gave to our folks who were still waiting outside, and were put through the &lt;em&gt;whole&lt;/em&gt; rigmarole of standing in line again! And when we finally reached the head of the line, we were asked to even weigh the carry-on baggage! &lt;/p&gt;  &lt;p&gt;This is the last time I'll be dealing with Thai Airways. I'm sorry they're part of Star Alliance - I should've taken the Qantas ticket and taken the miles on my frequent-flyer account there!&lt;/p&gt;  &lt;p&gt;The rest of the check-in procedure was a breeze. The emigration staff were courteous and efficient and very cooperative (I've only two free pages in my passport and I generally ask them to stamp their stuff on an otherwise occupied page. The security check was over before it began, and the lounge is nice and spacious. Free Internet Access (for only an hour, natch!) means that you get to see this post fresh off the presses.&lt;/p&gt;  &lt;p&gt;They've just called for boarding and I'm going to rush. This will be the last post from Bangalore for a while now! See you from the other side of the equator!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-7488482453716267310?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/06/leaving-from-bangalore.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-538468543855927568</guid><pubDate>Fri, 18 Apr 2008 19:05:00 +0000</pubDate><atom:updated>2008-04-19T00:35:59.917+05:30</atom:updated><title>US Patent 7165225</title><description>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Wow! So after 7 years, the US Patent Office finally assigned this patent to Microsoft, where I worked when we filed this patent application.&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.patentstorm.us/patents/7165225-claims.html" href="http://www.patentstorm.us/patents/7165225-claims.html"&gt;http://www.patentstorm.us/patents/7165225-claims.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Guess this makes me an &amp;quot;inventor&amp;quot; or something...*smirk*&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-538468543855927568?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/04/us-patent-7165225.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-1244403028888355236</guid><pubDate>Wed, 09 Apr 2008 17:57:00 +0000</pubDate><atom:updated>2008-04-09T23:27:26.823+05:30</atom:updated><title>The Virtual Machine Farm</title><description>&lt;p&gt;Several people have asked me about how I set up the Virtual Machine Farm to make development of multiple projects on multiple platforms easy. I don't claim to be an expert in this field, but I've stood on the shoulders of giants and I have been able to get a workable solution.&lt;/p&gt;  &lt;h3&gt;The Host Hardware&lt;/h3&gt;  &lt;p&gt;I'm a roaming developer these days, so I don't have a heavy-duty, dedicated development desktop unit I can use. This may change, but I'm not likely to change the approach even if it does.&lt;/p&gt;  &lt;p&gt;Right now I'm developing on a little Acer laptop with the following specs:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;A single Turion 64x2 processor&lt;/li&gt;    &lt;li&gt;4GB RAM (of which only 3GB is actually available - given memory-mapped IO and all)&lt;/li&gt;    &lt;li&gt;160 GB HD partitioned into a System partition (Windows Vista Home Premium) of 40GB and a work partition of 100 GB. This work partition contains all the VMs.&lt;/li&gt;    &lt;li&gt;A very sub-optimal 1280x800 14&amp;quot; display. I would change this for my old Dell's 1600x1200 in half-a-heartbeat&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The host machine runs Vista Home Premium as installed by the manufacturer, with most of the third-party crud removed. I don't want to muck around too much on this system, because my goal is to be able to restore this system in about 4 minutes flat, install Microsoft Virtual PC, and get back to normal, even in the case of some very crazy crash.&lt;/p&gt;  &lt;p&gt;Once most of the third party crap is done, Vista's footprint hovers around 1.5GB of used RAM, excluding the aggressive caching stuff it does.&lt;/p&gt;  &lt;p&gt;It goes without saying that the Virtual PCs will benefit from beefier metal, but the system is adequate as it stands. The amount of RAM and the presence of hardware virtualization makes all the difference though, as does having a dual-core CPU. Virtual PCs simulate single-cores, and even if Virtual PC itself runs only on one core, it leaves the other core available to the host machine.&lt;/p&gt;  &lt;h3&gt;The Base Virtual Operating System&lt;/h3&gt;  &lt;p&gt;I used to prefer developing on Windows XP simply because we had Ghost images set up to get a machine up and running fast, and the OS itself is relatively skinny. &lt;/p&gt;  &lt;p&gt;I use nLite to strip down a Windows XP SP2 installation to around 215MB or so. Since I'm installing the XP on a Virtual PC with a very small set of standard hardware devices being simulated, I can be pretty aggressive and even leave out things like drivers which bloat the typical install and serve no additional purpose. &lt;/p&gt;  &lt;p&gt;I leave out most non-development-type things - I'll never use Windows Media Player in the VM, for example - and keep a bare minimum of the system components (IE, Notepad and Calc are essentials, for example).&lt;/p&gt;  &lt;p&gt;Turn off System Restore and Hibernation support, and sparingly turn-off services that you know you won't need. Don't remove services even though nLite allows you to. You may need them some day in the future, and the impact on the footprint isn't worth the headache of having to re-do the whole VM farm.&lt;/p&gt;  &lt;p&gt;Once we get a clean, light XP ISO, we can create a base Virtual Machine and install the system on there. I make the virtual HD something like 4GB in size, which after defragmentation, preparation and compaction, comes to under 2GB, and I can burn that on a single DVD. It is not surprising that the skinny OS with nothing but IE on it has a runtime footprint under 90MB in size. &lt;/p&gt;  &lt;p&gt;You can safely allocate 256MB for this Virtual Machine and never swap the guest OS, but you won't because we will NEVER run this HD directly. It's going to form the base of a hierarchy of differenced disks, so we'll just mark it as read-only as soon as we finish running all possible updates at the time of installation. I'll take a backup onto DVD at this stage.&lt;/p&gt;  &lt;h4&gt;Tip: The Guest OS Swap File&lt;/h4&gt;  &lt;p&gt;Just in case though, I create a second virtual hard drive to act as the swap hard drive, and stick it on a flash drive made from an SD card which goes permanently into the card-reader. I do this for all other Virtual Machines I build - and the SD card doesn't have to be ReadyBoost grade, even!&lt;/p&gt;  &lt;h4&gt;Tip: Defragmentation, Preparation and Compaction&lt;/h4&gt;  &lt;p&gt;I use the Whitney Family Defragmenter to defrag all my virtual hard drives, prepare the hard drives for compaction, and compact before backing up or storing. It makes a big difference to the size of the VHD file. &lt;/p&gt;  &lt;h4&gt;Tip: NTFS Compression&lt;/h4&gt;  &lt;p&gt;I always turn OFF NTFS compression of the VHD file in the host operation, and turn ON NTFS compression of the Virtual Disk in the guest OS. NTFS compression does not work for files that are over 4GB in size.&lt;/p&gt;  &lt;h3&gt;The Development Base&lt;/h3&gt;  &lt;p&gt;I like to use Emacs for my development, and I also like my PATH and other system variables set, regardless of the development platform.&lt;/p&gt;  &lt;p&gt;So I create a VPC using a virtual HD that differences from the Base OS HD, and install cygwin, Emacs, other tools I need, and do all the system variable and directory configuration as required. This is the one I spend time with, because tweaking things carefully here pays off later, and I won't have to do it again.&lt;/p&gt;  &lt;p&gt;Again, I won't be using this VHD directly, since all my development platform VPCs will difference from this one. I'll mark it as read-only and take a backup onto DVD as well.&lt;/p&gt;  &lt;h3&gt;The Platforms&lt;/h3&gt;  &lt;p&gt;I usually use VS 2003 for the older projects we work on, and I've decided to use VS 2008 for the newer ones. We just skipped a whole version. &lt;/p&gt;  &lt;p&gt;So I create two VPCs, each with hard-drives that are differenced from the Development Base VHD. It's like OO-inheritance, since both of these VPCs have the configuration I've set up carefully.&lt;/p&gt;  &lt;p&gt;I'll install VS 2003 with full-kit on one, and VS 2008 on the other. As newer platforms are required, I'll do the same for them. These are bulky VHDs, but they carry everything they need with them and they can get a new employee or laptop fully battle-ready in less than half-an-hour.&lt;/p&gt;  &lt;p&gt;I'll actually never use these VHDs directly either. I'll back these up on an external hard drive.&lt;/p&gt;  &lt;h3&gt;The Projects&lt;/h3&gt;  &lt;p&gt;These are individual instances of VMs, each with a VHD differencing from the appropriate platform setup, which can serve as a clean room, sequestered environment for each project. It's also easy to be able to host these VMs on a single test-bed server, configure their networking, and allow clients to do the UAT-phase of the project from a closely-monitored environment before deploying it to the field and testing it there.&lt;/p&gt;  &lt;p&gt;In these Virtual Machines, we also hook up a separate VHD mapped to a well-known junction-point (like C:\work), which SVN can use to keep the local project copy of the repository, and from which all the building can be done. This is useful because we can backup ONLY this VHD regularly - these are lightweight enough to generally be backed up on to a single CD or a 2GB flash-drive even.&lt;/p&gt;  &lt;h2&gt;Benefits&lt;/h2&gt;  &lt;h4&gt;Standardization&lt;/h4&gt;  &lt;p&gt;VM-based development platforms are by-definition identical, and we never have issues along the lines of having to deal with users' idiosyncrasies with regard to folders and paths. People can use each others' machines without any loss of productivity.&lt;/p&gt;  &lt;p&gt;Portability is also a big benefit because we can sometimes use faster hardware while demo-ing or at a roadshow, without having to worry about whether the setup is perfect.&lt;/p&gt;  &lt;h4&gt;Backup and Redundancy&lt;/h4&gt;  &lt;p&gt;We back up at critical points, and frequently back up valuable work. In conjunction with judicious use of SVN, we can survive a many-layered failure of computing hardware and still get back to a known state relatively quickly.&lt;/p&gt;  &lt;h4&gt;Ease of Management&lt;/h4&gt;  &lt;p&gt;It's easier than one imagines to manage this farm of VMs, because each piece of software is installed exactly once. The only downside is that each leaf-node (Project) VM will have to do the incremental Windows Update, but since project life-cycles are what they are, this is fairly expected.&lt;/p&gt;  &lt;h4&gt;Demo Software&lt;/h4&gt;  &lt;p&gt;We can install demo software branching off at the appropriate level on the tree to check out stuff before rolling it out into our general use. The most recent case-in-point is actually the VS 2008 tree, which has a trunk with the stock install, and a fork with the Silverlight beta and other not-yet-ready-for-primetime stuff.&lt;/p&gt;  &lt;h2&gt;Conclusion&lt;/h2&gt;  &lt;p&gt;I hope this post helps someone. &lt;/p&gt;  &lt;p&gt;It'll certainly make things clearer to me when I read things next year and wonder why we're doing something like this!&lt;/p&gt;  &lt;p&gt;If anyone wants specifics on things like which services I've turned off, which system modules I've deleted with nLite, or what development tools I use, shoot me a mail and I'll consider a follow up of this document.&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:db992d6a-c110-4aa5-a9a0-e15c6ec1a346" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Microsoft%20Virtual%20PC" rel="tag"&gt;Microsoft Virtual PC&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Visual%20Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Software%20Development" rel="tag"&gt;Software Development&lt;/a&gt;,&lt;a href="http://technorati.com/tags/System%20Management" rel="tag"&gt;System Management&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-1244403028888355236?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/04/virtual-machine-farm.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-6588304955707247707</guid><pubDate>Wed, 09 Apr 2008 13:06:00 +0000</pubDate><atom:updated>2008-04-09T22:19:41.235+05:30</atom:updated><title>Silverlight Weirdness (the sequel to Silverlight Woes)</title><description>&lt;p&gt;First off, let me thank Scott Guthrie for taking the time to respond to my mails and pointing me to Peter Puszkiewicz, and let me thank him for helping me debug this situation...&lt;/p&gt;  &lt;p&gt;Peter requested that I try the following steps:&lt;/p&gt;  &lt;p&gt;&amp;lt;quote&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;1. I'll call this one out, but it's a lot of work, so maybe don't try this first. you seem to have a lot of stuff installed (including two versions of Blend)... why don't you clean your vm and start by just following Bradley's post. Get the base package running, then add to it to find the culprit &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;2. go to Silverlight.net and view a Silverlight sample. Does the control launch for you at all? does it launch for a beta 1 sample? Best way to be sure is to right-click on screen space that you expect to be Siverlight and check to see if a menu with the sigle item &amp;quot;Silverlight Configuration&amp;quot; shows up&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;3. Can you send me the full registry hive for the Silverlight ClSID? I remember that some tools expected to find progID AgControl.AgControl to find a path to npctrl.dll... this may still be the case&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;4. Along those lines, can you run Process Monitor, attach (filter) it to your instance of devenv.exe, and send me a dump of what is happening while you are trying to start up the Silverlight project? I'd like to see what it's looking for an not finding. If you're not familiar, Process Monitor is a great tool from Microsoft/SysInternals which allows you to monitor HDD/Registry requests from processes. It is also free:) &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;5. Make sure you have access to (read access) to all Silverlight dll's/registry keys. You can find the relevant keys by looking for posts from DHarvey on the Silverlight.net forums. Alternatively, I can send them tomorrow.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;6. Try running VS as an admin&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;/quote&amp;gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Now, I had started with a clean VM with nothing but Visual Studio to start with, and I'd never been able to get the base package working. The installation of Blend was more an act of desperation hoping the installation would iron out any wrinkles in the VS 2K8 install, so I wasn't going to try this instanter... &lt;/li&gt;    &lt;li&gt;I remember having been to Silverlight.net and trying time-after-time to install Silverlight, which would report a successful installation but request me to install again. I thought I fixed that somehow! &lt;/li&gt;    &lt;li&gt;I did this - walking all over the registry and looking for anything weird. Never found anything out of the ordinary here... &lt;/li&gt;    &lt;li&gt;This was a good thing to try. But before I started doing this, I decided to verify Step 2 again. &lt;/li&gt;    &lt;li&gt;This was a given since I was running the VM as an Administrator. &lt;/li&gt;    &lt;li&gt;Ditto... &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Now I've followed some pretty interesting steps to set up my Virtual Machine farm, so I decided to start at the root installation - a VM with &lt;em&gt;nothing &lt;/em&gt;on it but a light version of Windows XP SP2, properly patched and updated. So no Visual Studio, no Microsoft Office, nothing! &lt;/p&gt;  &lt;p&gt;I fired up IE and sauntered on to &lt;a href="http://silverlight.net/showcase"&gt;http://silverlight.net/showcase&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Right there, I realized that I had NEVER been able to install Silverlight properly. I then spent the next 2 hours installing and re-installing Silverlight, and turning on several services I had earlier turned off to tweak the VM installation to have a smaller footprint - each time being told the install was successful, but only to be invited to reinstall when I went to check out the showcase. The installation log and Event Viewer both showed me that the installations were &amp;quot;successful&amp;quot;!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/john.azariah/R_zH8QbFowI/AAAAAAAACb4/9Om2b2zhKt8/s1600-h/Silverlight%20Weirdness%202%5B15%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="441" alt="Liar Liar!" src="http://lh5.google.com/john.azariah/R_y_NwbFomI/AAAAAAAACcA/-sG03XvwemY/Silverlight%20Weirdness%202_thumb%5B13%5D.jpg?imgmax=800" width="704" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;It lies like a Persian Rug!&lt;/p&gt;  &lt;p&gt;Then I got the idea of running &lt;strong&gt;&lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx" target="_blank"&gt;procmon&lt;/a&gt;&lt;/strong&gt; while IE loaded &lt;a href="http://silverlight.net/showcase"&gt;http://silverlight.net/showcase&lt;/a&gt; and trying to figure out what went wrong. After combing through about 25,000 lines of diagnostics looking for weirdness, I found that IE reported that it had successfully loaded the Silverlight DLLs! &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.google.com/john.azariah/R_y_RgbFonI/AAAAAAAACck/MlqMdaWY6y0/s1600-h/Silverlight%20Weirdness%201%5B12%5D.jpg" target="target"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="548" alt="Why do you need DSOUND?" src="http://lh4.google.com/john.azariah/R_y_UgbFooI/AAAAAAAACco/PbR-Czw9HdY/Silverlight%20Weirdness%201_thumb%5B10%5D.jpg?imgmax=800" width="904" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The only innocent-looking failure was that it couldn't load DSOUND.dll - fair enough, you don't need DirectSound to browse the web, do you?&lt;/p&gt;  &lt;p&gt;Now since I was running a development environment in a virtual machine, I reasonably assumed I wasn't going to need Wireless Networking, UPnP, Sound, System Restore, Help and Support, Windows Media Player among other modules which only contribute bloat to a development environment. I had therefore stripped them out using nLite before installing my development tools. &lt;/p&gt;  &lt;p&gt;Anyway - just to cover all bases, I fished out a dsound.dll from another Windows XP installation and plonked it into the VM - and whadyaknow - it worked!! I was able to view all the Silverlight demonstrations I could find.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/john.azariah/R_y_WQbFopI/AAAAAAAACcM/qx5QYZxwyog/s1600-h/Silverlight%20Weirdness%203%5B17%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="521" alt="It Works!" src="http://lh3.google.com/john.azariah/R_y_YQbFoqI/AAAAAAAACcQ/Q_4dL2oDKgU/Silverlight%20Weirdness%203_thumb%5B13%5D.jpg?imgmax=800" width="704" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I must confess I'm a little peeved by the strange dependency that Silverlight has on sound, of all things! This is supposed to be a development and web-application platform - and while it's arguable that sound and video make the user experience rich and cool, I don't think that it's defensible to make sound a mandatory prerequisite of the platform - and it's completely inexpiable that the platform would die without giving a clue of this strange dependency!&lt;/p&gt;  &lt;p&gt;In sum - I'm finally able to get started on Silverlight. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.google.com/john.azariah/R_zFgwbFouI/AAAAAAAACcU/BuYwKBhE7L8/s1600-h/Silverlight%20Weirdness%205%5B5%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="566" alt="Hello World!" src="http://lh5.google.com/john.azariah/R_zFiwbFovI/AAAAAAAACcY/wl_4-EfeV6I/Silverlight%20Weirdness%205_thumb%5B3%5D.jpg?imgmax=800" width="904" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;At least I know His Gu-ness will respond to a mail in a timely manner if I'm similarly stumped the next time! And I can always use procman before mailing him next time!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/john.azariah/R_zCkQbFosI/AAAAAAAACcc/LVA1h9kJ5l8/s1600-h/Silverlight%20Weirdness%204%5B12%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="183" alt="Words of Wisdom!" src="http://lh5.google.com/john.azariah/R_zClwbFotI/AAAAAAAACcg/4IGU94EMeZ4/Silverlight%20Weirdness%204_thumb%5B10%5D.jpg?imgmax=800" width="281" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:7fedc700-8d4f-4a19-8510-7abf3888973a" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Silverlight" rel="tag"&gt;Silverlight&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Visual%20Studio%202008" rel="tag"&gt;Visual Studio 2008&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-6588304955707247707?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/04/silverlight-weirdness-sequel-to.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-6016857328417887788</guid><pubDate>Tue, 08 Apr 2008 08:30:00 +0000</pubDate><atom:updated>2008-04-08T14:17:54.272+05:30</atom:updated><title>Silverlight Woes</title><description>&lt;p&gt;So I've installed VS 2008, and all the stuff required to check out the Silverlight platform on a fresh new Virtual PC dedicated to do nothing else!&lt;/p&gt;  &lt;p&gt;Here's all the stuff installed:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Release version of Visual Studio 2008&lt;/li&gt;    &lt;li&gt;Silverlight Tools Beta 1 for Visual Studio 2008 from &lt;a title="http://www.microsoft.com/downloads/details.aspx?FamilyId=E0BAE58E-9C0B-4090-A1DB-F134D9F095FD&amp;amp;displaylang=en" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=E0BAE58E-9C0B-4090-A1DB-F134D9F095FD&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyId=E0BAE58E-9C0B-4090-A1DB-F134D9F095FD&amp;amp;displaylang=en&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Expression Blend, Expression Web&lt;/li&gt;    &lt;li&gt;Blend 2 December Preview, Blend 2.5 March 08 Preview, ASP.NET MVC Preview 2 from Microsoft Downloads&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I've &lt;em&gt;already&lt;/em&gt; read BradleyB's blog posts at &lt;a title="http://weblogs.asp.net/bradleyb/archive/2008/03/06/installation-tips-for-sivliverlight-tools-beta-1-for-visual-studio-2008.aspx" href="http://weblogs.asp.net/bradleyb/archive/2008/03/06/installation-tips-for-sivliverlight-tools-beta-1-for-visual-studio-2008.aspx"&gt;http://weblogs.asp.net/bradleyb/archive/2008/03/06/installation-tips-for-sivliverlight-tools-beta-1-for-visual-studio-2008.aspx&lt;/a&gt;, and have followed all the instructions therein!&lt;/p&gt;  &lt;p&gt;My System Setup after all the jazz installed is:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.google.com/john.azariah/R_ss9QbFodI/AAAAAAAACZI/ufmaCJM5vso/silverlight%20project%20error%204%5B10%5D.jpg" target="_blank"&gt;&lt;img height="412" alt="silverlight project error 4" src="http://lh5.google.com/john.azariah/R_ss_AbFoeI/AAAAAAAACZQ/5skUPZLiItg/silverlight%20project%20error%204_thumb%5B8%5D.jpg" width="681" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Fired up VS and created a new Silverlight project, and expected to be able to write the canonical Hello World...and this is what I got:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/john.azariah/R_stBgbFofI/AAAAAAAACZY/26WAWCrdGfc/silverlight%20project%20error%201%5B6%5D.jpg" target="_blank"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="415" alt="silverlight project error 1" src="http://lh3.google.com/john.azariah/R_stDgbFogI/AAAAAAAACZg/ciyp7yVcUQw/silverlight%20project%20error%201_thumb%5B4%5D.jpg" width="685" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Fine - this might be some general first-boot problem. If you try to &amp;quot;Reload the designer&amp;quot;, as suggested, I get:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.google.com/john.azariah/R_stGAbFohI/AAAAAAAACZo/67jWEG164Cg/silverlight%20project%20error%202%5B5%5D.jpg" target="_blank"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="416" alt="silverlight project error 2" src="http://lh5.google.com/john.azariah/R_stIAbFoiI/AAAAAAAACZw/DDkvVhtvpUE/silverlight%20project%20error%202_thumb%5B3%5D.jpg" width="686" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Hmm...looks like it either really can't find the control, or there's some weirdness with Visual Studio acting as a Silverlight host!&lt;/p&gt;  &lt;p&gt;Rooted around the Registry looking for the CLSID in question, and sure enough, it refers to AgControl.AgControl1 - the Silverlight control. Now, if I remember correctly, an HRESULT of 0x8007007e generally indicates &amp;quot;File Not Found&amp;quot;. The InprocServer for this control points to the Silverlight installation directory, and to a valid DLL. What gives?&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.google.com/john.azariah/R_stKAbFojI/AAAAAAAACZ4/G3EFZ96cQpo/silverlight%20project%20error%203%5B4%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="429" alt="silverlight project error 3" src="http://lh5.google.com/john.azariah/R_stMAbFokI/AAAAAAAACaA/ux788RHIWOA/silverlight%20project%20error%203_thumb%5B2%5D.jpg" width="684" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I've hunted all over the web for anyone reporting this weirdness, without success. I've re-installed everything on a clean VM with only the stock Visual Studio 2008 as a starting point.&lt;/p&gt;  &lt;p&gt;Next attempt will be to try with Visual Studio 2005 and Silverlight!&lt;/p&gt;  &lt;p&gt;Bummer...I was really looking forward to using Linq and all...&lt;/p&gt;  &lt;p&gt;Finally, anyone who has a clue about what may help can mail me at john.azariah-at-gmail.com! Thanks&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:f1a4eb7b-1ca3-4699-9220-3b750d346ff6" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Silverlight" rel="tag"&gt;Silverlight&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Visual%20Studio%202008" rel="tag"&gt;Visual Studio 2008&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-6016857328417887788?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/04/silverlight-woes.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-533061239588824255</guid><pubDate>Wed, 30 Jan 2008 09:25:00 +0000</pubDate><atom:updated>2008-01-30T14:55:12.208+05:30</atom:updated><title>Wooot!</title><description>&lt;p&gt;My company is now ISO 9001:2000 certified!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-533061239588824255?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/01/wooot.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-2873917929184567506.post-3405641090536182894</guid><pubDate>Wed, 30 Jan 2008 07:19:00 +0000</pubDate><atom:updated>2008-01-30T12:49:10.859+05:30</atom:updated><title>The Importance Of Marketing</title><description>&lt;p&gt;Both the ISO auditors are keen on, and very knowledgeable about,&amp;nbsp;Indian food. Being foodies ourselves,&amp;nbsp;we were joking with them about the best &lt;em&gt;biriyani&lt;/em&gt; in the world being made in Bangalore - even after taking into account Delhi, Karachi and Hyderabad. (Let the &lt;strike&gt;flame &lt;/strike&gt;cookout wars begin!)&lt;/p&gt; &lt;p&gt;Anyway - come lunch time, and we decided to drive down to a South-Indian restaurant in Serangoon Road. Anyone who has been to Serangoon Road knows how the aromas of each restaurant on the street loudly proclaim the goodies obtainable inside. We stood outside the restaurant we had chosen, waiting for admittance behind a crowd of people, when we spied a place that billed itself as a Hyderabadi Biriyani house, and walked over.&lt;/p&gt; &lt;p&gt;While all the places around it were buzzing and overflowing with the lunch crowd, this place was&amp;nbsp;&lt;em&gt;empty.&lt;/em&gt; &lt;/p&gt; &lt;p&gt;Empty! In Singapore! This is a place where a hawker can viably sell food at 2 AM, on a Thursday morning, in Tampines, in the rain! We were&amp;nbsp;stunned, but since Peter had eaten there before and vouched for the food, we went in and sat down anyway.&lt;/p&gt; &lt;p&gt;The service was predictably good - we were the &lt;em&gt;only&lt;/em&gt; customers there after all. The food arrived on time and there was a rude plenty of it. It even tasted fantastic - probably the best Hyderabadi biriyani I've had outside Hyderabad, and definitely better than a good many I've had inside. A thoroughly good time was had by all, and several people in the group were publicly discussing what they were going to order again when they came back!&lt;/p&gt; &lt;p&gt;We were puzzled how an Indian&amp;nbsp;restaurant, in the middle of Little India, with excellent food and decor, could be empty during the lunch crowd when people were queuing up outside the neighbours. Puzzled enough to accost the head waiter and ask him when he brought us the post-prandial tea.&lt;/p&gt; &lt;p&gt;His response stunned us - the owners didn't want to invest in marketing!&lt;/p&gt; &lt;p&gt;Imagine that - you invest in infrastructure, rent a place in the right location, serve a darn fine lunch, impress customers enough to want to come back to you, &lt;em&gt;but don't invest in marketing&lt;/em&gt;! One wonders if the owner might have become more 'profitable' by closing down the place, firing the chefs, and selling away his equipment!&lt;/p&gt; &lt;p&gt;That's an interesting lesson for a geek like me - that success in selling something is at least as dependent on marketing as it is on getting the product done right...products don't &lt;em&gt;actually&lt;/em&gt; sell themselves all the time!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-3405641090536182894?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://jazariah.blogspot.com/2008/01/importance-of-marketing.html</link><author>noreply@blogger.com (Patagonian Toothfish)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item></channel></rss>