张 宇,王 珂,刘乐云
(上海广播电视卫星地球站,上海 201114)
计算机编译原理在开发工具中是作为基础进行实现的,可在常见的应用场景下很少被采用。主要原因是有以下几点:一是,应用程序的实现主要是与用户接触,更多与自然语言以及自然行为有关,更偏向于模糊与概率,所以人工智能在这方向应用的比较多也更合适。但在与设备通讯时,对于参数的判定要求真实,不存在模棱两可的情况。因此,我们在开发这方面的程序时,会使用判定语句、条件语句和一些运算来计算出报警情况,在效率、安全和开发难度的综合考虑下,我们会在程序中固化这些策略。但在长期的使用中发现,因为涉及的参数比较多,如果出现判断策略的改变,这将导致较大的程序升级,升级就意味了测试与成本。为了提高维护效率以及避免这种情况的更新需求,通过对报警策略进行解释表达式的方式进行开发,变得非常有价值。用户只需要在程序里修改报警表达式,就可以满足所有的报警策略方面的软件升级。
在设备监控中,常见的参数报警策略有以下一项或多项的与或组合:
⊙ 大于参考值。
⊙ 小于参考值。
⊙ 等于参考值。
⊙ 不等于参考值。
⊙ 在范围内(包括范围)。
⊙ 在范围外(包括范围)。
⊙ 枚举参数值。
在设备监控中,常见的参数报警策略可能用到的数据类型:
⊙ 整形。
⊙ 浮点数。
⊙ 布尔数。
⊙ 字符串。
⊙ 时间。
⊙ ……
例如:当需要制定温湿度报警时,我们可能写入如下策略:
设定室内温度24℃为参考温度,当温度高于等于参考值2℃(26℃)时进行警告,当温度低于等于参考值2℃(22℃)时进行警告,当温度高于等于4℃(28℃)时报警,当温度低于等于4℃(20℃)时进行报警。
else Normal();//温度正常这样的表达式对于一般的程序员来说没有问题,但这些语句必须被写入程序,当参考值由24调整为25时,我们的程序可能需要做一些调整,将所有的上下限做相应的加1修改就可以了。但当这样的调整很频繁时,我们不得不修改程序的结构,将参考值、当前值、警告时范围、报警时范围都考虑在内,这样将来再需要调整这些参考值时,就不再需要修改程序,只需要修改相关的参数就可以了。不过当上下限范围发生变化或需要更多的报警级别时,修改相应的程序结构将变得非常复杂,更何况在设备监控中需要采集的数据类型种类众多,对于程序开发和后期维护是非常不利的。在这样的背景下,通过表达式编译方式的程序开发结构被提出。
通过对众多参数策略的罗列与比对,我们对报警策略表达式的抽象结构做了以下几点的总结:
⊙ 参考值的上下限范围,上下范围可能相同或不同,极限情况下范围为0。
⊙ 周期内的持续变化,可能是连续上升、下降,极端情况下可能是不变化。
⊙ 区分报警等级,也就是计算出数值,由数值对应报警的形式(颜色、声音和操作)。
表达式编译算法的目的:能够理解表达式的意图,全面真实的反应表达式结构,能对每一个范畴内的运算符进行运算,最终产生正确的结果,并将结果以数值形式展现出来。
首先,表达式是由数字、算符、数字分组符号(括号)、自由变量和约束变量等以能求得数值的有意义排列方法所得的组合。也就是说,表达式能够被一般人理解的可见算式。
如 :((@+2)<$)?l1 :l0 ;
表达式的含义为:当前值+2小于参考值时返回长整形1否则返回长整形0;表达式运算符的关键字如表1中定义。
表1
运算符优先级定义如表2。
表2
数据类型定义如表3。
表3
我们就以((@+2)<$)?1l:0l;为例对表达式的转换与计算做简单的算法介绍:
(1)以下每个步骤,逐一处理每个字符。
(2)首先创建一个根表达式R。
(3)当读到第1个左括号,创建表达式E0,将”(”写入左目,连接到根结构R的左目之下。
(4)读到第2个左括号,再创建表达式E1,将”(”写入左目,连接到表达式E0的左目之下。
(5)读到 @,因为是变量,再次创建树状表达式E2,将”@”写入左目,连接到E1左目之下。
(6)读到+,因为是运算符,将直接写入E2的操作符中。
(7)读到2,因为是常数,将直接写入E2的右目,E2表达式完成,回溯到E1。
(8)读到),表示挂号完整,等待后续。
(9)读到<,因为是运算符,将直接写入表达式E1的操作符中。
(10)读到$,将直接写入表达式E1右目,回溯到表达式E0。
(11)读到?,因为是运算符,直接写入操作符中。
(12)读到1l,表示输出数据类型为长整形,写入右目。
(13)读到,表示确定操作符为条件语句,等待第三目。
(14)读到0l,表示输出数据类型为长整形,写入第三目。
(15)读到;表示表达式结束,回溯到R。
(16)退出表达式构造。
产生的表达式树状结构如图1所示。
图1
对产生的树状结构进行计算:
(1)得到R。
(2)获取E0左目。
(3)获取E1左目。
(4)获取E2左目@与E2右目相加,得到结果@1回溯到E1。
(5)将@1与$做比对,获取结果TF,回溯到E0。
(6)如果TF=T,获取结果1,否则获取结果0,回溯到R。
(7)由R产生结果输出。
对于每一种输出的值,只要在数据库中对该参数做好相应的定义,如:字体显示颜色、报警的声音、操作行为等,就可以从展现角度视为不同的报警级别。如图2所示。
图2
修改程序构架的时候担心的运行效率问题并没有成为瓶颈,解释程序对((@+2)<$)?1l:0l;这样的表达式在普通PC上进行10亿次的运算消耗的时间小于1秒。表达式解释程序在应用场景中可满足日常的设备监控的需要,并已在多个项目中广泛使用。真正做到无需修改程序就可满足参数添加和不同种类的报警策略的修改与设定。
[1] (美)阿霍(Aho,A,V)等著.李建中等译.编译原理.北京:机械工业出版社.