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