```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleCalculator
{
class Parser : Scanner
{
/// <summary>
/// Parser class, inherits from Scanner class
/// Each method (except contructor) assumes that get_token has been called.
/// It means that curr_tok holds the next token to be analysed.
/// </summary>
/// <summary>
/// Parser custom default constructor.
/// Defines two mathematical "constants".
/// </summary>
public Parser()
{
SymbolTable.Add("pi", Math.PI);
SymbolTable.Add("e", Math.E);
}
//some things are done here, no more loop
public double prim()
{
switch (curr_tok)
{
case token_value.NAME:
if (get_token() == token_value.ASSIGN)
{
string remember = name_string; //get_token might change name_string
curr_tok = get_token();
number_value = expr();
if (!SymbolTable.ContainsKey(remember))
{
SymbolTable.Add(remember, number_value);
}
else
{
SymbolTable[remember] = number_value;
}
return number_value;
}
if (SymbolTable.TryGetValue(name_string, out number_value))
{
return number_value;
}
return number_value;
case token_value.NUMBER:
curr_tok = get_token();
return number_value;
case token_value.MINUS: //unary minus
curr_tok = get_token();
return -prim();
case token_value.LPAREN:
curr_tok = get_token();
double e = expr();
if (curr_tok != token_value.RPAREN) { Error(") expected"); return 0.0; }
curr_tok = get_token();
return e;
case token_value.SQRT:
if (FindLeftParentesis())
{
curr_tok = get_token();
double f = expr();
if (curr_tok != token_value.RPAREN) { Error(") expected"); return 0.0; }
curr_tok = get_token();
if (f >= 0.0)
{
return Math.Sqrt(f);
}
else
{
Error("A square root of a negative is not possible.");
}
}
Error("Bad function syntax"); return 0.0;
default:
Error("primary expected");
return 0.0;
}
}
//handles multiplication and division
public double term()
{
double left = prim();
for (; ; ) //"for ever" and to avoid error "not all code paths return a value"
switch (curr_tok)
{
case token_value.MUL:
curr_tok = get_token();
left *= prim();
break;
case token_value.DIV:
curr_tok = get_token();
double d = prim();
if (d == 0) { Error("Divide by 0"); return double.NaN; }
left /= d;
break;
default:
return left;
}
}
//handles addition and sustraction
public double expr()
{
double left = term();
for( ; ; ) //"for ever" and to avoid error "not all code paths return a value"
switch (curr_tok)
{
case token_value.PLUS:
curr_tok = get_token();
left += term();
break;
case token_value.MINUS:
curr_tok = get_token();
left -= term();
break;
default:
return left;
}
}
}
}
```

The article starter has earned a lot of community kudos, and such articles offer a bounty for quality replies.