Irony - Language Implementation Kit/Introduction

 Basic Irony Tutorial

In this tutorial I will be going through the steps to create a basic language called “GridWorld” Syntax. Keep in mind: First, this tutorial was not intended to provide exhaustive knowledge of the Irony tool, and second, that use of the sample projects in the Irony download is strongly recommended.  Chapter 1 -- GridWorld   I. Introduction to GridWorld We will start off by creating a simple language that describes a grid of certain height and width, starts at some location within the grid, and move around within the grid. So here is some possible source code for the GridWorld language:  Create a 10 by 10 grid. Start at location 1,1.                                   (1) Move down 3.                  <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 (2) <p class=MsoNoSpacing>Move right 3. <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 (3) <p class=MsoNoSpacing>Move up 1. <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 (4) <p class=MsoNoSpacing> <p class=MsoNoSpacing>And here is the result, assuming (0,0) is of the form (row, column) and is the top left most square: <p class=MsoNoSpacing>

<p class=MsoNoSpacing> <p class=MsoNoSpacing>You might have already reasoned that it wouldn’t be too difficult to tackle this problem without use of any parsing tool at all. The first two lines of our language will always be the same in every program that we make, with different numbers in place of “10 by 10” and “1,1”, and the next few lines are quite repetitive. Perhaps the program would become more complex if the coder was assigned to <i style='mso-bidi-font-style:normal'>validate the syntax</i> of this toy language. Even still, in this case it would be a relatively easy task. <p class=MsoNoSpacing> <p class=MsoNoSpacing>However, consider writing the same program for a much more complex language such as Python or C#--a primitive approach from scratch, though not impossible, would take a lot of time. Irony offers a robust method to parse language structure. This GridWorld toy problem is a simple basis on which to learn how to tackle much more complex grammars in the future. <p class=MsoNoSpacing> <p class=MsoNoSpacing> II. Creating a GridWorld Grammar class <p class=MsoNoSpacing>The first step in attacking this problem with Irony is to create a Grammar class. This class will act like a generalizing schema to parse source code. First, we’ll need to get the Irony library. <p class=MsoNoSpacing> <p class=MsoNoSpacing style='margin-left:.5in;text-indent:-.25in;mso-list:l3 level1 lfo3'><span style='mso-bidi-font-family:Calibri'> 1.<span style='font:7.0pt "Times New Roman"'>      Download Irony. Go to https://github.com/IronyProject/Irony and get the latest version. <p class=MsoNoSpacing style='margin-left:.5in;text-indent:-.25in;mso-list:l3 level1 lfo3'><span style='mso-bidi-font-family:Calibri'> 2.<span style='font:7.0pt "Times New Roman"'>      Open the main project and build it in Visual Studio. <p class=MsoNoSpacing style='margin-left:.5in;text-indent:-.25in;mso-list:l3 level1 lfo3'><span style='mso-bidi-font-family:Calibri'> 3.<span style='font:7.0pt "Times New Roman"'>      This should generate Irony.dll in “irony-XXXX/Irony/bin/Debug” <p class=MsoNoSpacing style='text-indent:.5in'>Add Irony.dll to your project. <p class=MsoNoSpacing> <p class=MsoNoSpacing>Now, create a class that extends Irony.Grammar <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:blue;mso-no-proof:yes'>using <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> Irony <span style='color: red'>. Parsing ; <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:blue;mso-no-proof:yes'> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:blue;mso-no-proof:yes'>public <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> class <span style='color:navy'>GridWorldGrammar : Grammar <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'>{ <p class=MsoNoSpacing style='text-indent:.5in'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:blue; mso-no-proof:yes'>public <span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> GridWorldGrammar {} <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'>} <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> <p class=MsoNoSpacing>One option we have at this point is to use case sensitivity. The Grammar class has a constructor that takes a bool to define this characteristic, so we could have used the following to support phrases such as “moVE RigHT 1” (by default, the grammar <b style='mso-bidi-font-weight: normal'>is</b> case sensitive): <p class=MsoNoSpacing> <p class=MsoNoSpacing style='text-indent:.5in'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:blue; mso-no-proof:yes'>public <span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> GridWorldGrammar : base ( false ) {} <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> <p class=MsoNoSpacing>In this class, we define the rules of the GridWorld language in BNF. Our language structure has 3 parts to it: the create statement, the start statement, and one or more move statements. We’ll call the entity that contains all three of these parts the <b style='mso-bidi-font-weight: normal'><i style='mso-bidi-font-style:normal'>program</i></b>. The <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>createStatement </i></b>is defined with the words “Create” and “a” followed by a number, “by”, another number, “grid” and a period. A <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>moveStatement </i></b>contains a <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>direction </i></b>and a <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style: normal'>number. </i></b>Everything else in our language is defined in a similar fashion. In BNF, this is… <p class=MsoNoSpacing> <p class=MsoNoSpacing><b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>program</i></b><i style='mso-bidi-font-style: normal'>  :==<span style="mso-spacerun: yes">  <b style='mso-bidi-font-weight: normal'>createStatement</b>  <b style='mso-bidi-font-weight:normal'>startStatement</b><span style="mso-spacerun: yes">  <b style='mso-bidi-font-weight: normal'>moveStatements</b></i> <p class=MsoNoSpacing><b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>createStatement </i></b><i style='mso-bidi-font-style: normal'> :==<span style="mso-spacerun: yes">  “Create”<span style="mso-spacerun: yes">  “a”<span style="mso-spacerun: yes">   <b style='mso-bidi-font-weight:normal'>number</b><span style="mso-spacerun: yes">  “by”<span style="mso-spacerun: yes">   <b style='mso-bidi-font-weight:normal'>number</b><span style="mso-spacerun: yes">  “grid”<span style="mso-spacerun: yes">   “.”</i> <p class=MsoNoSpacing><b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>startStatement </i></b><i style='mso-bidi-font-style: normal'> :==<span style="mso-spacerun: yes">  “Start”<span style="mso-spacerun: yes">   “at” “location”  <b style='mso-bidi-font-weight:normal'>number</b></i><span style="mso-spacerun: yes">  “,” <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style: normal'>number </i></b><i style='mso-bidi-font-style:normal'><span style="mso-spacerun: yes"> “.”</i> <p class=MsoNoSpacing><b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>moveStatements</i></b><i style='mso-bidi-font-style: normal'>  :==<span style="mso-spacerun: yes">  <b style='mso-bidi-font-weight: normal'>moveStatement +</b></i> <p class=MsoNoSpacing><b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>moveStatement</i></b><i style='mso-bidi-font-style: normal'>  :==<span style="mso-spacerun: yes">  “Move”<span style="mso-spacerun: yes">   <b style='mso-bidi-font-weight:normal'>direction</b><span style="mso-spacerun: yes">  <b style='mso-bidi-font-weight: normal'>number</b>  “.”</i> <p class=MsoNoSpacing><b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>direction</i></b><i style='mso-bidi-font-style: normal'>  :==<span style="mso-spacerun: yes">  “up”<span style="mso-spacerun: yes">   | “down”  |<span style="mso-spacerun: yes">  “right”<span style="mso-spacerun: yes">   | “left”</i> <p class=MsoNoSpacing> <p class=MsoNoSpacing>BNF, or Backus-Naur Form, is an important notation that Irony uses to understand grammar definitions. If you are not familiar with it, no sweat, it’s easy to pick up. There are plenty of quick online tutorials, and Google is your friend. <p class=MsoNoSpacing> <p class=MsoNoSpacing>Luckily, there is almost a direct syntactic translation of this BNF description into C# through Irony’s use of overriding operators. First, we must define our Terminals and NonTerminals. Terminals are often predefined constructs, like a number or string. Here, our only Terminal is a number, which we’ll define in terms of a regular expression as “a series of one or more digits”: <p class=MsoNoSpacing> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:navy;mso-no-proof:yes'>RegexBasedTerminal <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> number <span style='color:red'>= new <span style='color:navy'>RegexBasedTerminal ( &quot;number&quot;, &quot;[0-9]+&quot; ); <p class=MsoNoSpacing> <p class=MsoNoSpacing>Everything else in our language is defined as a NonTerminal like so: <p class=MsoNoSpacing> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:navy;mso-no-proof:yes'>NonTerminal <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> program <span style='color:red'>= new <span style='color:navy'>NonTerminal ( &quot;program&quot; ), <p class=MsoNoSpacing style='text-indent:.5in'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:teal; mso-no-proof:yes'>createStatement <span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'> = new <span style='color:navy'>NonTerminal ( &quot;createStatement&quot; ), <p class=MsoNoSpacing style='text-indent:.5in'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:teal; mso-no-proof:yes'>startStatement <span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'> = new <span style='color:navy'>NonTerminal ( &quot;startStatement&quot; ), <p class=MsoNoSpacing style='text-indent:.5in'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:teal; mso-no-proof:yes'>moveStatements <span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'> = new <span style='color:navy'>NonTerminal ( &quot;moveStatements&quot; ), <p class=MsoNoSpacing style='text-indent:.5in'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:teal; mso-no-proof:yes'>moveStatement <span style='font-size:10.0pt;font-family: "Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'> <span style='color:red'>= new <span style='color:navy'>NonTerminal ( &quot;moveStatement&quot; ), <p class=MsoNoSpacing style='text-indent:.5in'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:teal; mso-no-proof:yes'>direction <span style='font-size:10.0pt;font-family: "Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'> <span style='color:red'>= new <span style='color:navy'>NonTerminal ( &quot;direction&quot; ); <p class=MsoNoSpacing> <p class=MsoNoSpacing>Each string in the NonTerminal constructor will be important later on when we navigate a parsed tree. Now we can translate the BNF statements into something Irony can understand. The following is the real meat of our language. <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:green;mso-no-proof:yes'> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>program <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:red;mso-no-proof:yes'>. <span style='font-size:10.0pt;font-family: "Courier New";mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>Rule <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> = createStatement + startStatement + moveStatements ; <p class=MsoNoSpacing> <p class=MsoNoSpacing>This should look familiar; this was the first statement in our BNF rules. <p class=MsoNoSpacing>Saying <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>this</i></b><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:red; mso-no-proof:yes'>+ <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>that </i></b>intuitively means “<b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>this</i></b> before <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style: normal'>that.</i></b>” Similarly, <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>this</i></b><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:red; mso-no-proof:yes'>| <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>that </i></b>means “<b style='mso-bidi-font-weight: normal'><i style='mso-bidi-font-style:normal'>this </i></b>or <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'>that”</i></b> as in BNF. <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>createStatement <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:red;mso-no-proof:yes'>. <span style='font-size:10.0pt;font-family: "Courier New";mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>Rule <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> = ToTerm (<span style='color:purple'>&quot;Create&quot; ) + &quot;a&quot; + number + <span style='color:purple'>&quot;by&quot; + <span style='color:teal'>number <p class=MsoNoSpacing style='text-indent:.5in'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:red; mso-no-proof:yes'>+ <span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> &quot;grid&quot; + &quot;.&quot; ; <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>startStatement <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:red;mso-no-proof:yes'>. <span style='font-size:10.0pt;font-family: "Courier New";mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>Rule <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> = ToTerm (<span style='color:purple'>&quot;Start&quot; ) + &quot;at&quot; + &quot;location&quot; + number + &quot;,&quot; <p class=MsoNoSpacing style='text-indent:.5in'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:red; mso-no-proof:yes'>+ <span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> number + &quot;.&quot; ; <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> <p class=MsoNoSpacing>Anytime a string literal is the first element used in a rule statement, as in both rules above, it’s good practice to put a ToTerm function surrounding the string. It’s not required, but erroneous parsing will occur if ToTerm is not used like this. <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>moveStatements <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:red;mso-no-proof:yes'>. <span style='font-size:10.0pt;font-family: "Courier New";mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>Rule <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> = MakePlusRule (<span style='color:teal'>moveStatements, moveStatement ); <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>moveStatement <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:red;mso-no-proof:yes'>. <span style='font-size:10.0pt;font-family: "Courier New";mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>Rule <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> = ToTerm (<span style='color:purple'>&quot;Move&quot; ) + <span style='color:teal'>direction + <span style='color:teal'>number + <span style='color:purple'>&quot;.&quot; ; <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>direction <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:red;mso-no-proof:yes'>. <span style='font-size:10.0pt;font-family: "Courier New";mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>Rule <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> = ToTerm (<span style='color:purple'>&quot;up&quot; ) | <span style='color:purple'>&quot;down&quot; | <span style='color:purple'>&quot;right&quot; | <span style='color:purple'>&quot;left&quot; ; <p class=MsoNoSpacing> <p class=MsoNoSpacing>Unfortunately, there is not a very easy way to describe the “one or more” and “zero or more” rules. These are called “plus” and “star” rules, respectively, which are drawn from a similar concept in Regex expressions. Irony uses the MakePlusRule and MakeStarRule function to define them. Both are used the same way syntactically, and MakePlusRule can be seen above in the <b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style: normal'>moveStatements</i></b> rule. <p class=MsoNoSpacing> One more statement is required to finish the grammar: <p class=MsoNoSpacing> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:blue;mso-no-proof:yes'>this <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:red;mso-no-proof:yes'>. <span style='font-size:10.0pt;font-family: "Courier New";mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>Root <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> = program ; <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> <p class=MsoNoSpacing>And another statement that will help keep the tree “clean”: <p class=MsoNoSpacing> <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size: 10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New";color:teal; mso-no-proof:yes'>MarkPunctuation <span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'>(<span style='color:purple'>&quot;Create&quot;, &quot;a&quot; , &quot;grid&quot; , &quot;by&quot; , &quot;Start&quot; , &quot;at&quot; , <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;text-indent: .5in;line-height:normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:purple;mso-no-proof:yes'>&quot;location&quot; <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'>, &quot;,&quot; , <span style='color:purple'>&quot;.&quot; , &quot;Move&quot; ); <p class=MsoNoSpacing> <p class=MsoNoSpacing>We’ll discuss this last statement in a little more depth in section IV. That’s it! We have adequately defined a GridWorld grammar to parse a GridWorld program. See the appendix for the complete <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:navy;mso-no-proof:yes'>GridWorldGrammar class. <p class=MsoNoSpacing> <p class=MsoNoSpacing> III. Parsing source code &amp; validating syntax <p class=MsoNoSpacing>Let’s say we have a GUI that has a Textbox, a Button, and a Label. Our Textbox will allow the user to type or paste source code that is in GridWorld syntax. Once a user places their code there, they press the Button, and the Label will state whether or not the syntax is of the right form. <p class=MsoNoSpacing> <p class=MsoNoSpacing>With Irony, this is a very simple operation. Here is a function that returns whether or not some given source code with a given grammar object is valid: <p class=MsoNoSpacing> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:blue;mso-no-proof:yes'>public <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> bool <span style='color: teal'>isValid ( string <span style='color:teal'>sourceCode, Grammar <span style='color:teal'>grammar ) <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'>{ <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     LanguageData language = <span style='color:blue'>new LanguageData (<span style='color:teal'>grammar ); <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     Parser parser = <span style='color:blue'>new Parser (<span style='color:teal'>language ); <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     ParseTree parseTree = <span style='color:teal'>parser. <span style='color:teal'>Parse ( sourceCode ); <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     ParseTreeNode root = <span style='color:teal'>parseTree. <span style='color:teal'>Root ; <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     return root != <span style='color:blue'>null ; <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'>} <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> <p class=MsoNoSpacing>The method this function uses is simple: attempt to parse the given source code with the given grammar’s rules. If this attempt fails, then the source code is not valid. Otherwise, it is valid. In this case we know the parsing failed when the root of the parsed tree doesn’t exist (is of null value). <p class=MsoNoSpacing> <p class=MsoNoSpacing>Obviously, there are different ways to implement this code just as there are different ways to describe our GridWorld language to Irony in the previous section. It is strongly suggested to explore other possibilities, increase understanding and knowledge of how Irony works, and thus reap the full benefits of the Irony tool. <p class=MsoNoSpacing> <p class=MsoNoSpacing> IV. Navigating the language tree &amp; validating content <p class=MsoNoSpacing>We’ve seen how Irony offers an easy and fast way to validate syntax. Now we’re going to take a look at how to examine the content of a parsed language tree. The following code is a function that returns the root of a parsed language tree. As you can see, it looks very similar to the isValid function above. <p class=MsoNoSpacing> <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:blue;mso-no-proof:yes'>public <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'> ParseTreeNode <span style='color:teal'>getRoot ( string <span style='color:teal'>sourceCode, Grammar <span style='color:teal'>grammar ) <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'>{ <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     LanguageData language = <span style='color:blue'>new LanguageData (<span style='color:teal'>grammar ); <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     Parser parser = <span style='color:blue'>new Parser (<span style='color:teal'>language ); <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     ParseTree parseTree = <span style='color:teal'>parser. <span style='color:teal'>Parse ( sourceCode ); <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     ParseTreeNode root = <span style='color:teal'>parseTree. <span style='color:teal'>Root ; <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">     return root ; <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'>} <p class=MsoNoSpacing> <p class=MsoNoSpacing>By using this function, we can explore and display source code in a robust manner. We’ll use the following function to display the tree in the DOS screen: <p class=MsoNoSpacing> <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size: 10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New";color:blue; mso-no-proof:yes'>public <span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'> void dispTree ( ParseTreeNode node, int <span style='color:teal'>level ) <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size: 10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof: yes'>{ <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;text-indent: .5in;line-height:normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:blue;mso-no-proof:yes'>for <span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'>(<span style='color:blue'>int i <span style='color:red'>= 0; i <span style='color:red'>&lt; level ; <span style='color:teal'>i ++ ) <p class=MsoNormal style='margin-top:0in;margin-right:0in;margin-bottom:0in; margin-left:.5in;margin-bottom:.0001pt;text-indent:.5in;line-height:normal; mso-layout-grid-align:none;text-autospace:none'><span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:navy; mso-no-proof:yes'>Console <span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:red;mso-no-proof:yes'>. <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:teal;mso-no-proof:yes'>Write <span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'>(<span style='color:purple'>&quot; &quot; ); <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;text-indent: .5in;line-height:normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:navy;mso-no-proof:yes'>Console <span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";color:red; mso-no-proof:yes'>. <span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";color:teal;mso-no-proof:yes'>WriteLine <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'>( node ); <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size: 10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof: yes'> <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;text-indent: .5in;line-height:normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:blue;mso-no-proof:yes'>foreach <span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'> ( ParseTreeNode child in node <span style='color:red'>. ChildNodes ) <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'><span style="mso-spacerun: yes">          <span style='color:teal'>dispTree ( child, <span style='color:teal'>level + 1); <p class=MsoNoSpacing><span style='font-size:10.0pt;font-family:"Courier New"; mso-bidi-font-family:"Courier New";mso-no-proof:yes'>} <p class=MsoNoSpacing> <p class=MsoNoSpacing>Now, let’s parse some code and compare outputs. Recall this statement we used at the very end of the grammar in section III: <p class=MsoNoSpacing> <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size: 10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New";color:teal; mso-no-proof:yes'>MarkPunctuation <span style='font-size:10.0pt; font-family:"Courier New";mso-bidi-font-family:"Courier New";mso-no-proof:yes'>(<span style='color:purple'>&quot;Create&quot;, &quot;a&quot; , &quot;grid&quot; , &quot;by&quot; , &quot;Start&quot; , &quot;at&quot; , <p class=MsoNormal style='margin-bottom:0in;margin-bottom:.0001pt;text-indent: .5in;line-height:normal;mso-layout-grid-align:none;text-autospace:none'><span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; color:purple;mso-no-proof:yes'>&quot;location&quot; <span style='font-size:10.0pt;font-family:"Courier New";mso-bidi-font-family:"Courier New"; mso-no-proof:yes'>, &quot;,&quot; , <span style='color:purple'>&quot;.&quot; , &quot;Move&quot; ); <p class=MsoNoSpacing> <p class=MsoNoSpacing>If we had not included this statement, the parsed tree from the source code in Figure 1 would look like that of Figure 2. However, since we added the statement to “help keep the tree clean,” the parsed tree looks like Figure 3. As you can see, MarkPunctuation is a very handy function. <p class=MsoNoSpacing>

<p class=MsoNoSpacing style='text-indent:.5in'>Figure 1<span style='mso-tab-count: 1'>                 <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 Figure 2                 <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 <span style='mso-tab-count:1'>                 Figure 3 <p class=MsoNoSpacing> <p class=MsoNoSpacing>Note: the names in this tree do not derive from the names of the Terminal and NonTerminal variables we used when defining the grammar, but rather from the string argument sent to the constructor of each variable when they were each declared. <p class=MsoNoSpacing> <p class=MsoNoSpacing>There are a number of ways to now go about reading the tree and producing some output. Note that this means your language is an interpreted language, not a compiled language; you must write the interpreter. I cooked up a function that uses the tree format in Figure 3 to create a grid similar to the one in section 1. See it in the appendix or in the example code included with this tutorial. <p class=MsoNoSpacing> <p class=MsoNoSpacing>Checking content, as well as validating syntax, is an important part of validating a language source code. This is because being able to determine which parts of code are incorrect or correct allows the developer to communicate to the user, often through syntax highlighting. <p class=MsoNoSpacing> <p class=MsoNoSpacing>For example, the function I wrote to display a grid from the language tree here can be easily broken if the user writes GridWorld code that goes off the grid, or tells the interpreter to start at a location not on the grid. These mistakes certainly wouldn’t be caught by the syntax validator function seen above; they are practically run-time errors. The developer could decide to check for these sort of errors, and then highlight the offending numbers in red. Thus, a user’s confusion and frustration can easily be avoided by making use of a content-checker. <p class=MsoNoSpacing> <p class=MsoNoSpacing>That’s all there is to making a simple domain-specific language parser with Irony! Please see Code Appendix One or the included source code to view what was discussed in the last few sections. <p class=MsoNoSpacing> <p class=MsoNoSpacing>The next section will deal with using some of Irony’s more advanced tools, and then I will go into how to maintain a slightly more complex language called “Manchester Syntax” that I created during the summer of 2010. <p class=MsoNoSpacing> <p class=MsoNoSpacing> V. Irony’s tools <p class=MsoNoSpacing>See the README.txt file in the irony-XXXXX folder that you downloaded from http://irony.codeplex.com/ for information on how to use Irony’s grammar explorer.