原文地址:http://www.cnblogs.com/Rainday/p/cmurphi_prime_5.html
下边是Murphi中语句的形式:
<stmts> ::= <stmt> {; [<stmt>] }
<stmt> ::= <assignment> /* assignment */
| <ifstmt> /* if statement */
| <switchstmt> /* switch statement */
| <forstmt> /* for statement */
| <whilestmt> /* while statement */
| <aliasstmt> /* alias statement */
| <proccall> /* procedure call */
| <clearstmt> /* clear statement */
| <errorstmt> /* error assertion */
| <assertstmt> /* assertion */
| <putstmt> /* output statement */
| <returnstmt> /* function return */
赋值语句:
<assignment> ::= <designator> := <expression>
被赋值的对象必须与后边的表达式的类型相兼容,且必须不是常量。
为变量赋超出其范围的值会引发运行时错误。
if语句:
<ifstmt> ::= if <expr> then [ <stmts> ] { elsif <expr> then [ <stmts> ] } [ else [ <stmts> ] ] endif
每个<expr>都必须是布尔类型的。
switch语句:
<switchstmt> ::= switch <expr> { case <expr> {, expr} : [ <stmts> ] } [ else [ <stmts> ] ] endswitch
每个"case"中的每个<expr>必须是与"switch"的<expr>的类型相兼容的常量。如果没有任何一个"case"能够匹配的话,"else"部分将会执行。
(之后有一句话看不明白:There is no fall through on cases.)
For语句:
<forstmt> ::= for <quantifier> do [stmts] endfor
<quantifier>在for语句,量词表达式和规则集(rulesets)中使用。
<quantifier> ::= <ID> : <typeExpr>
| <ID> := <expr> to <expr> [ by <expr> ]
第一种形式针对<typeExpr>(必须为简单类型)中的每一个值,从小到大执行for语句的循环体或者计算量词表达式的主体;第二种形式与Modula-2中的FOR语句相类似,两个表达式必须是整型的,并且后边的by表达式必须是一个常量表达式。
在for语句或者量词表达式中使用<quantifier>时,<ID>所声明的局部变量会覆盖其作用域之外的变量定义。在for的循环体中修改<quantifier>中变量的值是非法的。
While语句:
<whilestmt> ::= while <expr> do [stmts] end
无限循环是运行时错误。虽然由于状态的总数边界可以计算得到使得可以决定循环是否有限,无限循环实际上明显还会为验证器带来问题。目前,默认情况下,验证器会在1000次循环之后停下来并且给出一个错误消息。用户可以通过命令行参数改变这个限制。
Alias语句:
<aliasstmt> ::= alias <alias> { ; <alias> } do [ <stmts> ] end <alias> ::= <ID> : <expr>
Alias中定义的<ID>会覆盖外层同样的<ID>。
取决于<expr>是不是一个左值,Alias会有不同的表现。如果<expr>是一个左值,<ID>就会被定义为与这个左值相联系的表达式;如果<expr>不是一个左值,<ID>就会得到<expr>这个表达式所代表的值,并且<ID>在alias语句块中不可以被改变。
例子:
-- i = 2 beforehand; arr[2] = 1. alias foo : arr[i] -- foo gets identified with arr[2] bar : arr[i] + 1 -- bar gets identified with 2. do arr[i] := 3; -- now, foo = 3, but bar = 2. i := 1; -- foo is still bound to a[2]. foo := 4; -- arr[2] is now 4. bar = 2. bar := 2; -- Illegal. end
过程调用:
<proccall> ::= <ID> \( <expr> {, <expr> } \)
遵守过程的所有标准规则。常量形参(不带"var"的)可以传递任何类型兼容的实参;"var"定义的形参必须传递一个类型兼容的左值;"var"定义的子区间类型的形参必须传递相同子区间类型的左值。
Clear语句:
<clearstmt> ::= clear <designator>
这个语句可以将所有的左值重置为他们类型的最小值。枚举类型的最小值是其列表中的第一个值;布尔类型的最小值是false。
注意:Clear常用于将变量的不确定的值变为确定的值,否则,在验证过程中将会根据很多随机的值创建很多状态。不鼓励因为其他的目的而使用Clear语句。我们认为,使用"undefine"操作符来为保留的未定义的值来赋值会更加安全。
Error断言:
<errorstmt> ::= error <string>
Error语句的执行将会导致运行时错误。在验证器中,如果Error语句执行了,验证就会终止,特定的字符串会显示出来,如果要求的话,一条失败跟踪信息也会打印出来。
断言:
<assertstmt> ::= assert <expr> [ <string> ]
"assert <expr> <string>"与"if !<expr> then error <string> end"是完全等价的。
Output语句:
<putstmt> ::= put ( <expr> | <string> )
这条语句每次执行的时候都会打印出指示的值。这个语句的行为与C语言中的"printf"是一样的,所以在你每想要输出一个行的时候,小心地包含如下代码:
put "\n"
一般,在验证(有很多重复)中,这样做会导致打印大量的填充物。我们已经用它来调试,以及生成一个包含确定变量的所有可能值的文件(之后可能的处理是清除副本)。
(以上这一段的原文为:
Prints out the indicated value, each time the statement is executed. This is handed straight to printf, so be careful to include a
put "\n"
after each line you want to print.
Generally, this will cause a huge amount of stuff to be printed during verification (with much duplication). We have used it for debugging, and for generating a file of all of the possible values of certain variables (which is then processed to eliminate duplicates).)
函数返回:
<returnstmt> ::= return [ <expr> ]
离开当前的过程,函数,规则或者起始状态。如果是离开一个函数,则<expr>必须提供并且与函数的返回类型一致;否则,必须没有返回值。
这一部分的内容相当多,需要好好消化!!!
传送门: