473,788 Members | 3,030 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Constant expression evaluation

The following code was written by me.
It is used for evaluating constant expressions.
I think it is good. Any criticism?

namespace Churunmin.Hello World
{
using System;
using System.Collecti ons.Generic;
using System.Diagnost ics;
using System.Text;
using System.Reflecti on;

public class Calculator
{
[AttributeUsage( AttributeTarget s.Field)]
public class TokenAttribute: Attribute
{
private string name;

public TokenAttribute( string name)
{
this.name = name;
}

public string Name
{
get
{
return this.name;
}
}
}

[AttributeUsage( AttributeTarget s.Field)]
public class KeywordAttribut e: TokenAttribute
{
public KeywordAttribut e(string name): base(name)
{
}
}

public class Tokener
{
[Token("<none>")]
public const int TK_NONE = -1;
[Token("<number> ")]
public const int TK_NUMBER = -2;

[Keyword("pi")]
public const int TK_PI = -3;
[Keyword("e")]
public const int TK_E = -4;
[Keyword("sin")]
public const int TK_SIN = -5;
[Keyword("cos")]
public const int TK_COS = -6;
[Keyword("tan")]
public const int TK_TAN = -7;
[Keyword("lg")]
public const int TK_LG = -8;
[Keyword("ln")]
public const int TK_LN = -9;

public const string SIMPLE_TOKENS = "+-*/%^()";

private static readonly Dictionary<int, stringtokenDict ionary =
new Dictionary<int, string>();
public static string TokenToString(i nt token)
{
if (token < 0)
{
return tokenDictionary[token];
}
else if (SIMPLE_TOKENS. IndexOf((char)t oken) >= 0)
{
return ((char)token).T oString();
}
throw new Exception("Atte mpt to convert an invalid token to string:
" + token);
}

private static readonly Dictionary<stri ng, intkeywordDicti onary =
new Dictionary<stri ng, int>();
public static int TokenFromKeywor d(string keyword)
{
if (keywordDiction ary.ContainsKey (keyword))
{
return keywordDictiona ry[keyword];
}
throw new Exception("Atte mpt to convert an invalid keyword to
token: " + keyword);
}

public static void Test()
{
Console.WriteLi ne("keywordDict ionary:");
foreach (KeyValuePair<s tring, intkv in keywordDictiona ry)
{
Console.WriteLi ne("{0} --{1}", kv.Key, kv.Value);
}

Console.WriteLi ne("tokenDictio nary:");
foreach (KeyValuePair<i nt, stringkv in tokenDictionary )
{
Console.WriteLi ne("{0} --{1}", kv.Key, kv.Value);
}
}

static Tokener()
{
FieldInfo[] fields = typeof(Tokener) .GetFields(Bind ingFlags.Static
| BindingFlags.De claredOnly | BindingFlags.Pu blic |
BindingFlags.No nPublic);
foreach (FieldInfo field in fields)
{
TokenAttribute attr = Attribute.GetCu stomAttribute(f ield,
typeof(TokenAtt ribute), false) as TokenAttribute;
if (attr != null)
{
int v = (int)field.GetR awConstantValue ();
tokenDictionary[v] = attr.Name;
if (attr.GetType() == typeof(KeywordA ttribute))
{
keywordDictiona ry[attr.Name] = v;
}
}
}
}
}

public class Scanner: Tokener
{
public double DoubleData;
public int Token;

private StringBuilder cache = new StringBuilder(2 56);

private string data;
private int dataIndex;

private char c;

private void Read()
{
if (dataIndex < data.Length)
{
this.c = data[dataIndex++];
}
else
{
this.c = '\0';
}
}

private bool Check(string s, char c)
{
return s.IndexOf(c) >= 0;
}

private bool Check(string s)
{
return Check(s, this.c);
}

private void Save(char c)
{
this.cache.Appe nd(c);
}

private void Save()
{
Save(this.c);
}

private void SaveRead()
{
Save();
Read();
}

public Scanner(string data)
{
this.data = data;
Read();
Next();
}

private bool IsDigit(char c)
{
return c >= '0' && c <='9';
}

private bool IsLetter(char c)
{
return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
}

private bool ReadNumber()
{
this.cache.Leng th = 0;
if (!IsDigit(this. c))
{
return false;
}
SaveRead();
while (IsDigit(this.c ))
{
SaveRead();
}
if (this.c == '.')
{
SaveRead();
if (!IsDigit(this. c))
{
throw new Exception("The radix point must be followed by
digit.");
}
SaveRead();
while (IsDigit(this.c ))
{
SaveRead();
}
}
this.Token = TK_NUMBER;
this.DoubleData = double.Parse(th is.cache.ToStri ng());
return true;
}

private bool ReadName()
{
this.cache.Leng th = 0;
if (!(IsLetter(thi s.c) || this.c == '_'))
{
return false;
}
SaveRead();
while (IsLetter(this. c) || IsDigit(this.c) || this.c == '_')
{
SaveRead();
}
this.Token = TokenFromKeywor d(this.cache.To String());
return true;
}

private void SkipBlank()
{
while (this.c == ' ')
{
Read();
}
}

public void Next()
{
SkipBlank();
if (this.c == '\0')
{
this.Token = TK_NONE;
return;
}
if (ReadNumber()) return;
if (ReadName()) return;
if (SIMPLE_TOKENS. IndexOf(this.c) >= 0)
{
this.Token = this.c; // +, -, *, /, etc.
Read();
return;
}
throw new Exception("Enco unter invalid character when scanning for
token: '" + this.c + "'");
}

public static new void Test()
{
string s = "3*6+2*pi+e^2%6 6-9000";
Console.WriteLi ne("Scan \"" + s + "\" for tokens:");
Scanner scanner = new Scanner(s);
while (scanner.Token != Scanner.TK_NONE )
{
Console.WriteLi ne(Scanner.Toke nToString(scann er.Token));
scanner.Next();
}
}
}
public class Parser: Scanner
{
private static readonly Dictionary<int, intleftPriority = new
Dictionary<int, int>();
private static readonly Dictionary<int, intrightPriorit y = new
Dictionary<int, int>();
static Parser()
{
leftPriority.Ad d('+', 6); rightPriority.A dd('+', 6);
leftPriority.Ad d('-', 6); rightPriority.A dd('-', 6);
leftPriority.Ad d('*', 7); rightPriority.A dd('*', 7);
leftPriority.Ad d('/', 7); rightPriority.A dd('/', 7);
leftPriority.Ad d('%', 7); rightPriority.A dd('%', 7);
leftPriority.Ad d('^', 10); rightPriority.A dd('^', 9); // right
associative
}

public Parser(string data): base(data)
{
}

public int ParseExpression (out double v, int limit)
{
ParseSimpleExpr ession(out v); // the expression must start with a
simple expression
int op = this.Token;
// expand while operators have priorities higher than 'limit'
while (leftPriority.C ontainsKey(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("Expe cted an operator token, but was: '" +
TokenToString(o p) + "'");
}
op = nextop;
}
return op;
}

private void ParseSimpleExpr ession(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("Unex pected token: '" +
TokenToString(t his.Token) + "'");
}

private void ExpectToken(int t)
{
if (this.Token != t) throw new Exception(Strin g.Format("Expec ted
token: '{0]', but was '{1}'", TokenToString(t ),
TokenToString(t his.Token)));
Next();
}

public static new void Test()
{
double v;
string s = "3*6 + 2 - 10 % 99 + lg(8)/lg(2)";
new Parser(s).Parse Expression(out v, 0);
Console.WriteLi ne("{0} = {1}", s, v);
s = "ln(e^2)";
new Parser(s).Parse Expression(out v, 0);
Console.WriteLi ne("{0} = {1}", s, v);
s = "sin(pi/2)";
new Parser(s).Parse Expression(out v, 0);
Console.WriteLi ne("{0} = {1}", s, v);
foreach(Encodin gInfo ei in Encoding.GetEnc odings())
{
Encoding e = ei.GetEncoding( );
Console.Write( "{0,-6} {1,-25} {2,-40}", ei.CodePage, ei.Name,
ei.DisplayName) ;
Console.WriteLi ne();
}

}
}

public static double Evaluate(string s)
{
double v;
new Parser(s).Parse Expression(out v, 0);
return v;
}
}
}

Jan 21 '07 #1
0 3575

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2579
by: Frank Wallingford | last post by:
Note: For those with instant reactions, this is NOT the common "why is i = i++ not defined?" question. Please read on. I came across an interesting question when talking with my colleagues. According to the standard, most operators evaluate their operands in an unspecified order. This means that in code like this: f() + g()
8
1764
by: Brian Blais | last post by:
Hello, I have a string input from the user, and want to parse it to a number, and would like to know how to do it. I would like to be able to accept arithmetic operations, like: '5+5' '(4+3)*2' '5e3/10**3' I thought of using eval, which will work, but could lead to bad security problems
3
2354
by: lovecreatesbeauty | last post by:
Both `K&R C, 2nd' and `C: A reference manual, 5th' introduce the "hello, world" thing using the name "string-constant". But `ISO/IEC 9899:TC2' does not include this kind of thing in section `A.1.5 Constants'.
21
2419
by: Steven T. Hatton | last post by:
I'm trying to improve my formal understanding of C++. One significant part of that effort involves clarifying my understanding of the vocabulary used to describe the language. This is from the C++ Standard: "" "...sequence of operators and operands that specifies a computation...". That means to me that an expression can be "executed". I am purposely
15
2913
by: skibud2 | last post by:
Consider this example: u8 my_array; for (i = 0; i < (sizeof(my_array)/sizeof(u8)); i++) { ... } In the standard C specification, is the evaluation of '(sizeof(my_array)/sizeof(u8))' to 10 guarenteed to happen at compile
32
3327
by: silpau | last post by:
hi, i am a bit confused on expression evaluation order in expressions involving unary increment.decrement operators along with binary operators. For example in the following expression x += i + j + k++;
3
4767
by: Dan Smithers | last post by:
What constitutes a constant-expression? I know that it is something that can be determined at compile time. I am trying to use template code and keep getting compiler errors "error: cannot appear in a constant-expression" template <int s> class CFoo { private:
7
2813
by: John Koleszar | last post by:
Hi all, I'm porting some code that provides compile-time assertions from one compiler to another and ran across what I believe to be compliant code that won't compile using the new compiler. Not naming names here to remove bias - I'm trying to tell if I'm relying on implementation defined behavior or if this is a bug in the new compiler. Consider this stripped down example:
34
2174
by: jacob navia | last post by:
Hi I am adding an optimization to lcc-win: sqrt(2.0) will provoke now that the constant 1.4142... etc will be generated instead of generating an actual call. Details: -------
0
9655
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9498
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10363
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10172
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9964
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7517
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6749
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5398
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
2894
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.