Páginas

martes, 21 de febrero de 2012

Snippets... from creation to usage.

After finding about "cw" C# code snippet for Console.WriteLine() I tried to Console.ReadLine a lot of times by typing "cr" until I decided to create my own snippet and I'll do it again here with you.

First we add a new XML file to our project named ReadLine.snippet. We add now a snippet template by right clicking in the code Editor and select Insert Snippet. We proceed now to modify the template, since we are creating an expansion snippet we remove the <snippettype>SurroundsWith</snippettype> tag. In the title tag we name our snippet ReadLine and in the author tag you write your own name. Now is time to change the shortcut tag wich is the trigger of our snippet and why not we change it for "cr". In the description tag we add a short description of the snippet.

Since we are creating a C# snippet we change the language in the code tag for CSharp, and add the code inside CDATA[/*code goes here*/]. Our resulting snippets looks this way:


  <CodeSnippet Format="1.0.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <Header>
    <Title>Console.ReadLine()</Title>
    <Author>Enrique M. Castañeda</Author>
    <Shortcut>cr</Shortcut>
    <Description>Console.ReadLine()</Description>
    <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
    </SnippetTypes>
  </Header>
  <Snippet>
    <Declarations>
      <Literal>
        <ID>author</ID>
        <Default>Enrique M. Castañeda</Default>
      </Literal>
    </Declarations>
    <Code Language="CSharp">
      <![CDATA[Console.ReadLine();]]>
    </Code>
  </Snippet>
</CodeSnippet>

Is time to load our created snippet into VisualStudio to use it everywhere. To get it done we just go to Tools int the main menu and click on Code Snippet Manager. Once there we import our snippet from our current solution folder. We can then select where to place the snippet.

Now we are ready to type "cr" in any code file and Console.ReadLine(); will show. If we forget our snippet name we can just right click in the editor and select Insert Snippet.

martes, 14 de febrero de 2012

Getting an expression evaluated

Have you ever try to make a parser without any parsing technique? I had to. My first year in university we were oriented to make a Functions Evaluator, that allows the user to evaluate expressions, but also graph, derivate and compose Functions. Was quite a challenge.

While the Functions hierarchy, wich I pretend to post some time in the near future, was nicely done based on the Math namespace, the parse part wasn´t. I ended up with a cs file of more than 640 lines of code and a lot of recursive work. That kept me very upset, because even when the job was done and it ran (still does) very well is not a code I´m proud of.

But I got a major revelation when a couple of years later in the Compiler course we were introduced to Context-Sensitive Grammars and ANTLR and the example was an expression grammar. First thing I did was running ANTLR and get revenge in a couple of minutes of all the sleepless nights in first year. This is the basics operations version (+-*/), but the remaining functions are easily addable.


options
{
 language = 'CSharp';
}
expression returns [int value]
 : t = term {$value = $t.value;}
 ('+' t = term {$value += $t.value;}
 | '-' t = term {$value -= $t.value;}) *;

term  returns [int value]
 :  f = factor {$value = $f.value;}
 ('*'  f = factor {$value *= $f.value;}
 | '/' f = factor {if($f.value != 0)
    $value /= $f.value;
      else
       Console.WriteLine("Not Divide by Zero");})*; 
factor  returns [int value]
 : NUMBER {$value = int.Parse($NUMBER.text);}
 | '('e = expression')'{$value = $e.value;};

NUMBER 
 : (DIGIT)+;
fragment DIGIT
 : '0'..'9';

After the lexer and parser code generation through the ANTLR option, the rest was only add the Antlr.Runtime.dll reference to the project and code what follows:

  static void Main(string[] args)
        {            
            string exp = Console.ReadLine();

            ANTLRStringStream stream = new ANTLRStringStream(exp);
            calcLexer lexer = new calcLexer(stream);
            CommonTokenStream tokenStream = new CommonTokenStream(lexer);
            calcParser parser = new calcParser(tokenStream);
            
            Console.WriteLine(parser.expression());
                       
        }