<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2873917929184567506</id><updated>2011-11-28T04:58:30.304+05:30</updated><category term='meandering around'/><category term='computer science'/><category term='technology'/><category term='the beginning'/><category term='Yet Another Bright Idea'/><category term='photography'/><category term='science and research'/><category term='code-generation'/><category term='family'/><category term='brightsword'/><category term='insanity'/><category term='smitha'/><category term='india'/><category term='vapid sentimental nonsense'/><category term='brightsword.eden'/><category term='the antipodes'/><title type='text'>Wild Stabs In The Dark</title><subtitle type='html'>Inane ramblings from a desert island...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>45</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-1744445293136028022</id><published>2008-08-18T20:52:00.000+05:30</published><updated>2008-08-19T20:53:06.237+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='brightsword.eden'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Almost a full-blown LISP interpreter :)</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/1744445293136028022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=1744445293136028022' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1744445293136028022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1744445293136028022'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/08/almost-full-blown-lisp-interpreter.html' title='Almost a full-blown LISP interpreter :)'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-2438499200132435311</id><published>2008-08-07T20:51:00.000+05:30</published><updated>2008-08-19T20:54:10.129+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='brightsword.eden'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Post 6: Expression Evaluator - Finale</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/2438499200132435311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=2438499200132435311' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2438499200132435311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2438499200132435311'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/08/post-6-expression-evaluator-finale.html' title='Post 6: Expression Evaluator - Finale'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-7204085485568151748</id><published>2008-08-02T09:59:00.000+05:30</published><updated>2008-08-03T11:37:28.990+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='brightsword.eden'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Post 5: Expression Evaluator - Integration</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/7204085485568151748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=7204085485568151748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7204085485568151748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7204085485568151748'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/08/post-5-expression-evaluator-integration.html' title='Post 5: Expression Evaluator - Integration'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-3012825926617658252</id><published>2008-08-01T07:34:00.000+05:30</published><updated>2008-08-03T11:37:28.991+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='brightsword.eden'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Post 4: Expression Evaluator - Object Typing</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/3012825926617658252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=3012825926617658252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3012825926617658252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3012825926617658252'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/08/post-4-expression-evaluator-object.html' title='Post 4: Expression Evaluator - Object Typing'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-3533297027355511553</id><published>2008-07-31T07:33:00.000+05:30</published><updated>2008-08-03T11:37:28.991+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='brightsword.eden'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Post 3: Expression Evaluator - The Expression Class and Evaluation</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/3533297027355511553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=3533297027355511553' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3533297027355511553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3533297027355511553'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/07/post-3-expression-evaluator-expression.html' title='Post 3: Expression Evaluator - The Expression Class and Evaluation'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-393824189807423540</id><published>2008-07-30T15:31:00.000+05:30</published><updated>2008-08-03T11:37:28.991+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='brightsword.eden'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Post 2: Expression Evaluator - Building an Expression Tree</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/393824189807423540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=393824189807423540' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/393824189807423540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/393824189807423540'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/07/post-2-expression-evaluator-building.html' title='Post 2: Expression Evaluator - Building an Expression Tree'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-8769809160966658375</id><published>2008-07-30T12:41:00.000+05:30</published><updated>2008-08-02T12:44:48.362+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='family'/><title type='text'>Eden is Born!</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/8769809160966658375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=8769809160966658375' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8769809160966658375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8769809160966658375'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/07/eden-is-born.html' title='Eden is Born!'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/john.azariah/SJPz-9tGzJI/AAAAAAAAESg/0wYBbR29zNE/s72-c/IMG_4346_thumb.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-1372160782098087555</id><published>2008-07-25T07:31:00.000+05:30</published><updated>2008-08-03T11:37:28.991+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='brightsword.eden'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Post 1: Expression Evaluator - The Parser</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/1372160782098087555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=1372160782098087555' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1372160782098087555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1372160782098087555'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/07/post-1-expression-evaluator-parser.html' title='Post 1: Expression Evaluator - The Parser'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-1777577620297388683</id><published>2008-07-21T15:31:00.000+05:30</published><updated>2008-08-03T11:37:28.992+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='Yet Another Bright Idea'/><category scheme='http://www.blogger.com/atom/ns#' term='brightsword.eden'/><category scheme='http://www.blogger.com/atom/ns#' term='computer science'/><title type='text'>Part 0: Building a Basic Expression Evaluator</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/1777577620297388683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=1777577620297388683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1777577620297388683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1777577620297388683'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/07/part-0-building-basic-expression.html' title='Part 0: Building a Basic Expression Evaluator'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-3468096372521808750</id><published>2008-06-24T11:59:00.000+05:30</published><updated>2008-08-02T12:42:04.779+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='the antipodes'/><category scheme='http://www.blogger.com/atom/ns#' term='meandering around'/><category scheme='http://www.blogger.com/atom/ns#' term='family'/><title type='text'>Home!</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/3468096372521808750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=3468096372521808750' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3468096372521808750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3468096372521808750'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/06/home.html' title='Home!'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/john.azariah/SJQFnC7Gn8I/AAAAAAAAESQ/HcYoqCBvKZI/s72-c/26062008424_thumb.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-3261815804183711519</id><published>2008-06-22T12:20:00.000+05:30</published><updated>2008-08-02T12:40:06.953+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='the antipodes'/><category scheme='http://www.blogger.com/atom/ns#' term='meandering around'/><title type='text'>House-hunting</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/3261815804183711519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=3261815804183711519' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3261815804183711519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3261815804183711519'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/06/house-hunting.html' title='House-hunting'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/john.azariah/SJQISnTnNhI/AAAAAAAAESI/vMVHFngo_Ow/s72-c/20062008404_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-8806945871113750146</id><published>2008-06-21T12:29:00.000+05:30</published><updated>2008-08-02T12:36:04.273+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='the antipodes'/><category scheme='http://www.blogger.com/atom/ns#' term='meandering around'/><title type='text'>Goodbye Lonsdale, Hello Brunswick</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/8806945871113750146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=8806945871113750146' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8806945871113750146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8806945871113750146'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/06/goodbye-lonsdale-hello-brunswick.html' title='Goodbye Lonsdale, Hello Brunswick'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/john.azariah/SJQHOaAJL5I/AAAAAAAAESA/lPu_rl3BCHM/s72-c/16062008396_thumb%5B6%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-7946159665906801947</id><published>2008-06-14T18:49:00.000+05:30</published><updated>2008-08-03T09:57:25.323+05:30</updated><title type='text'>14 June 08 - The Travels (and travails) of Marcus</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/7946159665906801947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=7946159665906801947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7946159665906801947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7946159665906801947'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/06/14-june-08-travels-and-travails-of.html' title='14 June 08 - The Travels (and travails) of Marcus'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/john.azariah/SFYWajjaiZI/AAAAAAAAETA/HN2CIz--AwA/s72-c/14062008394_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-1387050055780846583</id><published>2008-06-13T18:49:00.000+05:30</published><updated>2008-06-16T12:58:41.766+05:30</updated><title type='text'>13 June 08 - Friday the Thirteenth</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/1387050055780846583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=1387050055780846583' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1387050055780846583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1387050055780846583'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/06/13-june-08-friday-thirteenth.html' title='13 June 08 - Friday the Thirteenth'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-7958952282615158184</id><published>2008-06-12T16:47:00.000+05:30</published><updated>2008-06-16T12:57:34.580+05:30</updated><title type='text'>12 June 08 - Part 1 : Roaming Around The Countryside</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/7958952282615158184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=7958952282615158184' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7958952282615158184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7958952282615158184'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/06/12-june-08-part-1-roaming-around.html' title='12 June 08 - Part 1 : Roaming Around The Countryside'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-6900573451148564451</id><published>2008-06-11T16:28:00.000+05:30</published><updated>2008-08-03T09:56:25.625+05:30</updated><title type='text'>11 June 08 - Wandering around Melbourne</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/6900573451148564451/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=6900573451148564451' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6900573451148564451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6900573451148564451'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/06/11-june-08-wandering-around-melbourne.html' title='11 June 08 - Wandering around Melbourne'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/john.azariah/SFYUbcn8MRI/AAAAAAAAESw/sS5iEUgPxEA/s72-c/11062008379_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-3276831535477811181</id><published>2008-06-10T15:24:00.000+05:30</published><updated>2008-06-16T12:49:08.718+05:30</updated><title type='text'>10 June 08 - First Day In Melbourne</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/3276831535477811181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=3276831535477811181' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3276831535477811181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3276831535477811181'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/06/10-june-08-first-day-in-melbourne.html' title='10 June 08 - First Day In Melbourne'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-8555743264722992240</id><published>2008-06-09T12:39:00.000+05:30</published><updated>2008-06-16T12:39:47.218+05:30</updated><title type='text'>Hello From Melbourne</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/8555743264722992240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=8555743264722992240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8555743264722992240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8555743264722992240'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/06/hello-from-melbourne.html' title='Hello From Melbourne'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-7488482453716267310</id><published>2008-06-08T23:55:00.001+05:30</published><updated>2008-06-16T13:05:36.440+05:30</updated><title type='text'>Leaving From Bangalore</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/7488482453716267310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=7488482453716267310' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7488482453716267310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7488482453716267310'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/06/leaving-from-bangalore.html' title='Leaving From Bangalore'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-538468543855927568</id><published>2008-04-19T00:35:00.001+05:30</published><updated>2008-04-19T00:35:59.917+05:30</updated><title type='text'>US Patent 7165225</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/538468543855927568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=538468543855927568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/538468543855927568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/538468543855927568'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/04/us-patent-7165225.html' title='US Patent 7165225'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-1244403028888355236</id><published>2008-04-09T23:27:00.001+05:30</published><updated>2008-04-09T23:27:26.823+05:30</updated><title type='text'>The Virtual Machine Farm</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/1244403028888355236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=1244403028888355236' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1244403028888355236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1244403028888355236'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/04/virtual-machine-farm.html' title='The Virtual Machine Farm'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-6588304955707247707</id><published>2008-04-09T18:36:00.001+05:30</published><updated>2008-04-09T22:19:41.235+05:30</updated><title type='text'>Silverlight Weirdness (the sequel to Silverlight Woes)</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/6588304955707247707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=6588304955707247707' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6588304955707247707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6588304955707247707'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/04/silverlight-weirdness-sequel-to.html' title='Silverlight Weirdness (the sequel to Silverlight Woes)'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-6016857328417887788</id><published>2008-04-08T14:00:00.001+05:30</published><updated>2008-04-08T14:17:54.272+05:30</updated><title type='text'>Silverlight Woes</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/6016857328417887788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=6016857328417887788' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6016857328417887788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6016857328417887788'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/04/silverlight-woes.html' title='Silverlight Woes'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-533061239588824255</id><published>2008-01-30T14:55:00.001+05:30</published><updated>2008-01-30T14:55:12.208+05:30</updated><title type='text'>Wooot!</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/533061239588824255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=533061239588824255' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/533061239588824255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/533061239588824255'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/01/wooot.html' title='Wooot!'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-3405641090536182894</id><published>2008-01-30T12:49:00.001+05:30</published><updated>2008-01-30T12:49:10.859+05:30</updated><title type='text'>The Importance Of Marketing</title><content type='html'>&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;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/3405641090536182894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=3405641090536182894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3405641090536182894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3405641090536182894'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/01/importance-of-marketing.html' title='The Importance Of Marketing'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-8578445985881295155</id><published>2008-01-30T12:23:00.001+05:30</published><updated>2008-01-30T12:50:30.138+05:30</updated><title type='text'>ISO 9001:2000</title><content type='html'>&lt;p&gt;My company is being audited today for ISO 9001 compliance.&lt;/p&gt; &lt;p&gt;It's definitely an exacting process to get ready for the first audit. We have reams and reams of documents and the Management Representative (MR) has been exercising the laser printer for the last three days running. &lt;/p&gt; &lt;p&gt;I gave a presentation about the company - for a change, the presentation was quite interactive, with the auditors asking genuine and intelligent questions, so that was refreshing.&lt;/p&gt; &lt;p&gt;I hope I'll have update the presentation soon...to include the ISO certification!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-8578445985881295155?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/8578445985881295155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=8578445985881295155' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8578445985881295155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8578445985881295155'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/01/iso-90012000.html' title='ISO 9001:2000'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-3825172678797838765</id><published>2008-01-29T07:41:00.001+05:30</published><updated>2008-01-30T12:50:44.537+05:30</updated><title type='text'>Early Morning Traffic</title><content type='html'>&lt;p&gt;The Singapore MRT is one of my favourite ways to travel. Day after day, I take the East-West (Green) line from either Tampines or Simei to our office close to the Redhill station. About 42-45 minutes worth of rail time...costs about a buck-thirty. In spite of the lemming-like crowds, one manages reasonably well...&lt;/p&gt; &lt;p&gt;While one sees the smooth running of trains every 2-5 minutes day-in and day-out as an example of well-oiled machinery, it's when things go spectacularly wrong that one is really impressed.&lt;/p&gt; &lt;p&gt;Sometime last week, I decided to walk to Tampines, rather than Simei, and catch the train from there. When I got there, however, there was more-than-the-usual crowd standing at the entrance to the station, gazing steadfastly at some writing. Every so often, a small section of the crowd would mumble, break away, and dodder down the road, while the rest of the lemmings moved in for a closer look at the writing on the wall.&lt;/p&gt; &lt;p&gt;Not willing to be the only ignoramus on the block, I dutifully donned my lemming-suit and joined in. A terse Singlish message along the lines of "Sorry for the inconvenient, MRT closed, Please follow signs to take the bus to Tanah Merah" greeted me when it was my turn at the edge of the cliff. I must confess that the mumbling and doddering came naturally after that.&lt;/p&gt; &lt;p&gt;After following the crowd (no visible signs anywhere, really) I found myself waiting for a spot in one of the special buses commandeered for this occasion. Orderly crowds, forsooth! I found all the experience of dealing with buses in India useful as I had to elbow my way into the bus for a place. We eventually reached Tanah Merah and were shepherded into a train which took us the rest of the way. There was no charge for the emergency bus service.&lt;/p&gt; &lt;p&gt;Once we were all definitely on our way, I got a chance to look around. Everyone was very annoyed by the delay, but the older folks were more stoic about it. The younger lemmings were texting away on their phones even more furiously than usual. Very uncharacterstically, I found my self in tension for a potential&amp;nbsp;&lt;em&gt;twenty &lt;/em&gt;minute delay!&lt;/p&gt; &lt;p&gt;It transpires that over 6,50,000 people were 'inconvenient'ed that morning - by&amp;nbsp;as much as&amp;nbsp;half an hour!&lt;/p&gt; &lt;p&gt;I don't know what impresses me more: the fact that the MRT system simply took&amp;nbsp;an unexpected emergency of such a scale&amp;nbsp;in stride and did a fine job by any account; or the fact that a 30&amp;nbsp;minute traffic delay, which is so commonplace in Bangalore, could cause such consternation to the Singaporean populace; or the fact that it caused &lt;em&gt;me&lt;/em&gt; to actually be concerned about arriving half an hour late!&lt;/p&gt; &lt;p&gt;Had I chosen to walk to Simei as I do usually, I would've been able to walk over to Tanah Merah and save myself 10 minutes! Now &lt;em&gt;that&lt;/em&gt; would've been an impressive achievement!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-3825172678797838765?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/3825172678797838765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=3825172678797838765' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3825172678797838765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3825172678797838765'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/01/early-morning-traffic.html' title='Early Morning Traffic'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-7053110293850452447</id><published>2008-01-28T08:11:00.001+05:30</published><updated>2008-01-30T12:50:16.080+05:30</updated><title type='text'>Visual Studio 2008</title><content type='html'>&lt;p&gt;OK...geek time again :)&lt;/p&gt; &lt;p&gt;I just got my hands on the new Visual Studio 2008! Fantastic! The DVD was waiting for me in the office - the MSDN subscription fulfillment guys don't let the grass grow under their feet!&lt;/p&gt; &lt;p&gt;I've decided to install it because I've watched the whole VS 2005 version from the sidelines - my dev environment is (very satisfactorily) still at VS 2003. I've now officially skipped a FULL version of a Microsoft product - and I'm afraid that it's likely that such a trend is going to continue :) I've still not, for example, installed Vista or Microsoft Office 2007.&lt;/p&gt; &lt;p&gt;However,&amp;nbsp;with&amp;nbsp;WCF and WF released - both frameworks that my friends back at Microsoft have worked on, and thought that I really ought to try them out and see how they fit into my scheme of things. &lt;/p&gt; &lt;p&gt;The install went off smoothly - and I got MSDN installed as well. Next came Expression and the whole ASP.NET AJAX paraphernalia. Also downloaded the Facebook VS 2K5 template for good measure...&lt;/p&gt; &lt;p&gt;Now off to play in my free time with all these new toys!&lt;/p&gt; &lt;p&gt;Let's see how this goes - will write about my experiences as they are sure to be unique!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-7053110293850452447?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/7053110293850452447/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=7053110293850452447' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7053110293850452447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7053110293850452447'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/01/visual-studio-2008.html' title='Visual Studio 2008'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-8759952453416628537</id><published>2008-01-28T08:03:00.001+05:30</published><updated>2008-01-28T08:03:20.914+05:30</updated><title type='text'>Hello from Singapore</title><content type='html'>&lt;p&gt;So I'm in the "fine" city :) &lt;/p&gt; &lt;p&gt;They even call themselves that in the free tourist guide - warning you of the various fines and punishments for transgressions big and small - and painstakingly pointing out that chewing gum is no long a capital offence here..&lt;/p&gt; &lt;p&gt;Got here flying Indian Airlines. Even after many times in the air, I still enjoy take-offs and landings. This time was unique though - an aborted takeoff!&lt;/p&gt; &lt;p&gt;It all started innocently enough - an on-time departure, no time spent on the apron. We were taxiing onto the runway when, two rows behind me, this guy starts wailing "I'm bleeding! Let me off!". Frantic attempts by the flight attendants and helpful comments by other passengers made it look like a scene out of Asterix and The Silver Star...&lt;/p&gt; &lt;p&gt;I'm always amazed by the efficiency at Changi - it's the only place where I spend less than 10 minutes at immigration and *still* get beaten to the carousel by my luggage!&lt;/p&gt; &lt;p&gt;I've also been highly impressed with the tightly controlled economy, where services are efficient and cheap! This time, however, I was shocked to find taxi fares up (by 35%, natch), apartment rental prices up (in some places by over 100%), house purchase prices up, food prices up, and general morale down...and I was only here 6 months ago! What's the world coming to when a tightly controlled economy can't keep its people happy!&lt;/p&gt; &lt;p&gt;Still - not all is bad here..the weather is still hot and humid, the traffic is still crazy, the trains still crowded - nothing out of the ordinary in the second-most densely populated country in the world.&lt;/p&gt; &lt;p&gt;Enough kvetching...I'm off to work...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-8759952453416628537?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/8759952453416628537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=8759952453416628537' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8759952453416628537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/8759952453416628537'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2008/01/hello-from-singapore.html' title='Hello from Singapore'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-2519737084925705046</id><published>2007-12-31T12:00:00.001+05:30</published><updated>2007-12-31T12:00:36.209+05:30</updated><title type='text'>Goodbye 2007</title><content type='html'>&lt;p&gt;It's been a crazy year...&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-2519737084925705046?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/2519737084925705046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=2519737084925705046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2519737084925705046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2519737084925705046'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/12/goodbye-2007.html' title='Goodbye 2007'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-2747068144930671974</id><published>2007-02-17T10:02:00.000+05:30</published><updated>2007-02-17T10:05:15.472+05:30</updated><title type='text'>Homesick in Australia</title><content type='html'>I'm in Sydney for a couple of weeks on work...&lt;br /&gt;&lt;br /&gt;So here are some of the pictures of family and friends I put together in my erm..copious free time!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="FONT-SIZE: 83%; WIDTH: 194px; FONT-FAMILY: arial,sans-serif; TEXT-ALIGN: center"&gt;&lt;div style="BACKGROUND: url(http://picasaweb.google.com/f/img/transparent_album_background.gif) no-repeat left 50%; HEIGHT: 194px"&gt;&lt;a href="http://picasaweb.google.com/john.azariah/FamilyAndFriends"&gt;&lt;img style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0px; BORDER-TOP: medium none; MARGIN-TOP: 16px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; BORDER-LEFT: medium none; PADDING-TOP: 0px; BORDER-BOTTOM: medium none" height="160" src="http://lh4.google.com/image/john.azariah/RdaECZtBtjE/AAAAAAAAANk/lxeU-wCwzdE/s160-c/FamilyAndFriends.jpg" width="160" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://picasaweb.google.com/john.azariah/FamilyAndFriends"&gt;&lt;div style="FONT-WEIGHT: bold; COLOR: #4d4d4d; TEXT-DECORATION: none"&gt;Family and Friends&lt;/div&gt;&lt;/a&gt;&lt;div style="COLOR: #808080"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-2747068144930671974?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/2747068144930671974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=2747068144930671974' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2747068144930671974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2747068144930671974'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/02/homesick-in-australia.html' title='Homesick in Australia'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-1392284910232744148</id><published>2007-02-04T18:48:00.000+05:30</published><updated>2007-02-04T18:55:14.855+05:30</updated><title type='text'>Picasa and Blogger</title><content type='html'>Something seems to have completely broken down with Picasa and Blogger and I can't post pictures as easily as I used to...&lt;br /&gt;&lt;br /&gt;Seems like a lot of people are having this problem... &lt;a href="http://groups.google.gy/group/blogger-help-publishing/browse_thread/thread/474d0d2af4735c27/38f55290c5bbb7e0#38f55290c5bbb7e0"&gt;here &lt;/a&gt;and &lt;a href="http://groups.google.gy/group/blogger-help-publishing/browse_thread/thread/02b0fca3d05c7ed4/38c6331dcd9c57fc#38c6331dcd9c57fc"&gt;here &lt;/a&gt;and &lt;a href="http://groups.google.gy/group/blogger-help-publishing/browse_thread/thread/7bce5a57495133c5/d54a8415cb91b0fd?lnk=gst&amp;q=Picasa&amp;amp;rnum=5#d54a8415cb91b0fd"&gt;here &lt;/a&gt;are some similarly disgruntled people..&lt;br /&gt;&lt;br /&gt;Arrgh..&lt;br /&gt;&lt;br /&gt;So the switch to my own WordPress server may be required after all..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-1392284910232744148?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/1392284910232744148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=1392284910232744148' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1392284910232744148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/1392284910232744148'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/02/picasa-and-blogger.html' title='Picasa and Blogger'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-7977506456142146086</id><published>2007-02-04T18:43:00.000+05:30</published><updated>2007-02-04T18:46:48.926+05:30</updated><title type='text'>A Church Blog???</title><content type='html'>I've volunteered to help set up a website for the church I go to (Richmond Town Methodist Church), and it struck me that most of what they wanted could actually be done with a blog.&lt;br /&gt;&lt;br /&gt;Off to google-land, and I came across &lt;a href="http:///2007/01/moving-from-blogger-to-wordpress-why-how-and-where/"&gt;this wonderful blog entry &lt;/a&gt;that talked about setting up our own blog server...&lt;br /&gt;&lt;br /&gt;Hmm...maybe this will work...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-7977506456142146086?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/7977506456142146086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=7977506456142146086' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7977506456142146086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/7977506456142146086'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/02/church-blog.html' title='A Church Blog???'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-209370575704721714</id><published>2007-02-02T08:51:00.000+05:30</published><updated>2007-02-02T09:12:00.754+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='science and research'/><title type='text'>"Can't Touch This"</title><content type='html'>Very interesting &lt;a href="http://link.brightcove.com/services/link/bcpid271543545/bctid422563006"&gt;video&lt;/a&gt; and &lt;a href="http://www.fastcompany.com/subscr/112/open_features-canttouchthis.html"&gt;article&lt;/a&gt; I caught this morning - thanks Greg!&lt;br /&gt;&lt;br /&gt;Fascinating what the human mind comes up with!&lt;br /&gt;&lt;br /&gt;Enjoy&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-209370575704721714?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/209370575704721714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=209370575704721714' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/209370575704721714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/209370575704721714'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/02/cant-touch-this.html' title='&quot;Can&apos;t Touch This&quot;'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-4637087928890350633</id><published>2007-02-01T16:50:00.000+05:30</published><updated>2007-02-01T17:16:45.308+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='india'/><category scheme='http://www.blogger.com/atom/ns#' term='meandering around'/><title type='text'>Coorg Trip</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/_DNpS0fva8mM/RcHNBQv6NpI/AAAAAAAAAK8/LCPA6AfXybI/s1600-h/200610221095.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_" alt="" src="http://3.bp.blogspot.com/_DNpS0fva8mM/RcHNBQv6NpI/AAAAAAAAAK8/LCPA6AfXybI/s400/200610221095.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_DNpS0fva8mM/RcHNBwv6NqI/AAAAAAAAALE/gPCTKR8RWHE/s1600-h/200610221098.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_" alt="" src="http://1.bp.blogspot.com/_DNpS0fva8mM/RcHNBwv6NqI/AAAAAAAAALE/gPCTKR8RWHE/s400/200610221098.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_DNpS0fva8mM/RcHNBwv6NrI/AAAAAAAAALM/OjLodVOkatg/s1600-h/200610221099.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_" alt="" src="http://1.bp.blogspot.com/_DNpS0fva8mM/RcHNBwv6NrI/AAAAAAAAALM/OjLodVOkatg/s400/200610221099.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_DNpS0fva8mM/RcHNCAv6NsI/AAAAAAAAALU/_Rjo4aVEVak/s1600-h/200610221102.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_" alt="" src="http://2.bp.blogspot.com/_DNpS0fva8mM/RcHNCAv6NsI/AAAAAAAAALU/_Rjo4aVEVak/s400/200610221102.jpg" border="0" /&gt;&lt;/a&gt; All pictures taken with the Nokia N70 camera-phone&lt;br /&gt;&lt;br /&gt;Coorg is a wonderful, picturesque place on the western side of Karnataka. Known for lush vegetation, brisk weather, fantastic arabica and robusta coffee &amp; friendly, cheerful people, Coorg is definitely one of the best places to be for a relaxing weekend getaway.&lt;br /&gt;&lt;br /&gt;We stayed at a holiday resort near Kakabe, from where a daredevil 4x4 Jeep ride took us to the top of a local hill. The scenery around was stunning as we watched the clouds try to crest the peak in vain... &lt;div style="CLEAR: both"&gt;&lt;a href="http://picasa.google.com/blogger/" target="ext"&gt;&lt;img style="BORDER-RIGHT: 0px; PADDING-RIGHT: 0px; BORDER-TOP: 0px; PADDING-LEFT: 0px; BACKGROUND: 0% 50%; PADDING-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: 0px; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial" alt="Posted by Picasa" src="http://photos1.blogger.com/pbp.gif" align="middle" border="0" /&gt;&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-4637087928890350633?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/4637087928890350633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=4637087928890350633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/4637087928890350633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/4637087928890350633'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/02/coorg-trip.html' title='Coorg Trip'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_DNpS0fva8mM/RcHNBQv6NpI/AAAAAAAAAK8/LCPA6AfXybI/s72-c/200610221095.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-2547725786448837499</id><published>2007-02-01T13:22:00.001+05:30</published><updated>2007-02-01T14:04:36.233+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='code-generation'/><title type='text'>Into the Wild Blue XML</title><content type='html'>&lt;p&gt;So in the previous entry, I posited a hypothetical template-based, metadata-driven, code generation system with one shortcoming - there was no concrete way to perform the application of the template onto the data.&lt;/p&gt;&lt;p&gt;In this article, I'm going to describe an approach we have developed to perform this operation.&lt;/p&gt;&lt;p&gt;The template we ended up with last time was:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;template :=&lt;br /&gt; &lt;em&gt;[PATTERN_BEGIN(property : property_metadata)]&lt;/em&gt;&lt;br /&gt;                 do&lt;br /&gt;                 {&lt;br /&gt;                     try&lt;br /&gt;                         {&lt;br /&gt;                         cmd.Parameters.Add("@p_&lt;em&gt;[property.name]&lt;/em&gt;", &lt;em&gt;[property.type]&lt;/em&gt;);&lt;br /&gt;  &lt;em&gt;[IF property.is_mandatory]&lt;/em&gt;&lt;br /&gt;                         cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = this.&lt;em&gt;[property.name]&lt;/em&gt;;&lt;br /&gt;  &lt;em&gt;[ELSE]&lt;/em&gt;&lt;br /&gt;   &lt;em&gt;[IF property.is_reference]&lt;/em&gt;&lt;br /&gt;                         if (this.&lt;em&gt;[property.name]&lt;/em&gt; == null)&lt;br /&gt;                         {&lt;br /&gt;                             cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = System.DBNull.Value;&lt;br /&gt;                         }&lt;br /&gt;                         else&lt;br /&gt;                         {&lt;br /&gt;                             cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = this.&lt;em&gt;[property.name]&lt;/em&gt;;&lt;br /&gt;                         }&lt;br /&gt;   &lt;em&gt;[ELSE]&lt;/em&gt;&lt;br /&gt;                         cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = this.&lt;em&gt;[property.name]&lt;/em&gt;;&lt;br /&gt;   &lt;em&gt;[ENDIF]&lt;/em&gt;&lt;br /&gt;                     }&lt;br /&gt;  &lt;em&gt;[ENDIF]&lt;/em&gt;&lt;br /&gt;                     catch (Exception ex)&lt;br /&gt;                     {&lt;br /&gt;  &lt;em&gt;[IF property.is_mandatory]&lt;/em&gt;&lt;br /&gt;                         System.Diagnostics.Debug.WriteLine(String.Format("Customer.Persist - Persisting Customer.[property.name] threw Exception [ {0} ]. Bailing.", ex.Message));&lt;br /&gt;                         throw ex;&lt;br /&gt;  &lt;em&gt;[ELSE]&lt;/em&gt;&lt;br /&gt;                         System.Diagnostics.Debug.WriteLine(String.Format("Customer.Persist - Persisting Customer.[property.name] threw Exception [ {0} ]. Filling Null Value.", ex.Message));&lt;br /&gt;                         cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = System.DBNull.Value;&lt;br /&gt;&lt;br /&gt;                         break;&lt;br /&gt;  &lt;em&gt;[ENDIF]&lt;/em&gt;&lt;br /&gt;                     }&lt;br /&gt;                 }&lt;br /&gt;                 while(false);&lt;br /&gt; &lt;em&gt;[PATTERN_END]&lt;/em&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Also, the data used to parametrize the template was:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;data := {&lt;br /&gt;  {"ID",       "System.Data.SqlDbType.UniqueIdentifier", true,  false},&lt;br /&gt;  {"IsActive", "System.Data.SqlDbType.Bit",              false, false},&lt;br /&gt;  {"Name",     "System.Data.SqlDbType.NVarChar",         false, true}&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;One way of looking at this snippet is to realise is that the invariant portion of the code (the non-italicised bits) is actually the &lt;em&gt;output&lt;/em&gt; we want. It follows that if the non-italicised bits are the &lt;em&gt;output&lt;/em&gt;, then the italicised portion must be the &lt;em&gt;program&lt;/em&gt;, in some hitherto undescribed language, which when processed by some hitherto unspecified compiler, will generate the output.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If we want to take this approach, and we don't want to be saddled with the task of creating a new language and writing a full-fledged compiler, then it behooves us to look at what languages and tools are already out there to be able to acheive what we want without going through all the motions.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Epiphany #1&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;As a side note, it is very interesting to note that the output of an XSLT transformation of an XML document can be &lt;em&gt;formatted text&lt;/em&gt;! All you have to do to achieve this is to appropriately set up the &amp;lt;xsl:output/&amp;gt; tag within the stylesheet.&lt;/p&gt;&lt;p&gt;So, if somehow, we could represent our data in an XML document, and have the template as an XSLT transform, we could then apply the transform to the data and emit text.&lt;/p&gt;&lt;p&gt;The reality, of course, is that it's fairly straightforward to represent both the data and the metadata in XML. In fact, we already have a mechanism to describe the metadata using XSD, which is itself an XML document. We won't appreciate the ramifications of this observation just yet, but all you need to do for now is to &lt;strong&gt;keep in mind that both the &lt;em&gt;data&lt;/em&gt; and its &lt;em&gt;metadata&lt;/em&gt; can be stored in XML format&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Application&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Consider the following XML snippet which would be a reasonable XML representation of the data:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;data&amp;gt;&lt;br /&gt; &amp;lt;property name="ID" type="System.Data.SqlDbType.UniqueIdentifier" is_mandatory="true" is_reference="false"/&amp;gt;&lt;br /&gt; &amp;lt;property name="IsActive" type="System.Data.SqlDbType.Bit" is_mandatory="false" is_reference="false"/&amp;gt;&lt;br /&gt; &amp;lt;property name="Name" type="System.Data.SqlDbType.NVarChar" is_mandatory="false" is_reference="true"/&amp;gt;&lt;br /&gt;&amp;lt;/data&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;And consider the following XSLT transform:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;xsl:transform match="data/property"&amp;gt;&lt;br /&gt; &amp;lt;xsl:value-of select="concat('if (this.', @Name, ' == null')"/&amp;gt;&lt;br /&gt; &amp;lt;xsl:value-of select="'{'"/&amp;gt;&lt;br /&gt; &amp;lt;xsl:value-of select="'}'"/&amp;gt;&lt;br /&gt; &amp;lt;xsl:value-of select="'else'"/&amp;gt;&lt;br /&gt; &amp;lt;xsl:value-of select="'{'"/&amp;gt;&lt;br /&gt; &amp;lt;xsl:value-of select="'}'"/&amp;gt;&lt;br /&gt;&amp;lt;/xsl:transform&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;If we apply this transform to the data xml, we would generate the following snippet:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;if (this.ID == null)&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;if (this.IsActive == null)&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;if (this.Name == null)&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Interesting.&lt;/p&gt;&lt;p&gt;Three observations can be immediately made now: &lt;/p&gt;&lt;ol&gt;&lt;li&gt;We have something which seems to give us a first approximation of what we want! This positive observation is very important!&lt;br /&gt;&lt;li&gt;XSLT has control structures like &lt;code&gt;&amp;lt;xsl:for-each&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;xsl:if&amp;gt;&lt;/code&gt; which means we seem to have a control language and its processing tools. This is also a positive observation.&lt;br /&gt;&lt;li&gt;It's a right pain-in-the-patootie to write the XSLT by hand. This &lt;em&gt;negative&lt;/em&gt; observation is critically important. &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In fact, if we wanted to write the whole XSLT for the whole class by hand, it would be a laborious and time-consuming procedure. We wrote all of the v1 patterns of Designer this way, and believe us - it was frustrating and difficult work. Emitting apostrophes, quotes, ampersands and getting the formatting right are all singularly difficult, as is debugging any one of a dozen kind of problems that &lt;em&gt;may&lt;/em&gt; crop up. Besides, all those &amp;lt;'s and &amp;gt;'s were starting to look a lot like distorted Lisp parens!&lt;/p&gt;&lt;p&gt;&lt;em&gt;(The similarity with Lisp is a very interesting coincidence. Lisp programmers think nothing of generating Lisp functions at runtime and executing them in-situ. In fact, a functional programming language like Lisp would make generation of heirarchical data structures like XML snippets very easy. More on this later.)&lt;/em&gt;&lt;/p&gt;&lt;p&gt;I'm lazy, remember? Catch me trying to write XSLT by hand longer than I need to! &lt;/p&gt;&lt;p&gt;Watch out for the next article where I'll discuss an approach to &lt;em&gt;generate the XSLT &lt;/em&gt;itself! &lt;/p&gt;&lt;p&gt;In the meanwhile, recap what we discovered here. &lt;strong&gt;We can use XML and XSLT as the basis of our code generation approach, &lt;em&gt;as long as we don't have to write the XSLT by hand&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Laziness Rocks!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-2547725786448837499?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/2547725786448837499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=2547725786448837499' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2547725786448837499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2547725786448837499'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/into-wild-blue-xml.html' title='Into the Wild Blue XML'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-835388967614235728</id><published>2007-02-01T13:18:00.000+05:30</published><updated>2007-02-01T13:46:54.907+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='brightsword'/><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='code-generation'/><title type='text'>The Code-Generation Mindset</title><content type='html'>&lt;p&gt;I'm a lazy guy.&lt;/p&gt;&lt;p&gt;I hate doing the same kind of thing over and over again. That's what computers are good at. So the cool thing to do is to try and get the computer to do the grunge work of writing a program, leaving me to do interesting things like designing the application properly...&lt;/p&gt;&lt;p&gt;There is nothing new about Code-Generation. Compilers have been doing it for years, consuming simpler syntax and higher-level abstractions and churning out instructions native to the execution platform. What's more, programming languages and their compilers have become more intelligent and &lt;em&gt;automatically&lt;/em&gt; perform significant optimizations so that an expert assembly programmer (a dying, if not extinct, breed) would find it hard to improve upon the code generated at the instruction-set level. &lt;/p&gt;&lt;p&gt;And this was old news in 1998...&lt;/p&gt;&lt;p&gt;However, almost ten years on, we're still writing code...&lt;/p&gt;&lt;p&gt;Granted, a lot of the code written in the industry now is in scripting languages, which can be argued to be at a higher level of abstraction than is system or even application programming. However, the same principle holds even now - as is evidenced by the kind of program required to connect to a database table and generate a table of its contents to be viewed on a web page.&lt;/p&gt;&lt;p&gt;"Hang on", you say, "that was a big deal in 2004 - before tools like Visual Studio.NET 2005 came along with their point-and-click wizards which generated all the code for that kind of thing"...&lt;/p&gt;&lt;p&gt;...and you'd be right - that's exactly what I'm saying too. &lt;em&gt;In fact, by the time I'm done with this topic, we'll build the exact pattern (down to tabs, semicolons and spelling mistakes) that Visual Studio.NET 2005 uses in its TypedDataset generator tool. (If that, by itself, isn't remarkable, consider the fact that it took me less than 2 days to write my pattern!)&lt;/em&gt;&lt;/p&gt;&lt;p&gt;What would be nice is if I could apply the code-generation paradigm to any repetitive, semi-mindless pattern of code. The way we currently deal with this now is either:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Cut/Paste/Edit the pattern to fit the requirement. Pray and compile/deploy hoping that the editing was comprehensively correct. Too many problems to list with this approach.&lt;br /&gt;&lt;li&gt;Make the pattern into a soulless library which boils everything to the lowest common denominator and adds a pattern to calling it. &lt;em&gt;Generally&lt;/em&gt; not a huge gain there, plus added complexity.&lt;br /&gt;&lt;li&gt;Use a functional programming language with functions as arguments to the variable bits of the pattern. Maps, Filters and Folds work really well for some kinds of patterns that iterate over a set of items. More on this much later.&lt;br /&gt;&lt;li&gt;Code-Generate. If the pattern is repeated a lot, this is the most sensible approach if you have the tools to do this. I'm going to try and expound on this in a little detail now.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;By the way, let me plug my company here - I founded, and currently work in, &lt;a href="http://www.brightsword.com" target="_blank"&gt;BrightSword Technologies Private Limited&lt;/a&gt;, and I am based in Bangalore, India. We recognised the value of this approach a long time ago, and built a code-generation framework which we have successfully used in a variety of real-world applications. We also took the data-driven web-application as a pattern, and wrote and sold a standalone code-generation tool called BrightSword Designer way back in 2002. We even had the point-and-click wizards for ASP, JSP, PHP and ASP.NET long before Visual Studio.NET 2005, and the ASP pattern implemented inheritance and polymorphism using explicit delegation even though VBScript has neither concept fully implemented!&lt;/p&gt;&lt;p&gt;Anyway, back to the mindset...&lt;/p&gt;&lt;p&gt;To successfully apply the Code-Generation approach, two prerequisites must be fulfilled:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;There must be a recognizable pattern. A pattern of code is basically a chunk of code with a few parts that are invariant, and some variants which change between instances of the pattern.&lt;br /&gt;&lt;li&gt;We must be able to describe the variant portion meaningfully with respect to the pattern.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Let me try to clarify this with an example. Consider this snippet of code you might write when calling a stored procedure using ADO.NET:&lt;/p&gt;&lt;pre&gt;                do&lt;br /&gt;                {&lt;br /&gt;                    try&lt;br /&gt;                    {&lt;br /&gt;                        cmd.Parameters.Add("@p_ID", System.Data.SqlDbType.UniqueIdentifier);&lt;br /&gt;&lt;br /&gt;                        cmd.Parameters["@p_ID"].Value = this.ID;&lt;br /&gt;                    }&lt;br /&gt;                    catch (Exception ex)&lt;br /&gt;                    {&lt;br /&gt;                        System.Diagnostics.Debug.WriteLine(String.Format("Customer.Persist - Persisting Customer.ID threw Exception [ {0} ]. Bailing.", ex.Message));&lt;br /&gt;                        throw ex;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                while(false);&lt;br /&gt;&lt;br /&gt;                do&lt;br /&gt;                {&lt;br /&gt;                    try&lt;br /&gt;                    {&lt;br /&gt;                        cmd.Parameters.Add("@p_IsActive", System.Data.SqlDbType.Bit);&lt;br /&gt;&lt;br /&gt;                        cmd.Parameters["@p_IsActive"].Value = this.IsActive;&lt;br /&gt;                    }&lt;br /&gt;                    catch (Exception ex)&lt;br /&gt;                    {&lt;br /&gt;                        System.Diagnostics.Debug.WriteLine(String.Format("Customer.Persist - Persisting Customer.IsActive threw Exception [ {0} ]. Filling Null Value.", ex.Message));&lt;br /&gt;                        cmd.Parameters["@p_IsActive"].Value = System.DBNull.Value;&lt;br /&gt;&lt;br /&gt;                        break;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                while(false);&lt;br /&gt;&lt;br /&gt;                do&lt;br /&gt;                {&lt;br /&gt;                    try&lt;br /&gt;                    {&lt;br /&gt;                        cmd.Parameters.Add("@p_Name", System.Data.SqlDbType.NVarChar);&lt;br /&gt;&lt;br /&gt;                        if (this.Name == null)&lt;br /&gt;                        {&lt;br /&gt;                            cmd.Parameters["@p_Name"].Value = System.DBNull.Value;&lt;br /&gt;                        }&lt;br /&gt;                        else&lt;br /&gt;                        {&lt;br /&gt;                            cmd.Parameters["@p_Name"].Value = this.Name;&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                    catch (Exception ex)&lt;br /&gt;                    {&lt;br /&gt;                        System.Diagnostics.Debug.WriteLine(String.Format("Customer.Persist - Persisting Customer.Name threw Exception [ {0} ]. Filling Null Value.", ex.Message));&lt;br /&gt;                        cmd.Parameters["@p_Name"].Value = System.DBNull.Value;&lt;br /&gt;&lt;br /&gt;                        break;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                while(false);&lt;br /&gt;&lt;br /&gt;  // mumble the incantation to execute the cmd on the connection&lt;/pre&gt;&lt;p&gt;As a digression, notice that this kind of code contains the kind of bullet-proofing and optimization that you would likely &lt;em&gt;want&lt;/em&gt; to put into your code, but &lt;em&gt;can't &lt;/em&gt;or &lt;em&gt;won't &lt;/em&gt;because it's too tedious. It's far simpler to write the usual code given in all the demos, and leave things to chance and the gods:&lt;/p&gt;&lt;pre&gt;                cmd.Parameters.Add("@p_ID", this.ID);&lt;br /&gt;                cmd.Parameters.Add("@p_IsActive", this.IsActive);&lt;br /&gt;                cmd.Parameters.Add("@p_Name", this.Name);&lt;br /&gt;&lt;br /&gt;  // mumble the incantation to execute the cmd on the connection&lt;/pre&gt;&lt;p&gt;Anyway - let's identify the pattern in the code. &lt;/p&gt;&lt;p&gt;It's basically the piece of code between the "&lt;code&gt;do&lt;/code&gt;" and the "&lt;code&gt;while(false);&lt;/code&gt;". (In reality, the &lt;em&gt;entire class &lt;/em&gt;is the pattern, but let's keep things simple for the example.)&lt;/p&gt;&lt;p&gt;The variant portion of the pattern takes a little recognition. We recognise the obvious:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;the name of the parameter&lt;br /&gt;&lt;li&gt;the type of the parameter&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Not so obvious are the following:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;whether the parameter is mandatory or optional&lt;br /&gt;&lt;li&gt;whether the property of the class is a reference or value type&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So in a formal way, we can say that the metadata (or "type") of the variant is:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;property_metadata ::= {name : string, type : string, is_mandatory : bool, is_reference : bool}  &lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;If we assume a kind of pseudocode notation, we could write&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;template :=&lt;br /&gt; &lt;em&gt;[PATTERN_BEGIN(property : property_metadata)]&lt;/em&gt;&lt;br /&gt;                 do&lt;br /&gt;                 {&lt;br /&gt;                     try&lt;br /&gt;                         {&lt;br /&gt;                         cmd.Parameters.Add("@p_&lt;em&gt;[property.name]&lt;/em&gt;", &lt;em&gt;[property.type]&lt;/em&gt;);&lt;br /&gt;  &lt;em&gt;[IF property.is_mandatory]&lt;/em&gt;&lt;br /&gt;                         cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = this.&lt;em&gt;[property.name]&lt;/em&gt;;&lt;br /&gt;  &lt;em&gt;[ELSE]&lt;/em&gt;&lt;br /&gt;   &lt;em&gt;[IF property.is_reference]&lt;/em&gt;&lt;br /&gt;                         if (this.&lt;em&gt;[property.name]&lt;/em&gt; == null)&lt;br /&gt;                         {&lt;br /&gt;                             cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = System.DBNull.Value;&lt;br /&gt;                         }&lt;br /&gt;                         else&lt;br /&gt;                         {&lt;br /&gt;                             cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = this.&lt;em&gt;[property.name]&lt;/em&gt;;&lt;br /&gt;                         }&lt;br /&gt;   &lt;em&gt;[ELSE]&lt;/em&gt;&lt;br /&gt;                         cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = this.&lt;em&gt;[property.name]&lt;/em&gt;;&lt;br /&gt;   &lt;em&gt;[ENDIF]&lt;/em&gt;&lt;br /&gt;                     }&lt;br /&gt;  &lt;em&gt;[ENDIF]&lt;/em&gt;&lt;br /&gt;                     catch (Exception ex)&lt;br /&gt;                     {&lt;br /&gt;  &lt;em&gt;[IF property.is_mandatory]&lt;/em&gt;&lt;br /&gt;                         System.Diagnostics.Debug.WriteLine(String.Format("Customer.Persist - Persisting Customer.[property.name] threw Exception [ {0} ]. Bailing.", ex.Message));&lt;br /&gt;                         throw ex;&lt;br /&gt;  &lt;em&gt;[ELSE]&lt;/em&gt;&lt;br /&gt;                         System.Diagnostics.Debug.WriteLine(String.Format("Customer.Persist - Persisting Customer.[property.name] threw Exception [ {0} ]. Filling Null Value.", ex.Message));&lt;br /&gt;                         cmd.Parameters["@p_&lt;em&gt;[property.name]&lt;/em&gt;"].Value = System.DBNull.Value;&lt;br /&gt;&lt;br /&gt;                         break;&lt;br /&gt;  &lt;em&gt;[ENDIF]&lt;/em&gt;&lt;br /&gt;                     }&lt;br /&gt;                 }&lt;br /&gt;                 while(false);&lt;br /&gt; &lt;em&gt;[PATTERN_END]&lt;/em&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Now, we can enumerate the parametrizing entities:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;data := {&lt;br /&gt;  {"ID",       "System.Data.SqlDbType.UniqueIdentifier", true,  false},&lt;br /&gt;  {"IsActive", "System.Data.SqlDbType.Bit",              false, false},&lt;br /&gt;  {"Name",     "System.Data.SqlDbType.NVarChar",         false, true}&lt;br /&gt; }&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;It's pretty obvious that with this kind of a setup, we could make the assertion that we could generate the desired block of by somehow &lt;em&gt;apply&lt;/em&gt;ing the &lt;code&gt;data&lt;/code&gt; onto the &lt;code&gt;template&lt;/code&gt;. We simply need some magic wand to perform the desired &lt;em&gt;apply &lt;/em&gt;operation. In pseudo-functional notation,&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;p&gt;code := apply(template, data)&lt;/p&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;My primary assertion in this article is that &lt;strong&gt;recognizing patterns and following the metadata-driven approach will lead to cleaner and better code&lt;/strong&gt;. Thinking this way allows us to worry about bullet-proofing and optimizing our code, because the time invested in strengthening the &lt;em&gt;template &lt;/em&gt;of the pattern is miniscule compared to the time required to scan and change all &lt;em&gt;occurrences &lt;/em&gt;of the pattern. We could extend and strengthen the code by simply modifying the template, or more radically by extending the metadata and template together. One bug fixed or one optimization baked into the template gets multiplied into the generated code. &lt;em&gt;Big Hammer&lt;/em&gt;! &lt;/p&gt;&lt;p&gt;Of course, there is the small matter of performing the &lt;em&gt;apply&lt;/em&gt; operation to somehow take both &lt;code&gt;template&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; to give us code - but you'll have to stay tuned for that!&lt;/p&gt;&lt;p&gt;Food for thought, no? &lt;/p&gt;&lt;p&gt;Well! &lt;em&gt;Bon Appetit&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-835388967614235728?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/835388967614235728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=835388967614235728' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/835388967614235728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/835388967614235728'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/code-generation-mindset.html' title='The Code-Generation Mindset'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-3122490405017845137</id><published>2007-01-31T09:27:00.000+05:30</published><updated>2007-01-31T17:11:52.894+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='vapid sentimental nonsense'/><title type='text'>Technology Indroduction: My Early Years...</title><content type='html'>I've been involved in Computer Science and Technology for my entire career, and for a good portion of my education before...&lt;br /&gt;&lt;br /&gt;I was interested in electronics and tinkering around with Radios and Tape Players from the time I was in 5th grade. My mum, who worked in Indian Institute of Science, helped me build a 555-based flashing LED for the school science fair when I was in 6th grade. My interest in electronics remains until this day...&lt;br /&gt;&lt;br /&gt;The first computer I wrote any software for was a Sinclair ZX Spectrum - while I was still in high school. A couple of friends and I then went on to build our own Zilog Z-80 computer. We wrote programs for these machines in Basic, and using PEEK and POKE to write stuff into memory was considered cutting-edge!&lt;br /&gt;&lt;br /&gt;The first computer I owned was a Macintosh Plus - which was the standard-issue computer for the class of '93 at Dartmouth College. The whole concept of event-driven programming and visually appealing user interfaces was a sea-change from the low-level, command-line based, DOS programs I had written until then. &lt;br /&gt;&lt;br /&gt;I managed to find a balance between the powerful GUI-driven paradigms of the Mac and the NeXT boxes found in the computing clusters at Dartmouth with the command-line and shell-script heavy environments of the unix accounts given to us at the computer science department, so to this day, it's nice to feel at home in both worlds.&lt;br /&gt;&lt;br /&gt;It was here that I made my first contribution to global software - a fix in Emacs, submitted and accepted!&lt;br /&gt;&lt;br /&gt;It was at this time I was offered an internship at Microsoft Corporation, and I had the good fortune to work on Excel 4.5 as a developer in the Charting Group. This introduced me to visual debuggers, x86 assembly code, and production-grade software engineering methodology. Very useful exposure...&lt;br /&gt;&lt;br /&gt;I then spent a short stint at Oracle Corporation after graduating, in the Oracle Forms development team. This was my first experience using industry-strength VMS and Unix tools, and working in an environment where portability between dozens of environments was concern #1. I must say that I really didn't appreciate the experience I got there until much much later...&lt;br /&gt;&lt;br /&gt;My big break was in 1994, when I joined Microsoft Corporation as an employee in the Microsoft Project group. Microsoft Project was one of the coolest, albeit little-known, applications in the Office group, and the team was an extremely talented and hard-working group. In a lot of ways, this was my baptism in fire, and I don't think I had a bigger influence in my career than my team lead and colleagues in those days at Microsoft.&lt;br /&gt;&lt;br /&gt;One of the tasks I was assigned was to help sever the connections between the front and back ends of Project, so that the back end could be replaced with a powerful new custom database. This experience had me touching almost all of the grungiest parts of a version 5 application and gave me a real appreciation for solid software architecture - one of my driving passions to this day. The importance of writing clean, maintainable code within a clean, extensible architecture was driven home so forcefully that I cannot imagine working any other way. It is indeed a valuable skill to keep a balance between performance, future extensibility, maintainability and coding efficiency.&lt;br /&gt;&lt;br /&gt;In addition to this, this was also where I learned the importance of building and maintaining a proper development environment - I became intimately acquainted with the versioning and build processes, identifying and applying software tools and hardware knowledge.&lt;br /&gt;&lt;br /&gt;My first new software project was a project that eventually served as the prototype for SharePoint Portal. The small team that worked on this was on fire to use the collective knowledge to set the foundation for a solid product with a long future, so architectural purity became a driving design guideline. It also introduced me to XML, and gave me a serious primer on database design and usage. Again, I would only appreciate the nuances of what I learned much later...&lt;br /&gt;&lt;br /&gt;I then moved back to India for personal reasons, and joined the fledgling Microsoft India R&amp;D Private Limited, where I worked on what was to become Visual J#. Although some of the work I did here resulted in my first US Patent application, it was becoming clear to me that the time had come for me to move on...&lt;br /&gt;&lt;br /&gt;In March 2000, I resigned from my post at Microsoft, bringing to a close more than 5 years with the software company. By all accounts, these were enjoyable years, where both skills and friendships were forged, and which set me up for the next part of my career...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-3122490405017845137?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/3122490405017845137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=3122490405017845137' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3122490405017845137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3122490405017845137'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/technology-indroduction-my-early-years.html' title='Technology Indroduction: My Early Years...'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-4704735557835070047</id><published>2007-01-31T09:07:00.000+05:30</published><updated>2007-01-31T09:18:40.297+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='smitha'/><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><title type='text'>More Flora..er..Pictures</title><content type='html'>&lt;span style="font-family:arial;"&gt;It's that time of year again...&lt;br /&gt;&lt;br /&gt;January 26 is the Republic Day of India, and in Bangalore, where I live, the local botanical garden puts up a massive flower show.&lt;br /&gt;&lt;br /&gt;I've not been to the show since I was a kid - and it's mayhem out there on the 26th...so Mum, Smitha and I went out there on the first weekend following...&lt;br /&gt;&lt;br /&gt;Smitha wanted to learn how to use the 30D, and I, not having much of a clue myself, thought I'd try a few shots as well.&lt;br /&gt;&lt;br /&gt;We shot almost exclusively with the 75-300 lens. The camera was mostly on High-speed Multi-shot mode, and the lens got a chance to show off the ability to take technically difficult shots of flying bees and beetles...in focus, natch!&lt;br /&gt;&lt;br /&gt;The gardens were still crowded, and the amount of litter everywhere was appalling - yet another indictment of what people who keep their houses spotless will do in public...&lt;br /&gt;&lt;br /&gt;I've uploaded the pictures with reduced resolution to save space. Track back to me if you want any picture in full resolution and I'll do my best to e-mail it to you :)&lt;br /&gt;&lt;br /&gt;Enjoy!!&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="FONT-SIZE: 83%; WIDTH: 194px; FONT-FAMILY: arial,sans-serif; TEXT-ALIGN: center"&gt;&lt;div style="BACKGROUND: url(http://picasaweb.google.com/f/img/transparent_album_background.gif) no-repeat left 50%; HEIGHT: 194px"&gt;&lt;a href="http://picasaweb.google.com/john.azariah/Flora"&gt;&lt;img style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0px; BORDER-TOP: medium none; MARGIN-TOP: 16px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; BORDER-LEFT: medium none; PADDING-TOP: 0px; BORDER-BOTTOM: medium none" height="160" src="http://lh3.google.com/image/john.azariah/RcALzQv6NSE/AAAAAAAAAK4/p_x0PNmXcRk/s160-c/Flora.jpg" width="160" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://picasaweb.google.com/john.azariah/Flora"&gt;&lt;div style="FONT-WEIGHT: bold; COLOR: #4d4d4d; TEXT-DECORATION: none"&gt;Flora&lt;/div&gt;&lt;/a&gt;&lt;div style="COLOR: #808080"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-4704735557835070047?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/4704735557835070047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=4704735557835070047' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/4704735557835070047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/4704735557835070047'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/more-floraerpictures.html' title='More Flora..er..Pictures'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-3367661300666957137</id><published>2007-01-30T15:58:00.000+05:30</published><updated>2007-01-30T16:07:58.177+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='meandering around'/><title type='text'>Flora, Fauna and other Wildlife</title><content type='html'>&lt;span style="font-family:arial;"&gt;Here are some of the pictures taken on the Ooty trip with the 30D.&lt;br /&gt;&lt;br /&gt;The picture quality in some cases has been compromised because I aggressively compressed them on the camera. I need to get a 4GB card (or two) to allow me to take the pictures RAW.&lt;br /&gt;&lt;br /&gt;The kit as it stands now is the 30D body, Canon EFS 18-55 and Canon EFS 75-300 IS.&lt;br /&gt;&lt;br /&gt;The pictures have been uploaded without the corrections proffered by Picasa. So there! :)&lt;br /&gt;&lt;br /&gt;Enjoy&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="FONT-SIZE: 83%; WIDTH: 194px; FONT-FAMILY: arial,sans-serif; TEXT-ALIGN: center"&gt;&lt;div style="BACKGROUND: url(http://picasaweb.google.com/f/img/transparent_album_background.gif) no-repeat left 50%; HEIGHT: 194px"&gt;&lt;a href="http://picasaweb.google.com/john.azariah/FloraAndFauna"&gt;&lt;img style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0px; BORDER-TOP: medium none; MARGIN-TOP: 16px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; BORDER-LEFT: medium none; PADDING-TOP: 0px; BORDER-BOTTOM: medium none" height="160" src="http://lh3.google.com/image/john.azariah/Rb8bkgv6MeE/AAAAAAAAAG0/zlO9yyDCoIk/s160-c/FloraAndFauna.jpg" width="160" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://picasaweb.google.com/john.azariah/FloraAndFauna"&gt;&lt;div style="FONT-WEIGHT: bold; COLOR: #4d4d4d; TEXT-DECORATION: none"&gt;Flora and Fauna&lt;/div&gt;&lt;/a&gt;&lt;div style="COLOR: #808080"&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="FONT-SIZE: 83%; WIDTH: 194px; FONT-FAMILY: arial,sans-serif; TEXT-ALIGN: center"&gt;&lt;div style="BACKGROUND: url(http://picasaweb.google.com/f/img/transparent_album_background.gif) no-repeat left 50%; HEIGHT: 194px"&gt;&lt;a href="http://picasaweb.google.com/john.azariah/TheOotyTripJan15172007"&gt;&lt;img style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0px; BORDER-TOP: medium none; MARGIN-TOP: 16px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; BORDER-LEFT: medium none; PADDING-TOP: 0px; BORDER-BOTTOM: medium none" height="160" src="http://lh6.google.com/image/john.azariah/Rb8dZQv6NGE/AAAAAAAAAG4/nF9FwQ427xs/s160-c/TheOotyTripJan15172007.jpg" width="160" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://picasaweb.google.com/john.azariah/TheOotyTripJan15172007"&gt;&lt;div style="FONT-WEIGHT: bold; COLOR: #4d4d4d; TEXT-DECORATION: none"&gt;The Ooty Trip: Jan 15-17 2007&lt;/div&gt;&lt;/a&gt;&lt;div style="COLOR: #808080"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-3367661300666957137?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/3367661300666957137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=3367661300666957137' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3367661300666957137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/3367661300666957137'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/flora-fauna-and-other-wildlife.html' title='Flora, Fauna and other Wildlife'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-4792787358872989305</id><published>2007-01-30T15:35:00.000+05:30</published><updated>2007-01-30T16:08:19.526+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='smitha'/><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><title type='text'>Smitha!</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/_DNpS0fva8mM/Rb8Ycwv6MdI/AAAAAAAAAAk/ihBAH7aQy58/s1600-h/IMG_2211.JPG"&gt;&lt;span style="font-family:arial;"&gt;&lt;img id="BLOGGER_PHOTO_ID_" alt="" src="http://3.bp.blogspot.com/_DNpS0fva8mM/Rb8Ycwv6MdI/AAAAAAAAAAk/ihBAH7aQy58/s320/IMG_2211.JPG" border="0" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style="CLEAR: both"&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Smitha, my wife, is my favourite photography subject. Usually she acquiesces to my insane demands to "stand here...look there...&lt;strong&gt;there&lt;/strong&gt;...&lt;strong&gt;THERE&lt;/strong&gt;!!!" by gritting her teeth - which makes her smile look wonderful on camera!&lt;br /&gt;She was sitting around while I was fumbling with the 30D the moment I got it, and I managed to squeeze off this spontaneous portrait.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;color:#999999;"&gt;Canon 30D, 70-300mm IS, flash&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-4792787358872989305?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/4792787358872989305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=4792787358872989305' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/4792787358872989305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/4792787358872989305'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/smitha.html' title='Smitha!'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_DNpS0fva8mM/Rb8Ycwv6MdI/AAAAAAAAAAk/ihBAH7aQy58/s72-c/IMG_2211.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-2103412065274379004</id><published>2007-01-30T14:42:00.000+05:30</published><updated>2007-01-30T15:17:40.992+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='the antipodes'/><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='meandering around'/><title type='text'>November 7-10 2006: Sydney, Australia</title><content type='html'>Sydney Opera House&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_DNpS0fva8mM/Rb8KwAv6MaI/AAAAAAAAAAM/OIGc-22LunI/s1600-h/PHOT0378.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_" alt="" src="http://4.bp.blogspot.com/_DNpS0fva8mM/Rb8KwAv6MaI/AAAAAAAAAAM/OIGc-22LunI/s320/PHOT0378.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style='clear:both; text-align:NONE'&gt;All these pictures were taken with Smitha's handy Creative DiViCam. This was taken from a boat as we took a tour of the Sydney Harbour.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The Coat Hanger&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_DNpS0fva8mM/Rb8MDgv6McI/AAAAAAAAAAc/y_Tu54BUw_4/s1600-h/PHOT0430.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_" alt="" src="http://2.bp.blogspot.com/_DNpS0fva8mM/Rb8MDgv6McI/AAAAAAAAAAc/y_Tu54BUw_4/s320/PHOT0430.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="CLEAR: both"&gt;Smitha and I in front of the famous Sydney Harbour Bridge. Someday we'll go on the Bridge Climb! &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Pipe Organ, Sydney Opera House&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_DNpS0fva8mM/Rb8LZgv6MbI/AAAAAAAAAAU/ZuDP7oHcfBI/s1600-h/PHOT0415.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_" alt="" src="http://2.bp.blogspot.com/_DNpS0fva8mM/Rb8LZgv6MbI/AAAAAAAAAAU/ZuDP7oHcfBI/s320/PHOT0415.JPG" border="0" /&gt;&lt;/a&gt;&lt;div style='clear:both; text-align:NONE'&gt;A friend works in the Sydney Opera House so we got a bit of a tour of the inside. This is the pipe organ in the main hall.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-2103412065274379004?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/2103412065274379004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=2103412065274379004' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2103412065274379004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/2103412065274379004'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/coat-hanger.html' title='November 7-10 2006: Sydney, Australia'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_DNpS0fva8mM/Rb8KwAv6MaI/AAAAAAAAAAM/OIGc-22LunI/s72-c/PHOT0378.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-6885901476926409598</id><published>2007-01-30T11:53:00.000+05:30</published><updated>2007-01-30T16:13:41.141+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Yet Another Bright Idea'/><category scheme='http://www.blogger.com/atom/ns#' term='insanity'/><title type='text'>Gimme..Gimme..Gimme..</title><content type='html'>&lt;span style="font-family:arial;"&gt;&lt;br /&gt;So...&lt;br /&gt;&lt;br /&gt;I feel more and more like a Luddite these days...&lt;br /&gt;&lt;br /&gt;I still have a laptop which weighs about half a ton, is made of pig-iron and runs on coal and steam...&lt;br /&gt;&lt;br /&gt;I keep thinking that someday I need to get a new one, if only to retire the mule that hauls it around for me, and I keep looking for that new feature that will finally make me give it all up and buy a new one...&lt;br /&gt;&lt;br /&gt;It's a Dell Inspiron 8200 more or less gifted to me by a good friend - and against all odds, it's survived around 3 years with me. I love its 15" screen with 1600 x 1200 resolution - makes it easy to see a reasonable block of code in Emacs or Visual Studio.&lt;br /&gt;&lt;br /&gt;So I lied - it was a cutting edge machine in its day...&lt;br /&gt;&lt;br /&gt;The real problem is that while it's bulky and really does give my arms a workout carrying it, it is perfectly sufficient for my use - and I do actually write code and stuff on it :)&lt;br /&gt;&lt;br /&gt;What I &lt;em&gt;actually&lt;/em&gt; noticed is that over the last few months, my travel kit has grown to prodigious proportions with power supplies and adapters of all shapes and sizes, so my next purchases will all try to minimize the number of wall-warts and bricks I need to carry around to stay powered up...&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;One laptop from the mesazoic era with its brick...&lt;/li&gt;&lt;li&gt;Pair of simple headphones and mic for Skype...&lt;/li&gt;&lt;li&gt;Mobile phone and its wart...&lt;/li&gt;&lt;li&gt;Bluetooth headset - &lt;em&gt;&lt;span style="font-size:78%;"&gt;ok..so I'm not a Luddite after all -&lt;/span&gt;&lt;/em&gt; and its extension. The extension plugs into the phone's wart so it's not so bad...&lt;/li&gt;&lt;li&gt;A small point-and-shoot digital camera (for undercover paparazzi work :)) and its charger&lt;/li&gt;&lt;li&gt;USB Multi-card reader...&lt;/li&gt;&lt;li&gt;assorted cables...&lt;/li&gt;&lt;li&gt;assorted adapters to deal with international power socket form factors...&lt;/li&gt;&lt;li&gt;A small USB web-cam..&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Now this is after I got rid of&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The PDA and its charger - my phone does a reasonable approximation thereof&lt;/li&gt;&lt;li&gt;The CD-player and its charger - my phone plays music in Offline mode, and I can always boot up the laptop...&lt;/li&gt;&lt;/ul&gt;And I didn't buy an iPod for roughly the same reasons :)&lt;br /&gt;&lt;br /&gt;What would be lovely is if the laptop:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;got a lot smaller (&lt;em&gt;yes..that's within reach&lt;/em&gt;) and had battery power to last an 8 hour flight (&lt;em&gt;that's OK too&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;could play music without having to have it open and turned on and taking up my tray-table on a flight (&lt;em&gt;the newer HPs do just this - score! :))&lt;/em&gt; and &lt;/li&gt;&lt;li&gt;have a fast-enough startup time to actually use as a PDA to check flight schedules and things (&lt;em&gt;this should be easy...my antediluvian Dell comes out of "Hibernate" in 12 seconds flat...&lt;/em&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Now...&lt;br /&gt;&lt;br /&gt;...if only the laptop could &lt;em&gt;also &lt;/em&gt;act as my mobile and use/charge my headset, I could get rid of having to carry my phone on my business trips - my laptop could just be in my backpack as always and I could take calls on the wired or the bluetooth headsets...or heck - just get rid of the wired headset and buy a bluetooth noise-cancelling headband with mic. (Yep - I really was lying about being a Luddite!)&lt;br /&gt;&lt;br /&gt;This shouldn't be too difficult to do - the newer cars already have the ability to accept SIM cards and behave like telephones - muting the music and routing the call to the audio system of the car - so why not on a laptop?&lt;br /&gt;&lt;br /&gt;So that's what its going to take for me to buy a new laptop...&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-6885901476926409598?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/6885901476926409598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=6885901476926409598' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6885901476926409598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6885901476926409598'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/gimmegimmegimme.html' title='Gimme..Gimme..Gimme..'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-5026700601120575945</id><published>2007-01-23T14:04:00.000+05:30</published><updated>2007-01-23T14:11:15.169+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><category scheme='http://www.blogger.com/atom/ns#' term='vapid sentimental nonsense'/><title type='text'>Goodbye Old Friend...</title><content type='html'>I just upgraded to a Canon 30D from a Minolta 800si film SLR.&lt;br /&gt;&lt;br /&gt;I've shot a lot of stuff with the 800si - bought it before a trip to Bryce Canyon in the US - but time and technology move on, and after a lot of compromising (mostly in the form of Digital Point and Shoots), and after a trip to beautiful, picturesque New Zealand with nothing but my Nokia N70 camera-phone, I finally chanced upon an opportunity to get a Canon 30D.&lt;br /&gt;&lt;br /&gt;We went to the Himalayan foothills for the New Year and I shot a couple of rolls with the 800si before finally switching. I think the film roll is finally going the way of the polaroid...&lt;br /&gt;&lt;br /&gt;Took the 30D on a trip to Ootcamund - a hill station close-by - and shot a bunch of water-birds in a bird sanctuary. The machine feels good. I have to still get used to the spot-metering and the AF, but it was a good first outing.&lt;br /&gt;&lt;br /&gt;I'll post a few of the pictures as I get the time...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-5026700601120575945?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/5026700601120575945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=5026700601120575945' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/5026700601120575945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/5026700601120575945'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/goodbye-old-friend.html' title='Goodbye Old Friend...'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2873917929184567506.post-6990441066245537406</id><published>2007-01-23T13:55:00.000+05:30</published><updated>2007-01-23T14:03:08.429+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='insanity'/><category scheme='http://www.blogger.com/atom/ns#' term='the beginning'/><title type='text'>Arrrghhhhhhhh...phewwww</title><content type='html'>Well..I'm finally here.&lt;br /&gt;&lt;br /&gt;What I really want to do is have my other blog's posts moved to this one so I can use my johnazariah.blogspot.com address as my main blog...&lt;br /&gt;&lt;br /&gt;Can't figure out if it can be done...&lt;br /&gt;&lt;br /&gt;Oh well..let me start with this address then!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2873917929184567506-6990441066245537406?l=jazariah.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jazariah.blogspot.com/feeds/6990441066245537406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2873917929184567506&amp;postID=6990441066245537406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6990441066245537406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2873917929184567506/posts/default/6990441066245537406'/><link rel='alternate' type='text/html' href='http://jazariah.blogspot.com/2007/01/arrrghhhhhhhhphewwww.html' title='Arrrghhhhhhhh...phewwww'/><author><name>Patagonian Toothfish</name><uri>http://www.blogger.com/profile/15003030360576324824</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-QG4v2xsSZZg/TmzgNpUym4I/AAAAAAAAIIs/x4LNGuceyfc/s220/d2f4f6d06901c13a9167966cc1b6b678.jpeg'/></author><thr:total>0</thr:total></entry></feed>
