续一下,还没完 public class Parser: Scanner
{
private static readonly Dictionary<int, int> leftPriority = new Dictionary<int, int>();
private static readonly Dictionary<int, int> rightPriority = new Dictionary<int, int>();
static Parser()
{
leftPriority.Add('+', 6); rightPriority.Add('+', 6);
leftPriority.Add('-', 6); rightPriority.Add('-', 6);
leftPriority.Add('*', 7); rightPriority.Add('*', 7);
leftPriority.Add('/', 7); rightPriority.Add('/', 7);
leftPriority.Add('%', 7); rightPriority.Add('%', 7);
leftPriority.Add('^', 10); rightPriority.Add('^', 9); // right associative
} public Parser(string data): base(data)
{
} public int ParseExpression(out double v, int limit)
{
ParseSimpleExpression(out v); // the expression must start with a simple expression
int op = this.Token;
// expand while operators have priorities higher than 'limit'
   while (leftPriority.ContainsKey(op) && leftPriority[op] > limit)
   {
   Next();
   double rhs; // right hand side
   // read expression with higher priority
   int nextop = ParseExpression(out rhs, rightPriority[op]);
   switch (op)
   {
   case '+':
   v = v + rhs;
   break;
   case '-':
   v = v - rhs;
   break;
   case '*':
   v = v * rhs;
   break;
   case '/':
   v = v / rhs;
   break;
   case '%':
   v = v % rhs;
   break;
   case '^':
   v = Math.Pow(v, rhs);
   break;
   default:
throw new Exception("Expected an operator token, but was: '" + TokenToString(op) + "'");
   }
   op = nextop;
   }
   return op;
} private void ParseSimpleExpression(out double v)
{
if (this.Token == TK_NUMBER)
{
v = this.DoubleData;
Next();
return;
}
if (this.Token == TK_PI)
{
v = Math.PI;
Next();
return;
}
if (this.Token == TK_E)
{
v = Math.E;
Next();
return;
}
if (this.Token == TK_SIN)
{
Next();
ExpectToken('(');
ParseExpression(out v, 0);
ExpectToken(')');
v = Math.Sin(v);
return;
}
if (this.Token == TK_COS)
{
Next();
ExpectToken('(');
ParseExpression(out v, 0);
ExpectToken(')');
v = Math.Cos(v);
return;
}
if (this.Token == TK_TAN)
{
Next();
ExpectToken('(');
ParseExpression(out v, 0);
ExpectToken(')');
v = Math.Tan(v);
return;
}
if (this.Token == TK_LG)
{
Next();
ExpectToken('(');
ParseExpression(out v, 0);
ExpectToken(')');
v = Math.Log10(v);
return;
}
if (this.Token == TK_LN)
{
Next();
ExpectToken('(');
ParseExpression(out v, 0);
ExpectToken(')');
v = Math.Log(v);
return;
}
throw new Exception("Unexpected token: '" + TokenToString(this.Token) + "'");
} private void ExpectToken(int t)
{
if (this.Token != t) throw new Exception(String.Format("Expected token: '{0]', but was '{1}'", TokenToString(t), TokenToString(this.Token)));
Next();
} public static new void Test()
{
double v;
string s = "3*6 + 2 - 10 % 99 + lg(8)/lg(2)";
new Parser(s).ParseExpression(out v, 0);
Console.WriteLine("{0} = {1}", s, v);
s = "ln(e^2)";
new Parser(s).ParseExpression(out v, 0);
Console.WriteLine("{0} = {1}", s, v);
s = "sin(pi/2)";
new Parser(s).ParseExpression(out v, 0);
Console.WriteLine("{0} = {1}", s, v);
foreach(EncodingInfo ei in Encoding.GetEncodings())
{
Encoding e = ei.GetEncoding();
Console.Write( "{0,-6} {1,-25} {2,-40}", ei.CodePage, ei.Name, ei.DisplayName);
Console.WriteLine();
} }
} public static double Evaluate(string s)
{
double v;
new Parser(s).ParseExpression(out v, 0);
return v;
}
}
}