原文地址:http://www.cnblogs.com/Rainday/p/cmurphi_prime_3.html
1. 常量,类型和变量的定义
定义具有如下的语法:
<decl> ::= const { <constdecl> ; } | type { <typedecl> ; } | var { <vardecl> ; }
常量定义:
<constdecl> ::= <ID> : <expr>
常量定义中的<expr>必须有一个在编译的时候可以确定的值。
类型定义:
<typedecl> ::= <ID> : <typeExpr>
<typeExpr> ::= <ID> -- a previously defined type.
<typeExpr> ::= <expr> .. <expr> -- Integer subrange.
<typeExpr> ::= enum \{ <ID> {, <ID> } \} -- enumeration.
<typeExpr> ::= record { <vardecl> } end
<typeExpr> ::= array \[ <typeExpr> \] of <typeExpr>
注意,特殊的枚举类型"boolean"是预定义的,与其相关的常量"true"和"false"也是,他们均为Murphi的保留字。整型类型不是预定义的,因为使用一般的整数而不将其限制为子区间将会导致存储的急剧消耗。
简单类型包括布尔类型,枚举类型,整数的有限子区间。
复合类型是复合类型或者简单类型的数组,以及复合类型或者简单类型的记录。
数组的索引类型必须是简单类型。
变量定义:
<vardecl> ::= <ID> { , <ID> } : <typeExpr>
下边的例子演示了定义的代码:
const I: 2; J: 31415 * I / 9; -- J will be 6981 type val_t: 0..99; -- simple types. ind_t: 1..i; enum_t: enum { x, y, z }; b: boolean; r_t: record f:0..1; g: 0..2; end; -- Record. rr_t: record r: r_t; s: r_t; end; -- Record of record. a_t: array [ ind_t ] of 19..29; -- 1-dimensional array. aa_t: array [ ind_t ] of a_t; -- 2-dimensional array. ar_t: array [ 1..2 ] of r_t; -- Array of record. ra_t: record a1: a_t; foo: ind_t; end; -- Record with array. ae_t: array [ enum_t ] of enum_t; -- Array with enum index and range. aae_t: array [ ind_t ] of ae_t; -- 2-dim array, 2nd index is enum. re_t: record f: enum_t; end; -- Record of enum. var val : val_t; arr : ae_t; rec : record foo: ind_t; bar: boolean; end;
2. 过程和函数的定义
所有的过程和函数都必须在程序的最外层定义,使用下边的语法:
<procdecl> ::= <procedure> | <function> <procedure> ::= procedure <ID> \( [ <formal> { ; <formal> } ] \) ; [ { <decl> } begin ] [ <stmts> ] end; <function> ::= function <ID> \( [ <formal> { ; <formal> } ] \) : <typeExpr>; [ { <decl> } begin ] [ <stmts> ] end;
与Pascal的过程不同,没有参数的过程和函数仍然需要一对包含空参数的括号。
函数必须使用return语句在函数内的某处返回一个值。函数可以有副作用;然后,对使用有副作用的函数,会有很多限制。
注:函数的副作用是调用函数的时候可以对函数之外的东西产生影响,如修改全局变量的值,使用输出语句(输出到屏幕或者写文件等等)等等。
过程或者函数的参数列表的形式为:
<formal> ::= [var] <ID> { , <ID> } : <typeExpr>
使用"var"定义的形参是通过引用传值的;不使用"var"定义的形参也是通过引用传值,但是在过程或者函数中不允许改变形参的值。
形参和局部变量的定义会覆盖他们作用域范围之外的变量的定义。
下边的例子展示了过程和函数的定义:
procedure Swap(var i, j: val_t); var temp: val_t; begin temp := i; i := j; j := temp; end; function plustwo(input: val_t): val_t; const two : 2; begin return (input + two); end;
初看使用BNF表示的语法规则,总觉得不是很适应,不过有例子的话,就不一样了。
传送门: