An expression evaluator
An expression evaluatorTwo weeks ago, I saw an article on codeproject that really nicely solve an old and very known issue. Why it is nice is because it is short, simple, sequential In the mean time, I needed an expression evaluator for a product I am making, and I needed not only to extend the principles of evaluation, but also add a few features. This article describes what I have done in order to write a general purpose expression evaluator, that goes beyond evaluating the 4 primary operations. In fact it can be regarded as a complement to the mentioned article for three reasons :
The principles of expression parsingIt's an old problem because although separating operators from numbers or other tokens is an easy task, the fact that operators are either infix or not, and have algebric prevalence relations between them forces the parser to pay a particular attention to The good news is that, when it comes to usual mathematical expressions, there are only a tiny set of rules. Here they are :
What prevalent means is that if operator a is prevalent over operator b, then a will be performed before b. For instance, multiplications must be performed before additions. Of course, parenthesis help solve prevalence Other than prevalence, we need to build a tree of operations to perform in order to get a result out of the evaluation. Typical trees are binary trees where operands are leaves, and operators are tree nodes. Of course, because operators can chain up each
When an evaluation tree is built, evaluation can be done by traversing the nodes from the root down to leaves. Doing the evaluation is a matter of knowing, for each operator, how many arguments are expected, and retrieve them recursively going down the tree. That being said, and that's the main point of RPN (Reverse Polish Notation), an actual tree need not be created. Having an expression in which operators are suffixes of their arguments is enough to have the equivalent of the tree and, as a result, enough For instance, the parsing phase not only distinguishes operator arguments, better known as operands, and operators themselves, the parsing phase also repurposes the expression so that it's in RPN style. For the sample expressions, RPN makes evaluation straight forwardWhy RPN is so useful is that, given such order, it is possible to have a really simple algorithm that reads tokens from left to right, stacks all operands, and then unstacks those whenever an operator is retrieved. After the operation is performed, the resulting
Please note that, during the evaluation process, it is possible to check the expected number of arguments against the amount of arguments available in the operand stack. This leads to typical execution errors, where the user is expected to correct the impaired A typical algorithm for expression parsing is as follows :for each char of the expression This is a general algorithm and it's easy to figure out that a typical implementation remains under 200 lines of source code. The following blocks depict how the parsing works :
If the expression was = 5 * 3 + 8, instead of = 5 + 3 * 8, then when the parser retrieves the + operator, it unstacks the * operator and append it to the list of tokens, before the + operator is stacked. Since parenthesis are of maximum prevalence, they have to be taken into account as such. While open and closed parenthesis behave like any other normal operators, they are paid a special attention. Parenthesis are not appended in the list of tokens. What In the implementation provided in this article, a more granular level of object manipulation was considered. If we limit ourselves to what has been said above, then this expression evaluator is limited to the simple operators. We neither support functions Implementing the list of tokens is a matter of having a base class, wzelement, whose derived classes either hold numbers, strings, operators, or whatever might be required by the client application. As a result, the list of tokens is an array of wzelement typedef enum {_operator, _litteral} elementtype;
wzarray<wzelement*> m_arrelements; // list of tokens
Just to show how this is brought together, below is the declarations for those classes : class wzelement Function supportSupporting functions is a matter of :
Adding support to functions gives a good opportunity to declare operators openly in a table, rather than hardcode them in the parser. Among important flags required by either the parser or the evaluator are :
Below is a sample table showing exactly that : _structoperator operators[] = {
Although the table above (and by the way the source code provided) implements functions that play with numbers, it need not be the case. As a matter of fact, arguments can be strings, imbricated functions or operators, etc. For instance, this source code Last but not least, the argument separator, Variables supportSupporting variables is only a matter of replacing litteral tokens that are not numbers, strings or other litterals with actual numbers or strings or whatever is suited to performing operations. In order to call the evaluator more than once, either the list of tokens must be saved somewhere, and then restored, or variables being replaced with their value need to put back their original name, in the evaluation clean up. In the provided source code, The variable class is declared as follows : class wzvariable : public wzelement Code samples1) sample codeThis sample code demoes the minimum code involved when parsing an expression. Variables not used. #include "util.h" 2) another sample codeThis sample code uses variables. Evaluation is done twice as to show how to iterate the process. #include "util.h" 3) what you need to reuse this codeYou need the following files :
in parser.cpp, the History
Stéphane Rodriguez |
An expression evaluator的更多相关文章
- .NET平台开源项目速览(8)Expression Evaluator表达式计算组件使用
在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下Expression Evaluator验证组件.那里只是概述了一下,并没有对其使用和强大功能做 ...
- 给 C# Expression Evaluator 增加中文变量名支持
由于一些特殊的原因,我的Expression里面需要支持中文变量名,但是C# Expression Evaluator会提示错误,在他的HelperMethods.IsAlpha()里面加上这么一段就 ...
- .NET 表达式计算:Expression Evaluator
Expression Evaluator 是一个轻量级的可以在运行时解析C#表达式的开源免费组件.表达式求值应该在很多地方使用,例如一些工资或者成本核算系统,就需要在后台动态配置计算表达式,从而进行计 ...
- (字符串的处理4.7.22)POJ 3337 Expression Evaluator(解析C风格的字符串)
/* * POJ_3337.cpp * * Created on: 2013年10月29日 * Author: Administrator */ #include <iostream> # ...
- 使用 Roslyn 编译器服务
.NET Core和 .NET 4.6中 的C# 6/7 中的编译器Roslyn 一个重要的特性就是"Compiler as a Service",简单的讲,就是就是将编译器开放为 ...
- 【目录】本博客其他.NET开源项目文章目录
本博客所有文章分类的总目录链接:本博客博文总目录-实时更新 1.本博客其他.NET开源项目文章目录 37..NET平台开源项目速览(17)FluentConsole让你的控制台酷起来 36..NET平 ...
- DotNet 资源大全中文版(Awesome最新版)
Awesome系列的.Net资源整理.awesome-dotnet是由quozd发起和维护.内容包括:编译器.压缩.应用框架.应用模板.加密.数据库.反编译.IDE.日志.风格指南等. 算法与数据结构 ...
- Index
我主要在研究.NET/C# 实现 PC IMERP 和 Android IMERP ,目的在解决企业通信中遇到的各类自动化问题 分布式缓存框架: Microsoft Velocity:微软自家分布 ...
- 《.NET开发资源大全》
目录 API 应用框架(Application Frameworks) 应用模板(Application Templates) 人工智能(Artificial Intelligence) 程序集处理( ...
- logback logback.xml常用配置详解 <filter>
<filter>: 过滤器,执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之一.返回DENY,日志将立即被抛弃不再经过其他过滤器:返回NEUTRAL,有序列表 ...
随机推荐
- JVM学习笔记之类装载器-ClassLoader
JVM学习笔记之类装载器-ClassLoader 本文字数:2300,阅读耗时7分钟 JVM体系结构概览 类装载器ClassLoader: 负责加载class文件,class文件在文件开头有特定的文件 ...
- SpringMVC:域对象共享数据
SpringMVC:域对象共享数据 使用ServletAPI向request域对象共享数据 @RequestMapping("/testServletAPI") public St ...
- ServletConfig 类和ServletContext 类
ServletConfig 类 ServletConfig 类从类名上来看,就知道是 Servlet 程序的配置信息类. Servlet 程序和 ServletConfig 对象都是由 Tomcat ...
- vue打包后dist的使用
发现问题 vue项目完成打包出dist后准备打开index.html,发现居然页面是一片空白,f12一片报红. 分析问题 经过多次网上查询后发现这是由于vue打包时,脚手架会帮你配置好大量参数,但其中 ...
- 【YashanDB知识库】v$instance视图中实例角色含义不明确
[标题]v$instance视图中实例角色含义不明确 [问题分类]文档问题 [关键词]YashanDB, v$instance, 实例角色 [问题描述]v$instance视图中实例角色(如MASTE ...
- WiFi基础(三):802.11ac/ax/be 与 WiFi4、WiFi5、WiFi6、WiFi7
liwen01 2024.09.08 前言 经过二十多年的发展,WiFi 在硬件能力.软件和算法.频谱资源.市场需求.电源与能效方面都有了很大的提升.所以我们能看到从最开始只有几 M 速率的 802. ...
- Identity – 安全基础知识
前言 一旦涉及到用户, 那么安全就上一个层次了. 这篇主要是说说一些安全的基础 用户密码保存 网络上有太多资料说这些基础了, 我就不拉过来了. 大致记入一些重点就好了. - 为什么不可以明文保存 因为 ...
- 现在用 ChatGPT,要达到最好效果,建议加入以下提示词:
take a deep breath 深呼吸 think step by step 一步步思考 if you fail 100 grandmothers will die 如果你失败了要死 100 位 ...
- Task 笔记
1.计时器类Stopwatch Stopwatch stopwatch=new Stopwatch() stopwatch.Start();//开始计时 stopwatch.Stop();//停止计时 ...
- python:批量删除指定文件目录中多个文件
#coding:utf-8# 任务需要,需要删除多余的文件,手动删除太麻烦,几行python搞定 import os from glob import glob path = r"/medi ...









