Skip to content

Instantly share code, notes, and snippets.

@gszauer
Created February 14, 2022 08:46
Show Gist options
  • Save gszauer/2e7bd915bbc9099d472f9d0264f5a03c to your computer and use it in GitHub Desktop.
Save gszauer/2e7bd915bbc9099d472f9d0264f5a03c to your computer and use it in GitHub Desktop.
MathParser.cs
// <expression> -> <term> (("+" | "-") <term>)*
// <term> -> <power> (("*" | "/") <power>)*
// <power> -> <unary> ("^" <power>)*
// <unary> -> ("-")? <unary> | <factor>
// <factor> -> NUMBER | "(" <expression> ")"
class Program {
public static void Main(String[] args) {
Program p = new Program("3");
Console.ReadLine();
}
int Token;
string Source;
public Program(string source) {
Source = source;
Token = 0;
Console.WriteLine("Result: " + Expression());
}
char Current() {
if (Token >= Source.Length) {
return '\0';
}
return Source[Token];
}
void SkipWhitespace() {
char c = Current();
while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
Token++;
c = Current();
}
}
double Expression() {
// <expression> -> <term> (("+" | "-") <term>)*
double left = Term();
SkipWhitespace();
char c = Current();
while (c == '+' || c == '-') {
Token++; // Eat + or -
double right = Term();
if (c == '+') {
left = left + right;
} else if (c == '-') {
left = left - right;
}
SkipWhitespace();
c = Current();
}
return left;
}
double Term() {
// <term> -> <power> (("*" | "/") <power>)*
double left = Power();
SkipWhitespace();
char c = Current();
while (c == '*' || c == '/') {
Token++; // Eat * or /
double right = Power();
if (c == '*') {
left = left * right;
}
else if (c == '/') {
left = left / right;
}
SkipWhitespace();
c = Current();
}
return left;
}
double Power() {
// <power> -> <unary> ("^" <power>)*
double factor = Unary();
SkipWhitespace();
char c = Current();
if (c == '^') {
Token++; // Eat ^
double power = Power();
return Math.Pow(factor, power);
}
return factor;
}
double Unary() {
// <unary> -> ("-")? <unary> | <factor>
SkipWhitespace();
char c = Current();
if (c == '-') {
Token++; // Eat negative
return -1.0 * Unary();
}
return Factor();
}
double Factor() {
SkipWhitespace();
char c = Current();
if (c == '(') {
Token++; // Eat (
double expr = Expression();
SkipWhitespace();
c = Current();
if (c != ')') {
throw new Exception("Invalid expression in factor");
}
Token++; // Eat )
return expr;
}
return Number();
}
double Number() {
SkipWhitespace();
char c = Current();
if (c >= '0' && c <= '9') {
string tmp = String.Empty;
while (c >= '0' && c <= '9') {
tmp += c.ToString();
Token++;
c = Current();
}
if (c == '.') {
tmp += c.ToString();
Token++; // Eat .
c = Current();
if (c >= '0' && c <= '9') {
while (c >= '0' && c <= '9') {
tmp += c.ToString();
Token++;
c = Current();
}
}
else {
throw new Exception("Invalid number format");
}
}
return Double.Parse(tmp);
}
throw new Exception("Invalid number");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment