Skip to content

Instantly share code, notes, and snippets.

View toptensoftware's full-sized avatar

Brad Robinson toptensoftware

View GitHub Profile
// No parens
Assert.AreEqual(Parser.Parse("10 + 20 * 30").Eval(), 610);
// Parens
Assert.AreEqual(Parser.Parse("(10 + 20) * 30").Eval(), 900);
// Parens and negative
Assert.AreEqual(Parser.Parse("-(10 + 20) * 30").Eval(), -900);
// Nested
// Parenthesis?
if (_tokenizer.Token == Token.OpenParens)
{
// Skip '('
_tokenizer.NextToken();
// Parse a top-level expression
var node = ParseAddSubtract();
// Check and skip ')'
// Negative
Assert.AreEqual(Parser.Parse("-10").Eval(), -10);
// Positive
Assert.AreEqual(Parser.Parse("+10").Eval(), 10);
// Negative of a negative
Assert.AreEqual(Parser.Parse("--10").Eval(), 10);
// Woah!
// Parse a unary operator (eg: negative/positive)
Node ParseUnary()
{
// Positive operator is a no-op so just skip it
if (_tokenizer.Token == Token.Add)
{
// Skip
_tokenizer.NextToken();
return ParseUnary();
}
[TestMethod]
public void AddSubtractTest()
{
// Add
Assert.AreEqual(Parser.Parse("10 + 20").Eval(), 30);
// Subtract
Assert.AreEqual(Parser.Parse("10 - 20").Eval(), -10);
// Sequence
public class Parser
{
// Constructor - just store the tokenizer
public Parser(Tokenizer tokenizer)
{
_tokenizer = tokenizer;
}
Tokenizer _tokenizer;
// Construct an expression tree
var expr = new NodeBinary(
new NodeNumber(10),
new NodeNumber(20),
(a,b) => a + b
);
// Evaluate it
var result = expr.Eval();
// NodeBinary for binary operations such as Add, Subtract etc...
class NodeBinary : Node
{
// Constructor accepts the two nodes to be operated on and function
// that performs the actual operation
public NodeBinary(Node lhs, Node rhs, Func<double, double, double> op)
{
_lhs = lhs;
_rhs = rhs;
_op = op;
public abstract class Node
{
public abstract double Eval();
}
class NodeNumber : Node
{
public NodeNumber(double number)
{
_number = number;
var testString = "10 + 20 - 30.123";
var t = new Tokenizer(new StringReader(testString));
// "10"
Assert.AreEqual(t.Token, Token.Number);
Assert.AreEqual(t.Number, 10);
t.NextToken();
// "+"
Assert.AreEqual(t.Token, Token.Add);