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()); }
No hay comentarios:
Publicar un comentario