patterncsharpMinor
Hello There Calculator
Viewed 0 times
hellotherecalculator
Problem
The open source project I work on uses Antlr4 pretty heavily, but I don't know much about it. I thought I would use April's Community Challenge as an opportunity to learn something about grammars, lexers, and parsers.
My calculator only handles integer multiplication, division, addition, and subtraction, but it does handle the order of operations correctly. Whitespace is stripped away, so it's optional, and the calculator will throw an
Is there anything I could have done better? I do think I want to go back and add support for exponentiation and parenthesis later, but that's later.
GitHub repo here.
BasicMathGrammar.g4
IntegerMathVisitor.cs
```
class IntegerMathVisitor : BasicMathBaseVisitor
{
public override int VisitCompileUnit(BasicMathParser.CompileUnitContext context)
{
// There can only ever be one expression in a compileUnit. The other node is EOF.
return Visit(context.expression(0));
}
public override int VisitNumber(BasicMathParser.NumberContext context)
{
return int.Parse(context.GetText());
}
public override int VisitAddition(BasicMathParser.AdditionContext context)
{
var left = WalkLeft(context);
var right = WalkRight(context);
return left + right;
}
public override int VisitSubtraction(BasicMathParser.SubtractionContext context)
{
var left = WalkLeft(context);
My calculator only handles integer multiplication, division, addition, and subtraction, but it does handle the order of operations correctly. Whitespace is stripped away, so it's optional, and the calculator will throw an
ArgumentException if it's passed an expression that it doesn't understand.Is there anything I could have done better? I do think I want to go back and add support for exponentiation and parenthesis later, but that's later.
GitHub repo here.
BasicMathGrammar.g4
grammar BasicMath;
/*
* Parser Rules
*/
compileUnit : expression+ EOF;
expression :
expression MULTIPLY expression #Multiplication
| expression DIVIDE expression #Division
| expression ADD expression #Addition
| expression SUBTRACT expression #Subtraction
| NUMBER #Number
;
/*
* Lexer Rules
*/
NUMBER : INT; //Leave room to extend what kind of math we can do.
INT : ('0'..'9')+;
MULTIPLY : '*';
DIVIDE : '/';
SUBTRACT : '-';
ADD : '+';
WS : [ \t\r\n] -> channel(HIDDEN);IntegerMathVisitor.cs
```
class IntegerMathVisitor : BasicMathBaseVisitor
{
public override int VisitCompileUnit(BasicMathParser.CompileUnitContext context)
{
// There can only ever be one expression in a compileUnit. The other node is EOF.
return Visit(context.expression(0));
}
public override int VisitNumber(BasicMathParser.NumberContext context)
{
return int.Parse(context.GetText());
}
public override int VisitAddition(BasicMathParser.AdditionContext context)
{
var left = WalkLeft(context);
var right = WalkRight(context);
return left + right;
}
public override int VisitSubtraction(BasicMathParser.SubtractionContext context)
{
var left = WalkLeft(context);
Solution
First, I have to mention that I'm very happy that you chose to explore antlr! ...looking at what you've done here, you now know more about
But ANTLR aside...
Classes are
I don't like the name you've chosen for
I'm not sure about this line here:
You just instantiated it, does it come with error listeners for free? If so, that deserves a comment. If not, then that line could be removed.
Visitor and ErrorNode than I do!But ANTLR aside...
Classes are
internal unless specified otherwise; still it would be nice to be explicit about it, and stick that internal modifier in front of your internal classes.I don't like the name you've chosen for
ThrowExceptionErrorListener - it makes the type's name sound like a method, as throw is a verb, and class names should be nouns. How about ThrowingErrorListener?I'm not sure about this line here:
lexer.RemoveErrorListeners();You just instantiated it, does it come with error listeners for free? If so, that deserves a comment. If not, then that line could be removed.
Code Snippets
lexer.RemoveErrorListeners();Context
StackExchange Code Review Q#87889, answer score: 8
Revisions (0)
No revisions yet.