Páginas

Mostrando entradas con la etiqueta Grammar. Mostrar todas las entradas
Mostrando entradas con la etiqueta Grammar. Mostrar todas las entradas

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());
                       
        }