Click here to Skip to main content
Click here to Skip to main content

A Tiny Expression Evaluator

By , 18 Aug 2011
 
TinyExe.png

Introduction

@TinyExe stands for "a Tiny Expression Evaluator". It is a small commandline utility that allows you to enter simple and more complex mathematical formulas which will be evaluated and calculated on the spot. Even though there are already a number of expression evaluators around on CodeProject and beyond, this particular project is meant mainly to demonstrate the possibilities of @TinyPG. @TinyPG is a parser generator used to create various types of languages and is described in another article here on CodeProject.

This expression evaluator therefore is based on a typical parser/lexer based compiler theory. The implementation of the sementics is done in pure C# codebehind. Since @TinyPG also generates pure and clearly readable C#, consequently this expression evaluator is a set of fully contained C# source code, without requiring any external dependencies. It can therefore be easily used within your own projects. This project also contains the grammar file used to generate the scanner and the parser, so feel free to modify the grammar for your own needs.

In this article, I will expain mainly:

  • Some of the features currently supported by this expression evaluator
  • How to use this evaluator engine within your own projects
  • How to extend the functionality of this evaluator as to adapt it to your own purposes

Background

Due to a lack of good example grammars and demos on how to use @TinyPG, I decided to build a demonstration project which shows how @TinyPG can be used for more advanced grammars such as expression evaluators. So why create an Expression Evaluator for the purpose of a demo? Because well, runtime Expression Evaluators are cool! Take Excel for example, it's the most widely used runtime Expression Evaluator used today. Wouldn't it be awesome to unleash some of that power of Excel inside your own applications?

So, since a runtime expression evaluator may just come in handy, I thought this would make a nice demo project. Note that this is not just a demo though. This expression evaluator is fully functional and ready to execute!

Even though @TinyPG comes with a small tutorial on how to write a simple expression evaluator, I decided to show that @TinyPG can be used to produce powerful LL(1)-grammars. This project also nicely demonstrates how the grammar and syntax can be cleanly separated from the semantics. The calculation rules are implemented separately from the parser and scanner.

Using the Tool

The functionality of the tool is based on the implementation as used in Excel. Currently the expression evaluator supports the following features:

  • It can parse mathematical expressions, including support for the most commonly used functions,e.g.:
    • 4*(24/2-5)+14
    • cos(Pi/4)*sin(Pi/6)^2
    • 1-1/E^(0.5^2)
    • min(5;2;9;10;42;35)
  • The following functions are supported:
    • About Abs Acos And Asin Atan Atan2 Avg Ceiling Clear Cos Cosh Exp Fact Floor Format Help Hex If Floor Left Len Ln Log Lower Max Min Mid Min Not Or Pow Right Round Sign Sin Sinh Sqr Sqrt StDev Trunc Upper Val Var
  • Basic string functions:
    • "Hello " & "world"
    • "Pi = " & Pi
    • Len("hello world")
  • Boolean operators:
    • true != false
    • 5 > 6 ? "hello" : "world"
    • If(5 > 6;"hello";"world")
  • Function and variable declaration
    • x := 42
    • f(x) := x^2
    • f(x) := sin(x) / cos(x)    // declare new dynamic functions using built-in functions
    • Pi
    • E
  • Recursion and scope
    • fac(n) := (n = 0) ? 1 : fac(n-1)*n     // fac calls itself with different parameters
    • f(x) = x*Y       // x is in function scope, Y is global scope
  • Helper functions
    • Help() - lists all built-in functions
    • About() - displays information about the utility
    • Clear() - clears the display

Basically when starting the tool, simply type the expression you want to calculate directly on the commandline. Use up and down buttons for autocompletion of previously entered expressions and formulas. Isn't this just so much easier than using the windows calculator? Anyway, currently only 5 datatypes are supported: double, hexidecimal, int, string and boolean. Note that integers (and hexadecimals also) are always converted to doubles when used in a calculation by default. Use the int() function to convert to integer explicitly.

The tool uses the following precedence rules for its operators:

1. ( ), f(x) Grouping, functions
2.  !   ~   -   + (most) unary operations
3. ^ Power to (Excel rule: that is a^b^c -> (a^b)^c
3. *   /   % Multiplication, division, modulo
4. +   - Addition and subtraction
4. & concatenation of strings
5. <   <=   >   >= Comparisons: less-than, ...
6. =   !=   <> Comparisons: equal and not equal
7. && Logical AND
8. || Logical OR
9.  ?: Conditional expression
10 := Assignment

Embedding the Evaluator Engine

If you would like to embed this Tiny Expression Evaluator inside your own projects, there are only a few simple steps involved.

  1. Copy the Evaluator folder including all classes inside it into your own C# project. In short, we have the following classes:
    1. Context - The context holds all available declared functions and variables and the scope stack.
    2. Expression - Wrapper class that holds and evaluates the expression.
    3. Function - Defines the prototype for a function. A function must have a name, a pointer (delegate) to an actual implementation of a function and it must have the minimum and maximum allowed number of paramters set.
    4. Functions - This class defines the list of default available functions. Feel free to add your own to the list.
    5. Parser - The parser for the expression. This code is generated by TinyPG.
    6. ParseTree - the resulting parse tree after parsing the expression. This code is generated by TinyPG.
    7. ParseTreeEvaluator - This is a subclass of ParseTree and implements the core semantics of the operators. The code should be pretty easy to understand, since the methods of the class correspond directly with the defined grammar (see TinyExe.tpg).
    8. Scanner - This is the scanner used by the parser to match against terminals inside the expression. This class is also generated by TinyPG.
    9. Variables - This is currently implemented as a (case-sensitive) dictionary. A variable is simply a <name, value> pair.
  2. Add the namespace (in this case TinyExe, but feel free to change it) to your classes.
  3. Then, insert the following code to execute an evaluation:
   string expr = "1*3/4"; // define the expression as a string
   ...
   // create the Expression object providing the string
   Expression exp = new Expression(expr);
   
   // check for parse errors
    if (exp.Errors.Count > 0)
    {
        Console.WriteLine(exp.Errors[0].Message);
        return;
    }
    
    // No parse error, go ahead and evaluate the expression
    // Note that Eval() always returns an object that can be of various types
    // you will need to check for the type yourself
    object val = exp.Eval();
    
    // check for interpretation errors (e.g. is the function defined?)
    if (exp.Errors.Count > 0)
    {
        Console.WriteLine(exp.Errors[0].Message);
        return;
    }
    // nothing returned, nothing to evaluate or some kind of error occured?
    if (val == null)
        return;
        
    //print the result to output as a string
    Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}", val));

The code above handles any expression gracefully. But just to be absolutely sure, you might want to trap any exception in a try...catch statement.

Extending the Evaluator Engine

Basically, there are 2 kinds of extensions you can make:

  1. Add your own built-in functions within the allowed syntax of the evaluator
  2. Enhance or change the syntax, therefore changing the grammar

Adding a Static Function

The easiest way to add a new function is to open up the Functions class, and add your implementation in the InitDefaults() method. If you prefer to externalize your function, then you should add your function to the Context.Default.Functions.

For example:

Context.Default.Functions.Add("myfunc", new StaticFunction("MyFunc", MyFunc, 2, 3));

where the MyFunc function is declared as:

private static object MyFunc(object[] parameters) { ... }

Parameters are passed as a list of objects. The number of objects will always be the same as specified in the declaration, in this case a minumum of 2 parameters and a mixumum of 3. The function will need to check the number of parameters and check for the correct type being passed.

In a more advanced setting, e.g., if you need access to the Context object, or to other classes in your project, you can implement your own version of the Function class. You  will need to create a subclass derived from the Function class and implement the Eval() method. Also, you will need to take care of the initialization of arguments, Parametersettings and handle the scope. As an example, take a look at the ClearFunction class.

Changing the Syntax

In order to change the syntax and add new features to the expression language, e.g. add support for extra datatypes (i.e., Date/Time, Money) or allow custom datatypes (i.e., structs), or maybe even more exotic: allow evaluaton of JavaScript, you will need to have a fundamental understanding of parsers and compiler theory. Please have a look at the @TinyPG parser generator article, it explains the basics on how to create a parser for your language.

Just changing the syntax will not be sufficient. It's quite easy to change the grammar used to parse the input, but the semantics (code behind) will also need to be updated accordingly. Luckily the ParseTree that is generated is quite straightforward in use. Suppose for example that we would like to support an new rule, e.g. an IF-THEN-ELSE statement. We could add a new statement in the grammer file (see the included TinyExe.tpg):

IfThenElseStatement	-> IF RelationalExpression THEN Expression (ELSE Expression)?;

When generating the code with @TinyPG for the Scanner, Parser and ParseTree, typically the ParseTree will now contain an addition method called:

protected virtual object EvalIfThenElseStatement
		(ParseTree tree, params object[] paramlist)

As you can see, the method is declared as virtual, meaning you can override this method in a subclass. This is exactly what I did in TinyExe. The ParseTreeEvaluator is a subclass of ParseTree and contains all necessary overrides. The main reason for putting this in a subclass, is that I can now change the grammar of the parser over and over again, and generate a new ParseTree, without the subclass being overwritten.

So what you need to do is override the function in the ParseTreeEvaluator class. You need to understand that this method is called just-in-time, while evaluating the parsetree. At some point during parsing the input, the Parser created a new ParseNode of type IfThenElseStatement. During evaluation of this node, the corresponding EvalIfThenElseStatement (your overriden method!) is called.

At the point of entry in this method, you need to understand that the current ParseNode (of type IfThenElseStatement) is actually this. Because the statement contains 6 parts (of which the last 2 of the ELSE part are optional), this will contain 4 or 6 Nodes:

  1. this.Nodes[0] corresponds to the ParseNode of type IF
  2. this.Nodes[1] corresponds to the RelationalExpression
  3. this.Nodes[2] corresponds to the ParseNode of type THEN
  4. this.Nodes[3] corresponds to the Expression Node
  5. If this.Nodes[4] exists, it will correspond to the ELSE node
  6. if this.Nodes[5] exists, it will correspond to the Expression Node.

So again, I hope this makes clear that the structure of the ParseTree is straightforward and can be quickly resolved back to the original grammar.

Now, the nodes that are of real interest are nodes 1, 3 and 5 of course. So first, we evaluate Nodes[1]. Because Nodes[1] is a non-terminal, it means it can contains a complete subtree. This subtree needs to be evaluated. To make this easier, you can make use of the helper function this.GetValue().

object result = this.GetValue(tree, TokenType.RelationalExpression, 0);

Note that we expect the result of the evaluation to be a boolean value (true or false), however we cannot be certain. So make sure to first check the type of the return value. If this turns out not to be boolean, raise an error.

If result is true, then we can repeat the procedure and evaluate Nodes[3] and return this value. Otherwise we evaluate Nodes[5] (if it exists) and return that.

This is basically in a nutshell 2 ways how extensions are supported. If you have additional questions, just drop me a line.

Points of Interest

Apart from writing a fully functional-handy-comprehensive-easy-to-use-tiny-formula-calculation-utility that by far outperforms your default windows calculator, I also hope that this project will serve as a good demonstration on how @TinyPG can be used in a real-world-scenario.

Of course, there are always new features that could be added, however for now I think this demontration shows nicely how you can create a quite powerful language with some basic knowledge of grammars, parsers and of course a bit of c#.

So that's it. If you have any ideas for new features, comments or remarks, please drop a note!

HistoryHistory

@TinyExe v1.0

Tiny Expression Evaluator Version 1.0 was released on 16st of August 2011. This version includes the following features:

  • Evaluation of mathematical functions and expressions
  • Default built-in functions
  • Runtime function and variable declarations
  • Function-scoped and global variables
  • Recursive function calls
  • Multiple datatype support (double, int, hex, bool and string)
  • Recursive function calls
  • Predefined constants Pi en E
  • Boolean operators and assignments

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Herre Kuijpers
Architect Capgemini
Netherlands Netherlands
Currently Herre Kuijpers is employed at Capgemini Netherlands for over 10 years, where he developed skills with all kinds of technologies, methodologies and programming languages such as c#, ASP.Net, Silverlight, VC++, Javascript, SQL, UML, RUP, WCF. Currently he fulfills the role of software architect in various projects.
 
Herre Kuijpers is a very experienced software architect with deep knowledge of software design and development on the Microsoft .Net platform. He has a broad knowledge of Microsoft products and knows how these, in combination with custom software, can be optimally implemented in the often complex environment of the customer.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionADoubt in implementationmemberMathi2code15-May-13 1:01 
Hi Herre,
 

I'm having a list of Excel Formulae like IF(NOT(false),IF((2+5)=0,0,26),25)
 
And as you have mentioned I'm passing that formula to Expression and getting the output Value.
 
Here What is the use of each class could you please help me in understanding in detail.
 
Since I'm new to c# kindly help me so that I'll learn more.
 
Specifically I dont understand wht Parser, ParseTree,ParseTreeEvaluator,Scanner,Variables,CommandPromt.cs,TextHighlighter.cs
Also I'm not getting as you said code generated by TinyPG.
 
Please explain me in detail with the same example so that I can understand clearly.
 
Thanks in Advance,
Mathi
AnswerRe: ADoubt in implementationmemberHerre Kuijpers15-May-13 2:04 
the expression you provided is not correct, it contains parse errors. hence you will not get a valid value.
 
the expression separators are not a comma, but semicolons, hence you should use:
 
IF(NOT(false);IF((2+5)=0;0;26);25)
 
Parser, ParseTree, Scanner and TextHighlighter are files that are generated by TinyPG. these are responsible for correctly parsing the input statement into an evaluation tree. This is the ParseTree. each node in the ParseTree corresponds to an element in the orgionally defined grammar (please also read the article about TinyPG if you want to know more about these files). These files are generated by TinyPG based on the grammar specified.
 
ParseTreeEvaluator is a subclass of ParseTree and contains the logic to calculate the expression (once it is parsed correctly).
 
Variables contains the list of variables defined at runtime in the commandline tool.
CommandPrompt is specifically created for TinyExe and contains the commandline logic.
Herre

GeneralRe: A Doubt in implementationmemberMathi2code16-May-13 17:06 
Thanks a lot Herre,
Will look into TinyPG article and will post you if any help required. Please do help me.
 
With Regards,
Mathi
GeneralMy vote of 5memberMathi2code4-Apr-13 22:44 
really extra-ordinary
QuestionI'm getting an error when I try the below codememberMathi2code4-Apr-13 2:11 
Hi Herre,
I'm getting an error as below for the following code. The condition for which I'm trying to evaluate is IF(5>4,1,2)
"Unexpected token '' found. Expected BRACKETCLOSE". Kindly help me.
 
string expr = "IF(5>4,1,2)";
                // create the Expression object providing the string
                Expression exp = new Expression(expr);
 
                // check for parse errors
                if (exp.Errors.Count > 0)
                {
                    //Console.WriteLine(exp.Errors[0].Message);
                    //return;
                    liMessage.Text = exp.Errors[0].Message;
                }
 
                // No parse error, go ahead and evaluate the expression
                // Note that Eval() always returns an object that can be of various types
                // you will need to check for the type yourself
                object val = exp.Eval();
 
                // check for interpretation errors (e.g. is the function defined?)
                if (exp.Errors.Count > 0)
                {
                    //Console.WriteLine(exp.Errors[0].Message);
                    //return;
                    liMessage.Text = exp.Errors[0].Message;
                }
                // nothing returned, nothing to evaluate or some kind of error occured?
                if (val == null)
                    return;
 
                //print the result to output as a string
                liMessage.Text = string.Format(CultureInfo.InvariantCulture, "{0}", val);

AnswerRe: I'm getting an error when I try the below codememberHerre Kuijpers4-Apr-13 6:34 
its IF(5>4;1;2)
Herre

GeneralRe: I'm getting an error when I try the below codememberMathi2code4-Apr-13 22:43 
Thanks a lot Herre.so while using IF conditions from EXCEL formula we need to replace all the Commas with Semi-colon. Am I right ?
GeneralRe: I'm getting an error when I try the below codememberHerre Kuijpers5-Apr-13 1:39 
yes; I believe that is the excel standard.
Herre

GeneralRe: I'm getting an error when I try the below codememberMathi2code24-Apr-13 21:39 
Hi Herre,
 
When I am trying to use ROUND functionality it is throwing error.
in Excel we have 2 parameters like ROUND("Value","Digit")
so if the expressions is Round(10.26,0) it should give 10
if the expressions is Round(10.26,1) it should give 10.3
 
This fails here if I give 2 parameters but it works well and good for one parameter ROUND(10.3) alone.
 
Please suggest how to edit this function.
 
<pre lang="c#">this.Add("round", new StaticFunction("Round", delegate(object[] ps) { return Math.Round(Convert.ToDouble(ps[0])); }, 1, 1));</pre>
Thanks in Advance,
Mathi.
GeneralRe: I'm getting an error when I try the below codememberHerre Kuijpers24-Apr-13 21:48 
change the statement to:
 
            this.Add("round", new StaticFunction("Round", delegate(object[] ps) { 
                if (ps.Length == 1)
                    return Math.Round(Convert.ToDouble(ps[0])); 
                else
                    return Math.Round(Convert.ToDouble(ps[0]), Convert.ToInt32(ps[1])); 
            }, 1, 2));
Herre

GeneralRe: I'm getting an error when I try the below codememberMathi2code25-Apr-13 6:25 
Smile | :) Thanks a lot Herre. You're real Genius
QuestionExtra check in in lessthan.. why?memberHawVie30-Dec-12 10:47 
Hi Herre,
 
Simple question. Why is there an extra check for the 'Not followed by >' in the lessthan operator?
 
LESSTHAN		-> @"<(?!>)"; // matches only when not followed by >
 
I would expect the same for the greater than operator:
 
GREATERTHAN		-> @">";
 
That one could also match to ">="? But I tested it but it works. It's weird.. I don't understand why greater than doesn't require a extra check for the "="
 
Regards,
 
Jacob
AnswerRe: Extra check in in lessthan.. why?memberHawVie31-Dec-12 2:28 
My bad, I already found out that the extra check is to prevent a clash with the greater than literal.. Smile | :)
GeneralRe: Extra check in in lessthan.. why?memberHerre Kuijpers2-Jan-13 3:54 
hi,
actually it is required to prevent a clash with the NOTEQUAL <> operator.
 
cheers,
Herre

QuestionReplaceing SEMICOLON for COMMAmemberBig Jim24-Jun-12 20:18 
Hi Herre,
 
Awesome work!
 
Had a quick play to add a new function and 'seems' to work... Smile | :)
this.Add("regex", new StaticFunction("Regex", delegate(object[] ps) { return Regex.IsMatch(ps[0].ToString(), ps[1].ToString()); }, 2, 2));
 
I presume you used ';' as the delimiter to support EU based numbers?
 
I commented out the SEMICOLON token and then updated the usages to be COMMA (I'm EN-NZ Smile | :) ). Have updated the test input value everything passes so it 'seems' ok... am I right to think that I'm safe to continue now with COMMA (with the caveat that we wouldn't support multi language numbers)...? Smile | :)
 
Cheers and thanks again! Smile | :)
 
Jim
AnswerRe: Replaceing SEMICOLON for COMMAmemberHerre Kuijpers29-Jun-12 23:48 
Hi Jim,
 
I've used the Excel convention which uses semicolons to separate arguments.
if you choose to use a comma instead indeed you may run into problems om systems that use the EU based numbers.
 
be sure to always specify a culture when using the ToString(..) function
e.g. ps[1].ToString(CultureInfo.InvariantCulture). this will prevent problems with different cultures.
 
cheers,
Herre

GeneralRe: Replaceing SEMICOLON for COMMAmemberBig Jim30-Jun-12 0:26 
Very interesting as the NZ locale uses comma as the seperator for functions for me... Smile | :)
 
Either way... still nice work and thanks for the locale tip! Smile | :)
Questionpow doesn't workmemberMember 849921318-Dec-11 20:34 
>pow(1,2)
Unexpected token '' found. Expected BRACKETCLOSE
AnswerRe: pow doesn't workmemberHerre Kuijpers18-Dec-11 21:49 
try pow(1;2)
Herre

GeneralRe: pow doesn't workmemberMember 849921319-Dec-11 2:54 
But it is so exotic to use ";" here. Can i replace it by "," to get usual behavour of "pow" (for "pow" recognition in cpp-style, for example)?
QuestionProgramatic functions [modified]memberderek999917-Oct-11 5:31 
Is it possible to use functions programatically? For example,
     string expr = "f(x) = sin(x)"; // define the expression as a string
 
and then get all of the values by feeding different values of x into the expression:
 
     // create the Expression object providing the string
     Expression exp = new Expression(expr);
 
     for (float x=0.0; i<6.5; i+=0.1)
     {
          object val = exp.Eval(x);
          Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}", val));
     }
 
Apologies if it already does this and I've missed something!
 
EDIT: I worked out how to do it from your test code. Thanks for a great article!

modified 18-Oct-11 6:49am.

Questionwhen will be release next version?membersunriseyuen24-Sep-11 4:09 
when will be release next version?
GeneralMy vote of 5mvpMd. Marufuzzaman11-Sep-11 8:08 
Nice
QuestionMS Scripting Controls?memberaikimark22-Aug-11 11:52 
Why not use the Microsoft Scripting Control?
http://msdn.microsoft.com/en-us/library/aa227413(v=VS.60).aspx[^]
 
or, staying in the .Net arena, the ScriptControl class:
http://msdn.microsoft.com/en-us/library/system.web.ui.scriptcontrol.aspx[^]
AnswerRe: MS Scripting Controls?memberHerre Kuijpers22-Aug-11 21:57 
Note, as stated at the beginning of the article, I did not write this tool to compete with other evaluation engines or products.
 
MS Scripting control would be a good choice if it fits your needs.
Of course MS scripting control is closed source... so you are confined to the MS way of scripting..
A concern is that MS scripting control may give a user/prgrammar more power/access than you might want to give (e.g. allow direct access to harddrive or create activeX objects).
 
cheers
Herre

GeneralRe: other evaluation engines or productsmemberaikimark23-Aug-11 1:59 
@Herre
 
I thought your @TinyExe context was inadequate. When you wrote:
 
Even though there are already a number of expression evaluators around on codeproject and beyond, this particular project is meant mainly to demonstrate the possbilityies of @TinyPG.
 
The casual reader might not realize that the vast .Net framework included the ScriptControl class. I think that omission diminishes this article and misses a 'teaching moment'.
 
Your security concern
I realize that the user might do things in the script environment that you don't intend, but I don't see the potential harm. A user can't do any more than their login credentials and permission allow. If your application has elevated its privileges, I would certainly want to prevent a user from doing any scripting.
 
If you wanted to show the power of @TinyPG, you might use it to examine an entire script or script statement that the application user wants to execute and make sure that it doesn't contain any suspect code/calls (if lowering permissions wasn't practical). It seems to me that would show the power of @TinyPG without recreating an expression evaluator functionality that already exists in the .Net framework.
 
Your Microsoft scripting restriction concern
If you want to create your own scripting language, I'm not going to argue with you. However, you don't state that premise in your article introduction. A recent CodeProject article implements a LUA interpreter:
[^]
 
You could have shown how @TinyPG would make the code in that article simpler. You could have chosen a different language that hasn't already been (script) implemented at CodeProject.
 
You might have justified writing your evaluator by implementing something that isn't readily available to your users, such as special functions that aren't part of the base (scripted) language.
 
You might have chosen some other application that allows your @TinyPG to shine.



Neither my original comment nor this one is an attack on your articles or the effort you put into either of these two programs. I just think that the reader could have been better served if you had used a different application to show the benefits of @TinyPG, or if you had informed the (casual) reader that a scripting class was part of the .Net framework. There was no need to use any code from CodeProject, including @TinyExe, any other web site, or use a commercial product in order to implement scripting in a .Net application.
 
The two reasons you stated in your response to my original comment might have been included in your article as a reason to not use the ScriptControl class, but you didn't address these in your article. So I thought this was a glowing omission worth a comment.
GeneralMy vote of 5membersunriseyuen20-Aug-11 13:34 
good
Questioncode blockmemberSunrise Yuen20-Aug-11 0:48 
great
can use code block ?
for example
 

if (Expression)
{
.....
}else if (Expression)
{
....
}else
{
....
{
QuestionRe: code blockmemberHerre Kuijpers20-Aug-11 1:25 
ehm.. i'm afraid I don't understand the question...
what are you trying to achieve?
Herre

AnswerRe: code blockmembersunriseyuen20-Aug-11 13:43 
 
if (Overtime<10)
{
 
   Overtime_pay=overtime*20;
   .....
}else if (Overtime>=10 && Overtime<=30)
{
 
   Overtime_pay=overtime*15;
   .....
}else
{
  
   Overtime_pay=overtime*12;
   .....
}
 

GeneralRe: code blockmemberHerre Kuijpers20-Aug-11 22:14 
clearly this isn't supported right now.
Yes, codeblocks, if/else, while, for loop, etc could be supported
 
however allowing statements and statementblocks will increase the complexity of the grammar and semantics substantially and certainly isn't easy to do (e.g. dangling else problem).
it's beyond the scope of this article.
Herre

GeneralRe: code blockmembersunriseyuen21-Aug-11 4:02 
no need too complexity
just need if ,elseif,else will be a good rule engine.
GeneralRe: code blockmemberHerre Kuijpers21-Aug-11 5:38 
how about:
Overtime_pay := (overtime < 10) ? overtime*20 : ((overtime >= 10 && overtime <= 30) ? overtime*15 : overtime*12)
Herre

GeneralRe: code blockmembersunriseyuen21-Aug-11 13:27 
1,Readability is not good
2,maybe
 
 
if (Overtime<10)
{
 
   Overtime_pay=overtime*20;
   call function1;
   call function2;
   ...
 

}else if (Overtime>=10 && Overtime<=30)
{
 
   Overtime_pay=overtime*15;
   call function1;
   call function2;
   ...
}else
{
  
   Overtime_pay=overtime*12;
   call function1;
   call function2;
   ...
}

QuestionGood Job My Five ... remark on precedencememberTony Jenniges18-Aug-11 16:15 
Very good job.
 
I've been working on my own language ... timely article. It's MATLAB like with script file and script functions and matrix math ... all very similar to MATLAB.
 
I was struggling today with precedence. That is choosing the right precedence in regards to unary '-' and '^', '.^' (matrix element power) operators. I was rewriting it (a minor change to do) to match MATLAB's and Octave's:
 
In MATLAB and Octave: -2^2 = -4
 
Google or Bing give the same answer: -4
 
Your precedence (and mine originally, until today) -2^2 = 4 is more intuitive.
 
Now test 2^2^2^2 in google or bing and the answer is 65,536 (256 in MATLAB or Octave).
 
Regards,
 
Tony
AnswerRe: Good Job My Five ... remark on precedencememberHerre Kuijpers18-Aug-11 21:35 
yes, it seems precedence is a topic that is still under discussion.
As stated in this article I took Excel as lead regarding precedence, using the same rules.
 
so, also in excel we have 2^2^2^2 = 256 (evaluation from left to right)
and also in excel we have -2^2 = 4 (unary operator takes precedence over power).
 
but of course from a strict mathematical perspective, only MATLAB is correct (and google of course Wink | ;) ).
Herre

QuestionMy vote of 5mvpMarcelo Ricardo de Oliveira18-Aug-11 3:15 
Hi Herre, this is an excellent post, thanks for sharing it Thumbs Up | :thumbsup:
 
cheers,
marcelo
There's no free lunch. Let's wait for the dinner.
 
Take a look at Silverlight Menu4U here in The Code Project.

Buglocalization issue fixedmemberHerre Kuijpers18-Aug-11 1:24 
It turned out there was a bug converting and parsing decimal numbers. Depending on local settings regarding the decimal separator this was done incorrectly.
This is now fixed in this update (v1.0.1)
Herre

GeneralCool I saymvpSacha Barber17-Aug-11 21:30 
5 from me
Sacha Barber
  • Microsoft Visual C# MVP 2008-2011
  • Codeproject MVP 2008-2011
Open Source Projects
Cinch SL/WPF MVVM

Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralGood stuffmemberEduard Keilholz17-Aug-11 21:16 
Ga hem zeker een keer testen, zie er veelbelovend uit! +5
.: I love it when a plan comes together :.
http://www.zonderpunt.nl

GeneralMy vote of 5memberSkif17-Aug-11 7:46 
Way to go!
GeneralMy vote of 5membermaq_rohit17-Aug-11 6:09 
Outstanding
GeneralMy vote of 5memberFilip D'haene17-Aug-11 6:02 
Excellent article and code!
 
Thanks for sharing. Smile | :)
GeneralHigh 5 [modified]memberBassam Abdul-Baki17-Aug-11 2:01 
I would suggest adding a help function to list all the available functions.
 
Also, increase the accuracy (significant digits) when you get the chance.
Web - BM - RSS - Math - LinkedIn
modified on Thursday, August 18, 2011 10:23 AM

AnswerRe: High 5memberHerre Kuijpers17-Aug-11 3:09 
Hi,
good points, actually, Help() is already built in
higher significance? you mean use decimals?
 
regards,
Herre

GeneralRe: High 5 [modified]memberBassam Abdul-Baki17-Aug-11 3:25 
Good to know. It didn't occur to me to try () after help. Your list of functions in the article has help, not help(), listed. I would recommend a tabular list of the functions with a small description and/or example or group them by type.
 
As for significance, I just meant more decimals and higher calculations. Factorial(51) gives a stack overflow.
 
Edit: In retrospect, all those functions require () so help() should have been the obvious answer. D'Oh! | :doh: Blush | :O
Web - BM - RSS - Math - LinkedIn
modified on Wednesday, August 17, 2011 10:41 AM

AnswerRe: High 5mvpNishant Sivakumar17-Aug-11 10:00 
So why is this a question, Bassam? Poke tongue | ;-P
Regards,
Nish
My technology blog: voidnish.wordpress.com

GeneralRe: High 5memberBassam Abdul-Baki18-Aug-11 4:23 
Huh! I definitely didn't change it (intentionally). Smile | :)

GeneralMy vote of 5memberGPUToaster17-Aug-11 1:47 
I would say excellent.
 
It would also be great if @TinyPG could do matrix operations, especially Euler!
and support big matrices, like 128 * 128!!! This would be very time consuming of-course on a CPU. CUDA/OpenCL would do the magic for big matrix operations. In short, this tool can be extended to any levels.
 
Regards.
GeneralRe: My vote of 5memberHerre Kuijpers17-Aug-11 3:13 
supporting vectors, matrices and complex numbers could be a (big) next step indeed, but then you would basically be building another matlab.
so I feel it is beyond the scope of this utility (in this form anyway). Because then you would also require to load and save matrices, and maybe even the context. And allow to link to external modules at runtime.
 
but yes, the concept can be extended to any level.
Herre

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 18 Aug 2011
Article Copyright 2011 by Herre Kuijpers
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid