<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Aaron Feng: Translation Part 2 via Abstract Syntax Tree</title>
    <link>http://aaronfeng.com/articles/2007/04/26/translation-part-2-via-abstract-syntax-tree</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Adventures in software development</description>
    <item>
      <title>Translation Part 2 via Abstract Syntax Tree</title>
      <description>&lt;p&gt;&lt;a href="http://aaronfeng.com/articles/2007/04/14/csharp-to-pl-sql"&gt;Last post&lt;/a&gt; I created a simple translator by using &lt;a href="http://www.antlr.org/v3/index.html"&gt;ANTLR V3&lt;/a&gt; that translated C# (or Java) like syntax into PL/SQL.  The translation relied heavily on &lt;a href="http://www.stringtemplate.org/"&gt;String Template&lt;/a&gt; and token rewrite.  It generated the following PL/SQL statements from a single class declaration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drop table&lt;/li&gt;
&lt;li&gt;Drop sequence&lt;/li&gt;
&lt;li&gt;Create table&lt;/li&gt;
&lt;li&gt;Create sequence&lt;/li&gt;
&lt;li&gt;Create Trigger (sequence and trigger are for auto increment id column)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice there was not a one-to-one relationship between the input and the output.  Output like this is ideal for template based translation, but not when you are constructing an Abstract Syntax Tree (AST).  The reason is the tree nodes will have to be duplicated in order to render multiple items from a single input.  &lt;/p&gt;

&lt;p&gt;In this example, my language will stay the same, but output will only contain the creation of table.  In the future post, I will change the language into something simpler, and the ability to output all the previous items (drop table, create auto-incremented column) separately.  In this example I only want to focus on the basics on creating AST by keeping everything else as simple as possible.&lt;/p&gt;

&lt;p&gt;Let's take look at the new parser and lexer grammar.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="constant"&gt;CSharpSQL&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;g&lt;/span&gt;

&lt;span class="ident"&gt;grammar&lt;/span&gt; &lt;span class="constant"&gt;CSharpSQL&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;options&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
 &lt;span class="ident"&gt;output&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;AST&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
 &lt;span class="constant"&gt;ASTLabelType&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;CommonTree&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;

&lt;span class="ident"&gt;tokens&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
 &lt;span class="constant"&gt;CLASSDEF&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
 &lt;span class="constant"&gt;VARDEF&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;

&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="ident"&gt;parser&lt;/span&gt;
&lt;span class="ident"&gt;program&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;declaration&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="constant"&gt;System&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;out&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;println&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="global"&gt;$declaration&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;tree&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;toStringTree&lt;/span&gt;&lt;span class="punct"&gt;());&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;declaration&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;class_statement&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;{&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;variable_statement&lt;/span&gt;&lt;span class="punct"&gt;)*&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;}&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
                &lt;span class="punct"&gt;-&amp;gt;&lt;/span&gt; ^&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;class_statement&lt;/span&gt; &lt;span class="ident"&gt;variable_statement&lt;/span&gt;&lt;span class="punct"&gt;*)&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;class_statement&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;scope_modifier&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;class&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="constant"&gt;ID&lt;/span&gt;
                   &lt;span class="punct"&gt;-&amp;gt;&lt;/span&gt; ^&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;CLASSDEF&lt;/span&gt; &lt;span class="constant"&gt;ID&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;variable_statement&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;scope_modifier&lt;/span&gt; &lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="constant"&gt;ID&lt;/span&gt;  &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
                      &lt;span class="punct"&gt;-&amp;gt;&lt;/span&gt; ^&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;VARDEF&lt;/span&gt; &lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="constant"&gt;ID&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;scope_modifier&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;public&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="ident"&gt;more&lt;/span&gt; &lt;span class="ident"&gt;can&lt;/span&gt; &lt;span class="ident"&gt;be&lt;/span&gt; &lt;span class="ident"&gt;added&lt;/span&gt;
&lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;string&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
     &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;int&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
     &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;decimal&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
     &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;DateTime&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="ident"&gt;lexer&lt;/span&gt;
&lt;span class="constant"&gt;ID&lt;/span&gt;  &lt;span class="punct"&gt;:&lt;/span&gt;   &lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;'..'&lt;/span&gt;&lt;span class="string"&gt;z&lt;/span&gt;&lt;span class="punct"&gt;'|'&lt;/span&gt;&lt;span class="string"&gt;A&lt;/span&gt;&lt;span class="punct"&gt;'..'&lt;/span&gt;&lt;span class="string"&gt;Z&lt;/span&gt;&lt;span class="punct"&gt;'|'&lt;/span&gt;&lt;span class="string"&gt;_&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt; &lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;'..'&lt;/span&gt;&lt;span class="string"&gt;z&lt;/span&gt;&lt;span class="punct"&gt;'|'&lt;/span&gt;&lt;span class="string"&gt;A&lt;/span&gt;&lt;span class="punct"&gt;'..'&lt;/span&gt;&lt;span class="string"&gt;Z&lt;/span&gt;&lt;span class="punct"&gt;'|'&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'..'&lt;/span&gt;&lt;span class="string"&gt;9&lt;/span&gt;&lt;span class="punct"&gt;'|'&lt;/span&gt;&lt;span class="string"&gt;_&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="constant"&gt;WS&lt;/span&gt;  &lt;span class="punct"&gt;:&lt;/span&gt;   &lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;\t&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;\r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;\n&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;)+&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="global"&gt;$channel&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;HIDDEN&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first thing to notice is the tokens declaration before the program rule.  Since the the output will be a tree, tokens declaration defines a set of virtual tokens that can be used as tree nodes.  Virtual token help the tree parser to understand the relationship between nodes.  In this example there are two virtual tokens, CLASSDEF and VARDEF.  We need a way to distinguish the difference between variable name and the name of the class since we cannot tell by the token itself.  Class name will have CLASSDEF as its root node, and variable name will have VARDEF as its root node.&lt;/p&gt;

&lt;p&gt;Each rule returns a subtree by "rewriting" the input using the -&gt; notation.  Everything on the right hand side of -&gt; encodes the hierarchy of the subtree.  The token closest to the ^ symbol is the root node, and rest within the parentheses are the children of the root.  Notice that we only keep the meaningful nodes in the tree, and discard any unnecessary input by "rewriting" them.  Some rules do not return a subtree, but simply delegate the other rules to return the subtree.&lt;/p&gt;

&lt;p&gt;Now we need a tree walker to visit each node in the tree so it can render the final output.  The tree walker grammar is shown below:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="constant"&gt;Translate&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;g&lt;/span&gt;
&lt;span class="ident"&gt;tree&lt;/span&gt; &lt;span class="ident"&gt;grammar&lt;/span&gt; &lt;span class="constant"&gt;Translate&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;options&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
 &lt;span class="ident"&gt;tokenVocab&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;CSharpSQL&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
 &lt;span class="constant"&gt;ASTLabelType&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;CommonTree&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;

&lt;span class="attribute"&gt;@members&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
 &lt;span class="constant"&gt;String&lt;/span&gt; &lt;span class="ident"&gt;className&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
 &lt;span class="constant"&gt;List&lt;/span&gt;&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="constant"&gt;String&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;columns&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="constant"&gt;ArrayList&lt;/span&gt;&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="constant"&gt;String&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;

&lt;span class="ident"&gt;program&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;declaration&lt;/span&gt;
          &lt;span class="punct"&gt;{&lt;/span&gt;
           &lt;span class="constant"&gt;String&lt;/span&gt; &lt;span class="ident"&gt;table&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;CREATE TABLE &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;className&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;\n&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;(&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;\n&lt;/span&gt;&lt;span class="punct"&gt;';&lt;/span&gt;
           &lt;span class="constant"&gt;String&lt;/span&gt; &lt;span class="ident"&gt;seperator&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;,&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt;
           &lt;span class="constant"&gt;Object&lt;/span&gt;&lt;span class="punct"&gt;[]&lt;/span&gt; &lt;span class="ident"&gt;arrayColumns&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;columns&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;toArray&lt;/span&gt;&lt;span class="punct"&gt;();&lt;/span&gt;
           &lt;span class="keyword"&gt;for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;int&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;arrayColumns&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;++)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
            &lt;span class="keyword"&gt;if&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="ident"&gt;arrayColumns&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="ident"&gt;seperator&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt;
            &lt;span class="ident"&gt;table&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;arrayColumns&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;toString&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;seperator&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;\n&lt;/span&gt;&lt;span class="punct"&gt;';&lt;/span&gt;
           &lt;span class="punct"&gt;}&lt;/span&gt;
           &lt;span class="ident"&gt;table&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt;
           &lt;span class="constant"&gt;System&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;out&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;println&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;table&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;
           &lt;span class="ident"&gt;columns&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;clear&lt;/span&gt;&lt;span class="punct"&gt;();&lt;/span&gt;
          &lt;span class="punct"&gt;}&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;declaration&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; ^&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;CLASSDEF&lt;/span&gt; &lt;span class="constant"&gt;ID&lt;/span&gt; &lt;span class="ident"&gt;variable_statement&lt;/span&gt;&lt;span class="punct"&gt;*)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;className&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="global"&gt;$ID&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;variable_statement&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; ^&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;VARDEF&lt;/span&gt; &lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="constant"&gt;ID&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
                     &lt;span class="punct"&gt;{&lt;/span&gt;
                      &lt;span class="ident"&gt;columns&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="global"&gt;$ID&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;text&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="global"&gt;$type&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; NOT NULL&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;);&lt;/span&gt;
                     &lt;span class="punct"&gt;}&lt;/span&gt; &lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="ident"&gt;returns&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="constant"&gt;String&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
    &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;string&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="global"&gt;$value&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;nvarchar(255)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;int&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;   &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="global"&gt;$value&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;integer&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;decimal&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="global"&gt;$value&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;number(21,6)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;DateTime&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;  &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="global"&gt;$value&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;date&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="punct"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is where all the translation happens.  Once again we have a couple of member variables declared in @members to help collect all the required fields for the translation.  The tree grammar rule is very similar to parser or lexer rule.  Since the input is a tree, you need to define rules that will match the nodes in the tree.  You construct the rules by specifying the relationships between nodes using the same syntax parser used to create the tree.  We know whenever the tree walker sees the CLASSDEF one of the child nodes (ID) is the class name.  CLASSDEF can have zero or more variable_statement which means it can have zero or more VARDEF as its children.  Each VARDEF contains exactly two children nodes, a type and ID which is used to construct column definition.&lt;/p&gt;

&lt;p&gt;Let's run the recognizer using the following test program:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;java&lt;/span&gt;
&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;org&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;antlr&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;runtime&lt;/span&gt;&lt;span class="punct"&gt;.*;&lt;/span&gt;
&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;org&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;antlr&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;runtime&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;tree&lt;/span&gt;&lt;span class="punct"&gt;.*;&lt;/span&gt;
&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;java&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;io&lt;/span&gt;&lt;span class="punct"&gt;.*;&lt;/span&gt;

&lt;span class="ident"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Test&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
 &lt;span class="ident"&gt;public&lt;/span&gt; &lt;span class="ident"&gt;static&lt;/span&gt; &lt;span class="ident"&gt;void&lt;/span&gt; &lt;span class="ident"&gt;main&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;String&lt;/span&gt;&lt;span class="punct"&gt;[]&lt;/span&gt; &lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="ident"&gt;throws&lt;/span&gt; &lt;span class="constant"&gt;Exception&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
  &lt;span class="constant"&gt;ANTLRInputStream&lt;/span&gt; &lt;span class="ident"&gt;input&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="constant"&gt;ANTLRInputStream&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;System&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;in&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;
  &lt;span class="constant"&gt;CSharpSQLLexer&lt;/span&gt; &lt;span class="ident"&gt;lexer&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="constant"&gt;CSharpSQLLexer&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;
  &lt;span class="constant"&gt;TokenRewriteStream&lt;/span&gt; &lt;span class="ident"&gt;tokens&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="constant"&gt;TokenRewriteStream&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;lexer&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;

  &lt;span class="constant"&gt;CSharpSQLParser&lt;/span&gt; &lt;span class="ident"&gt;parser&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="constant"&gt;CSharpSQLParser&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;tokens&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;
  &lt;span class="constant"&gt;CSharpSQLParser&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;program_return&lt;/span&gt; &lt;span class="ident"&gt;r&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;parser&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;program&lt;/span&gt;&lt;span class="punct"&gt;();&lt;/span&gt;

  &lt;span class="constant"&gt;CommonTree&lt;/span&gt; &lt;span class="ident"&gt;tree&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;CommonTree&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getTree&lt;/span&gt;&lt;span class="punct"&gt;();&lt;/span&gt;
  &lt;span class="constant"&gt;CommonTreeNodeStream&lt;/span&gt; &lt;span class="ident"&gt;nodes&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="constant"&gt;CommonTreeNodeStream&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;tree&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;
  &lt;span class="constant"&gt;Translate&lt;/span&gt; &lt;span class="ident"&gt;walker&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="constant"&gt;Translate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;nodes&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;
  &lt;span class="ident"&gt;walker&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;program&lt;/span&gt;&lt;span class="punct"&gt;();&lt;/span&gt;
 &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice that the output of the parser is passed into the Translate tree walker for the translation.&lt;/p&gt;</description>
      <pubDate>Thu, 26 Apr 2007 22:27:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:0d000ac8-93b0-4dcf-990b-bae802418217</guid>
      <author>Aaron Feng</author>
      <link>http://aaronfeng.com/articles/2007/04/26/translation-part-2-via-abstract-syntax-tree</link>
      <category>programming</category>
    </item>
  </channel>
</rss>
