初探PLC 的ST 语言转换成C++ 的方法

28 篇文章 38 订阅

自动控制软件绕不开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 stexample
  VAR
    x : BOOL;
  END_VAR
  x := TRUE;
  REPEAT
    x := 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 的特点:

  1. 更多的表达,更少的冗余

                 这意味着更高的效率。

  1. 更好的学习曲线
  2. 有助于和领域专家交流
  3. 能自成文档(self-documenting)
  4. 领域特定验证

   软件开发大师Martin Flowler 指出:任何一个傻子都能够写成计算机能懂的代码。好的程序员能够编写人类能够读懂的代码。DSL 能够使代码更加容易让人理解。特别是让非计算机人士理解。这非常重要。D。Knuth 曾经指出:好的算法必需看上去令人信服( An algorithm must be see to believed)。计算机语言通常比较地复杂,使人们不能集中精力去关注算法本身。例如XML 是一种普遍使用的结构化文本描述语言。在PLCOpen 和IEC61499 中采用XML 来描述程序,功能块,设备,系统等各种模型。这相对于PLC 厂商私有的文档格式,是一大进步。但是XML 恐怕只适合计算机程序处理,仍然不适合人类阅读。例如:

<people>
<person>
<name>James</name>
<surname>Smith</surname>
<age>50</age>
</person>
<person employed="true">
<name>John</name>
<surname>Anderson</surname>
<age>40</age>
</person>
</people>

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}
	(
		'VAR'
			((localVariables += Var_Decl_Init) ';')*
		'END_VAR'
	)?
	statements=Stmt_List
;

Var_Decl_Init returns libraryElement::VarDeclaration:
	Var_Decl_Local
;

Var_Decl_Local returns libraryElement::LocalVariable:
	{LocalVariable} (constant ?= 'CONSTANT')? name=ID (located?='AT' location=Variable)? ':'
	( array?='ARRAY' '[' arrayStart=Array_Size '..' arrayStop=Array_Size ']' 'OF')?
	type=[datatype::DataType|Type_Name]
	( initalized?=':=' initialValue=Constant)?
;

/************************************************************************
								statement
************************************************************************/
Stmt_List returns StatementList: {StatementList}
	((statements += Stmt)? ';')*
;

Stmt returns Statement:
	Assign_Stmt |
	Subprog_Ctrl_Stmt |
	Selection_Stmt |
	Iteration_Stmt
;

Assign_Stmt returns AssignmentStatement:
	variable=Variable ':='
	expression=Expression
;

Subprog_Ctrl_Stmt returns Statement:
	Func_Call |
	//Invocation |
	{SuperStatement} 'SUPER' '(' ')' |
	{ReturnStatement} 'RETURN'
;

Selection_Stmt returns Statement:
	IF_Stmt | Case_Stmt
;

IF_Stmt returns IfStatement:
	'IF' expression=Expression 'THEN'
		statments=Stmt_List
		(elseif += ELSIF_Clause)*
		(else=ELSE_Clause)?
	'END_IF'
;

ELSIF_Clause returns ElseIfClause:
	'ELSIF' expression=Expression 'THEN'
		statements=Stmt_List
;

ELSE_Clause returns ElseClause:
	'ELSE'
		statements=Stmt_List
;

Case_Stmt returns CaseStatement:
	'CASE' expression=Expression 'OF'
		(case += Case_Selection)+
		(else=ELSE_Clause)?
	'END_CASE'
;

Case_Selection returns CaseClause:
	case += Constant (',' case += Constant)* ':' //only allow explicit constants here
		statements=Stmt_List
;

Iteration_Stmt returns Statement:
	For_Stmt |
	While_Stmt |
	Repeat_Stmt |
	{ExitStatement} 'EXIT' |
	{ContinueStatement} 'CONTINUE'
;

For_Stmt returns ForStatement:
	'FOR' variable=Variable_Primary ':=' from=Expression 'TO' to=Expression ('BY' by=Expression)? 'DO'
		statements=Stmt_List
	'END_FOR'
;

While_Stmt returns WhileStatement:
	'WHILE' expression=Expression 'DO'
		statements=Stmt_List
	'END_WHILE'
;

Repeat_Stmt returns RepeatStatement:
	'REPEAT'
		statements=Stmt_List
	'UNTIL' expression=Expression
	'END_REPEAT'
;

完整的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是值得研究的课题。

  • 16
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值