作者:兰花m123_680 | 来源:互联网 | 2023-10-17 19:30
自动控制软件绕不开ST (StructureText ) 语言。它是IEC61131-3 标准中唯一的一个高级语言。目前,大多数PLC 产品支持ST语言。在IEC61499 中,根据IEC61499的定义,功能块的内部算法可以使用若干语言来描述,虽然可以是C,或者java 这样的通用高级语言,但是为了符合OT 工程的使用习惯,几个主要的IEC61499 开发工具也都以STL语言作为功能块内部算法的语言,在著名的IEC61499 开源项目4diac 中,除了ST 以外,还可以采用lua 脚本语言。不过对于OT 工程师而言,大概也不会使用lua 这样的语言。
另一方面,在IEC61499 或IEC61131 的运行时中,通常是使用C++,或者java 这样的通用程序设计语言编写的。在这样的运行时中运行ST 程序的方式无非是两种方式。第一种方式是将ST 翻译成为一种中间语言,由运行时解释执行。第二种方式是将ST转换成C++ 。与运行时源码一起编译。4diac 采取的是后一种方法。
ST 语言是一种类似PASCAL 的语言,将它转换成为C++ 代码并非易事。传统的方式与编译器没有什么两样,一般采取两趟编译,第一趟词法分析,第二趟语法分析。只是产生的目标代码是C++罢了。这样的程序过于复杂。将它们融入自己的开发环境,工作量也不小。本博文讨论基于xtext 的方式,实现ST 转换成C++ 的技术方案。
ST 程序实例
ST 编写的程序长成这个样子:
PROGRAM stexampleVARx : BOOL;END_VARx := TRUE;REPEATx := FALSE;UNTIL x := FALSE;END_REPEAT;
END_PROGRAM;
可以看出,ST与pascal有几分神似,也有很大的差别。所以如果将pascal 2 C 的程序修改成为ST to C++ ,改动也不小。而改动一个编译器并不是容易的事情。
xtext 与DSL 语言
作者一直在寻找实现ST 语言到C++ 转换的其它技术路线。万般无奈之时,硬着头皮研究了4diac IDE 的源代码。结果发现4diac中,它采取了Eclipse xtext 项目的技术。于是开始关注xtext
官网:https://www.eclipse.org/Xtext/
按照xtext官网的说法,Xtext 是开发程序设计语言和领域特定语言(DSL:domain-specific languages)的架构。于是又引入了一个术语DSL。这才发现,Xtext和DSL 是语言工程方面的一个重要的工具和概念,网络上有许多信息,而且有一本完整的书来介绍-《Implementing Domain-Specific Languages with Xtext and Xtend - Second Edition》。本博文没有办法全面地介绍Xtext和DSL 。只是提一下基本概念。在后续的博文中我会继续介绍这方面的内容(如果有人点赞的话)。
DSL语言
网络上将DSL 语言翻译成为领域特定语言,这是一种面向专有领域的小型语言,例如SQL 语言就是一种DSL,它是数据库查询的专有语言。其实DSL 是相对于通用程序设计语言(GPL) 而言的。比如Java。C++,PASCAL 等等。IEC61131-3 中的ST 是工业控制领域的专用语言。DSL 的另一个特点当然是它们普遍都比较小。
定义(Wikipedia):DSL 是特定领域的专用计算机语言。
这种定义完全是相对而言的,ST相对于java ,ST是一种DSL 语言,而java 相对于 英语,java 是一种DSL 语言。所以没有严格之分。
那么,为什么要DSL呢?它们主要的用途是什么呢?
DSL 的特点:
- 更多的表达,更少的冗余
这意味着更高的效率。
- 更好的学习曲线
- 有助于和领域专家交流
- 能自成文档(self-documenting)
- 领域特定验证
软件开发大师Martin Flowler 指出:任何一个傻子都能够写成计算机能懂的代码。好的程序员能够编写人类能够读懂的代码。DSL 能够使代码更加容易让人理解。特别是让非计算机人士理解。这非常重要。D。Knuth 曾经指出:好的算法必需看上去令人信服( An algorithm must be see to believed)。计算机语言通常比较地复杂,使人们不能集中精力去关注算法本身。例如XML 是一种普遍使用的结构化文本描述语言。在PLCOpen 和IEC61499 中采用XML 来描述程序,功能块,设备,系统等各种模型。这相对于PLC 厂商私有的文档格式,是一大进步。但是XML 恐怕只适合计算机程序处理,仍然不适合人类阅读。例如:
James
Smith
50
John
Anderson
40
XML不愧为是结构性语言,XML 中太多<> 括起的tag 。使我们很难看出内容 。这也称为“信息噪声”太大。如果使用 ad-hoc DSL描述:
person {
name=James
surname=Smith
age=50
}
person employed {
name=John
surname=Anderson
age=40
}
显然它们要清晰多了。它是低噪声的,信息更能理解。进一步地,如果按如下方式描述,显然更加清晰。
James Smith (50)
John Anderson (40) employed
DSL的实现
对于最终用户而言,使用DSL 要比XML 代码容易多了,但是俗话说:“话越少,事越大“。开发DSL 的主要任何就是如何实现它。实现DSL 意味着能够阅读DSL 编写的文本,对它语法分析,处理它,和转换成为其它语言的代码。这个过程类似与编译器(compiler) ,涉及词法分析,语法分析和代码生成。具体的方式是采用一种语法描述语言来描述DSL语言的语法(这种语法描述语言其实也是DSL),然后通过语言工具(语法生成器(parser generators)或者编译器的编译器(compiler-compiler)来编译DSL 语言编写的代码。
Bison 和Flex 是非常著名的基于C语言的语法描述语言,Bison 用于语法规范,Flex 用于词法规范。Bison 是Yacc(Yet Another Compiler-compiler)的实现。在java 的世界,ANTLR 非常出名。github 有一个开源项目:https://github.com/nucleron/matiec。不过这个编译器需要4 个stage。看上去比较复杂。
实现DSL 的另一种方法是基于eclipse 的Xtext项目。
进入Xtext
Xtext 是Eclipse 用于实现程序设计语言和DSL 的软件架构。它包含了一个完整的语言基础设施,从语法分析开始,代码生成或者解释,直到完整的EclipseIDE集成,实现一个DSL语言非常快。。Xtext 最惊喜的事情是实现DSL 语言,只需要一个语法规范就可以了。Xtext 的语法规范类似于ANTLR。
安装Eclipse Xtext
安装Eclips 的方法是首先从Eclipse 官网下载一个eclipse-install ,然后安装一个Eclipse Modling Tools。在Eclipse Modling 下,安装Xtext 插件。就可以使用了。如果你点赞,我会在后面的博文中介绍安装过程的细节。
使用Xtext 实现ST 语言
前面提到,使用Xtext 实现DSL 的需要是编写语言的规范。如果我们要实现ST 语言的编译,首先需要有一个xtex格式的ST语言的规范。他们在4diac IDE 的源代码中可以找到。文件比较长,这里就不列出来了。摘录一些片段。
StructuredTextAlgorithm: {StructuredTextAlgorithm}(&#39;VAR&#39;((localVariables += Var_Decl_Init) &#39;;&#39;)*&#39;END_VAR&#39;)?statements=Stmt_List
;Var_Decl_Init returns libraryElement::VarDeclaration:Var_Decl_Local
;Var_Decl_Local returns libraryElement::LocalVariable:{LocalVariable} (constant ?= &#39;CONSTANT&#39;)? name=ID (located?=&#39;AT&#39; location=Variable)? &#39;:&#39;( array?=&#39;ARRAY&#39; &#39;[&#39; arrayStart=Array_Size &#39;..&#39; arrayStop=Array_Size &#39;]&#39; &#39;OF&#39;)?type=[datatype::DataType|Type_Name]( initalized?=&#39;:=&#39; initialValue=Constant)?
;/************************************************************************statement
************************************************************************/
Stmt_List returns StatementList: {StatementList}((statements += Stmt)? &#39;;&#39;)*
;Stmt returns Statement:Assign_Stmt |Subprog_Ctrl_Stmt |Selection_Stmt |Iteration_Stmt
;Assign_Stmt returns AssignmentStatement:variable=Variable &#39;:=&#39;expression=Expression
;Subprog_Ctrl_Stmt returns Statement:Func_Call |//Invocation |{SuperStatement} &#39;SUPER&#39; &#39;(&#39; &#39;)&#39; |{ReturnStatement} &#39;RETURN&#39;
;Selection_Stmt returns Statement:IF_Stmt | Case_Stmt
;IF_Stmt returns IfStatement:&#39;IF&#39; expression=Expression &#39;THEN&#39;statments=Stmt_List(elseif += ELSIF_Clause)*(else=ELSE_Clause)?&#39;END_IF&#39;
;ELSIF_Clause returns ElseIfClause:&#39;ELSIF&#39; expression=Expression &#39;THEN&#39;statements=Stmt_List
;ELSE_Clause returns ElseClause:&#39;ELSE&#39;statements=Stmt_List
;Case_Stmt returns CaseStatement:&#39;CASE&#39; expression=Expression &#39;OF&#39;(case += Case_Selection)+(else=ELSE_Clause)?&#39;END_CASE&#39;
;Case_Selection returns CaseClause:case += Constant (&#39;,&#39; case += Constant)* &#39;:&#39; //only allow explicit constants herestatements=Stmt_List
;Iteration_Stmt returns Statement:For_Stmt |While_Stmt |Repeat_Stmt |{ExitStatement} &#39;EXIT&#39; |{ContinueStatement} &#39;CONTINUE&#39;
;For_Stmt returns ForStatement:&#39;FOR&#39; variable=Variable_Primary &#39;:=&#39; from=Expression &#39;TO&#39; to=Expression (&#39;BY&#39; by=Expression)? &#39;DO&#39;statements=Stmt_List&#39;END_FOR&#39;
;While_Stmt returns WhileStatement:&#39;WHILE&#39; expression=Expression &#39;DO&#39;statements=Stmt_List&#39;END_WHILE&#39;
;Repeat_Stmt returns RepeatStatement:&#39;REPEAT&#39;statements=Stmt_List&#39;UNTIL&#39; expression=Expression&#39;END_REPEAT&#39;
;
完整的xtext 文件 443 行。
语言服务器协议(Language Server Protocol)
Eclipes xtext 项目提供了DSL的所有工具,包括了编辑时的高亮,语法检查,编译,代码生成,验证等等。全部是在Eclipse IDE 下完成的。但是ST语言的编译需要在IEC61131-3 或IEC61499 的IEC 环境下实现/对于4diac 而言,它同样是使用Eclipse IDE来实现的,所以,Xtext 成为了4diac IDE的插件。但是,如果你的IEC61131-3/IEC61499 IDE 采用其他语言和架构来实现的(比如C++,或者Javascript/nodeJS),那么如何将Xtext嵌入到你的IDE 中去呢?这要感谢微软公司开源的语言服务器协议。协议定义了在编辑器或IDE与语言服务器之间使用的协议。比如微软的VS Code 与编译器之间的协议。使用语言服务器协议能够实现云端语言开发环境。
到了Xtext 采用了eclipse 的lsp4j。实际上,xtext 指出web 方式的编辑。
具体实现时,可以将ST 编译做成一个服务器,甚至可以放置在docker 中。你的IEC61131-3/IEC61499 IDE 通过lsp4j 协议与ST编译服务器交互完成ST语言的转换。既可以本地访问,也可以远程访问。可以实现云端PLC。
小结和今后的工作
本博客介绍了采用Eclipse Xtext 工具实现IEC61131-3/IEC61499 的ST语言的编译方案,并且大致介绍了Xtext和语言服务器协议两个重要的技术。未来,我们会实现一个完整的,独立的ST语言服务器。这里特别要指出的是,Xtext 对于工业自动化领域的开放模型,模型驱动自动化(model driven automation) 同样非常重要,Xtext是值得研究的课题。