EGL语言教程之二:表达式与操作符

原创 2012年03月28日 11:19:26

表达式与操作符

1  表达式与操作符

一个表达式是由一系列操作符、操作数和特殊字符组成,并在运行时由EGL进行求值运算。操作数可以是常量、标识符或者关键字。EGL可以对以下几种表达式进行运算:

1.        逻辑表达式,可以被赋值为TRUE 或者 FALSE;参见“逻辑表达式”。

2.        数字和文本表达式,可以分别被赋值为数字或字符;参见“表达式类型”。

3.        日期/时间表达式是特殊和复杂的表达式;参见“日期和时间表达式”。

EGL对表达式进行求值运算时会遵循一系列的优先级规则(参见“操作符和优先级规则”)并从左到右(对于具有相同优先级的操作符),但你可以使用括号来强制指定不同的优先级规则。内层括号里的子表达式要在外层括号里的子表达式之前计算,并且所有括号中的表达式要在整个表达式之前先计算。

和数值一样,表达式也有类型。类型是对表达式所能被赋的值的序列集。关于更多的表达式类型的内容,参见“表达式类型”。关于更多的类型相关的内容,参见“类型”和“原始数据类型”。

 

1.1 特殊字符

在EGL中, 当使用下列功能运算符时可以使用非字母数字字符组:

1.        操作符(参见“操作符和操作数”)

2.        分隔符(参见本章的“分隔符”部分)

3.        类型扩展字符(参见“类型扩展字符”)

 

分隔符

分隔符用来标记输入的开始和结束。EGL使用下列分隔符:

 

引号 “”

在EGL中引号通常用来标记文字字符串。

花括号 { }

花括号可以在下列情况中使用:

1.属性值赋值,例如:

Button Button{ text="Button", onClick ::= Button_onClick };

2.记录字段初始值的赋值,例如:

record CustomerRecord {customerNumber=0,customerBalance=0}
    customerNumber INT;
    customerBalance int;
end

3.初始化变量(通常是数组),例如:

myStringsInit string[] {"Hello", "Goodbye"};

方括号 [ ]

方括号可以在下列情况中使用:


1.表示数组元素的数量:

myBigInts bigint[];

2.列举数组的成员,例如:

myBigInts = [10, 40];

3.数组指针,例如:

myBigInts[2] = 5;

括号()

括号可以在下列情况中使用:

 

1.函数的参数和返回值,例如:

function testFunction1(myInt INT in) returns(INT)
    return(5);
end

function testFunction2()
    testFunction1(12);
end

2. 表达式中优先进行求值运算的部分,例如:

newVar INT = (5-2)*4;

3. 表示变量的取值范围(某些类型要求),例如:

newDecimal DECIMAL(10,2);

4. 掩码表示的负数,例如:

result = strLib.formatNumber(myNum,"(*,***,###.##)");

1.2 操作符和优先级

下表按照优先级从高到低的顺序列除了EGL操作符的优先级。有些操作符有多重含义,需要根据上下文来判断。EGL有时用特殊字符去代表类型扩展(参见“类型扩展字符”)和分隔符(参见“分隔符”)。

这个表格不包括赋值运算符(=)和复杂赋值操作符(例如 +=)。关于其他特殊情况,参见“赋值”。

 

操作符 (以逗号分隔)

含义

.

成员访问操作符(一个圆点儿)提供了对实体成员访问的功能,例如记录的字段,库的函数,或者变量的属性。允许多级使用。按照从左到右的顺序成员变得更加具体。

@

@操作符代表一个名字引用属性而非字段。

new

New操作符调用构造函数(一种特殊的用来创建新变量的函数)创建一个引用变量(包含地址而非数值的变量)。除了一些外部类型(EXternalType)的情况,默认情况的构造函数没有任何参数;参见“new 操作数”。

[]

数组访问操作符(方括号)用来分隔指针数值和数组名,或者用来分隔子字符串数值和字符串变量名。a[x] 是一个数组子字符串,b[x:y] 是一个子字符串。

+, -

一元加号(+)和一元减号(-)优先级高于操作数或被括号括起来的表达式,而优先级低于两个表达式之间的操作符。

**

** 是指数操作符,它可以被读作“次方”。例如,c = a**b代表c是a的b次方。第一个操作数(例子中的a)是个浮点类型,但不能是负数。第二个操作数(例子中的b)浮点文本或变量,正数、负数或0.

*, /, &, |, xor

乘号(*),整除号(/),和三个按位操作符具有相同的优先级。整除能得到一个小数;例如,7/5得到1.4.

按位操作符 and (&),or(|),和exclusive or(xor)对两个操作数执行按位操作,并返回一个INT类型的数值。操作数应该是下列类型中的一种:HEX(2), HEX(4), HEX(8), INT, 或SMALLINT。操作符通过把HEX或SMALLINT类型的操作数转换成INT类型的操作数作为开始。如果是HEX类型,操作符会在操作数的左边补0直到操作数达到4位为止。

%

%是余数操作符。它对第一个操作数或数字表达式除以第二个操作数或数字表达式以后进行取余操作。例如7%5结果是2.

+,-

加号(+)和减号(-)是二进制操作符(要求两个操作数),加号和减号的优先级相同。

as

映射操作符,它指定一个类型(第二个操作数)到第一个操作数。

::,?:, +

EGL 用两个操作符专门表示连接。加号也用来表示连接操作符。关于它们之间的区别,参见“连接操作符”。

==, !=, <, >, <=, >=, isa

进行布尔比较的逻辑操作符具有相同的优先级;每个包含一个或多个这些逻辑操作符的表达式的结果为真(TRUE)或者假(FALSE)。

!

!是否定操作符。EGL 对紧跟在!后边的布尔数值(真true或假false)的逻辑表达式进行取反操作。跟在!后边的表达式必须用括号括起来。

is, not, in, like, matches

这些逻辑操作符用于对具有相同优先级的表达式进行比较;每个包含任一这些操作符的表达式被赋值成真(true)或者假(false)。参见“in 操作符”,“like 操作符”,“matches 操作符”。

&&, and

&&(也读作与(and))代表“两者必须都为真(true)”。如果操作符两边的两个逻辑表达式都为真(true),那么表达式为真(TRUE),否则表达式为假(FALSE)。

||, or

|| (也读作 或(or ))代表“两者其一或者两者都”。如果操作符两边的逻辑表达式都为假(false),那么表达式为假(FALSE),否则表达式为真(TRUE)。

 

例子

如果不注意优先级规则就可能导致意想不到的错误,比如下面的例子:


在第一个例子中,开发人员错误地假设减法的优先级高于乘法:

n NUM(3) = 100 - 98 * 100;

EGL解析得到的实际的算式为100 - (98 * 100), 结果得到一个比 NUM(3)大很多的运算结果。结果得到一个EGL0049E An overflow error occurred when assigning a value of -9,700to n.

在第二个例子中,开发人员想要使得以下表达式为真(true)如果element不是数组myArray的成员:

f (!element in myArray)

相反,“否定(not)” 操作符的优先级高于in 操作符,所以EGL在数组中查找一个false值,但这个行为不是开发人员所希望的。

在以上两个例子中,如果使用括号来强制指定优先级,不仅可以避免这些错误,而且可以使得代码更加容易读懂:

n NUM(3) = (100 - 98) * 100;
if (!(element in myArray))

1.3 表达式类型

一个表达式类型具有一个数值和一个类型,类型有一列的限制,即数值必须属于这个类型。以下规则使用EGL原始类型;。

下列规则决定一个表达式的类型。这些规则没有涵盖个体操作数的可能的转换(升级),这种可能的转换(升级)是与平台相关的:

数字表达式(Numeric expressions):

这些规则应用于包括算术操作数的表达式。这些规则定义表达式的希望的类型,单不定义精度和长度,并且不提及操作数如何转换,因为这一过程对于任何一个目标语言来说都不相同。下面的二元操作符能要求升级一个或更多的操作数:

1.        算术操作符 +, -, *, /, %, **

2.        算术比较操作符 ==, !=, <, >, <=, >=

3.        按位操作符 &,|, ^

以下规则按顺序应用于算术操作符和数字比较操作符:

1.        如果其中一个操作数是文本类型,那么表达式的类型就是NUMBER

2.        否则,如果其中一个操作数的是FLOAT类型,那么表达式的类型就是FLOAT

3.        否则,如果其中一个操作数是SMALLFLOAT类型,那么表达式的类型就是SMALLFLOAT

4.        否则, 如果其中一个操作数的是DECIMAL类型,那么表达式的类型就是DECIMAL

5.        否则, 如果其中一个操作数的是BIGINT类型,那么表达式的类型就是BIGINT

6.        否则, 如果其中一个操作数的是INT类型,那么表达式的类型就是INT

7.        否则, 如果其中一个操作数的是SMALLINT类型,那么表达式的类型就是SMALLINT

 

每个按位操作符和(&),或(|), 异或(^)对两个操作数执行按位操作,返回一个INT类型的值。任何一个操作数的类型可能是INT或者SMALLINT等类型

 

文本表达式

这些规则应用于二元运算,这些二元运算必须具有文本类型值。这里假设没有一个操作数是数字类型,然后应用这些数字表达式的规则。以下文本比较操作符能够要求升级一个或多个操作数:==, !=, <, >, <=, >=。


1.4 逻辑表达式

逻辑表达式决定你的程序的条件和循环的逻辑路径,类似if, while, for和case。

表总结了基本逻辑表达式的操作符和操作数。基本表达式由一个操作数、一个比较操作符和一个第二操作数构成。

第一操作数

比较操作符

第二操作数

日期/时间 表达式

==, != , <, >, <=, >=

日期/时间 表达式

第一和第二表达式必须是兼容类型。对于日期/时间的比较,大于号(>)代表时间上更晚;而小于号(<)代表时间上更早。

数字表达式

==, != , <, >, <=, >=

数字表达式

字符串表达式

==, != , <, >, <=, >=

字符串表达式

字符串表达式

like

正则表达式

字符串表达式与一个字符字段或文本进行比较,比较时从左到右逐个字符位进行比较。正则表达式可以包含通配符和转义字符。

 

NUM 或 CHAR 数值

 

==, != , <, >, <=, >=

NUM 或 CHAR 数值

字符串表达式

 

matches

 

正则表达式

字符串表达式与一个字符字段或文本进行比较,比较时从左到右逐个字符位进行比较。

正则表达式可以包含通配符和转义字符。正则表达式规则区分like和match操作符。

 


你可以使用“和”(&&)和“或”(||)操作符将更多成对儿的基本表达式组合在一起去实现复杂表达式。此外,你还可以使用“否定”操作符(!)对一个表达式的值进行取反操作(即把真TRUE改成假FALSE,或把假FALSE改成真TRUE)复杂逻辑表达式

如果一个逻辑表达式包含基本逻辑表达式,而且这个基本逻辑表达式是一个或多个“或”操作符和操作数组成,EGL 将按照优先级规则顺序为表达式进行求值运算。如果其中一个基本逻辑表达式的值为真(TRUE)那么求值停止。考虑下面的例子:

var01 == var02 || 3 in array03 || x == y

如果var01不等于 var02, 继续求值。如果数值3在array03中, 那么整个表达式的值为真(TRUE),而且EGL不需要继续对最后的基本逻辑表达式(x == y)进行求值。

  类似地,如果基本逻辑表达式由“和”操作数组成,那么只要其中一个基本逻辑表达式为假(FALSE),EGL 就立即停止进行求值运算。 在下面的例子中,只要var01 不等于var02,那么求值运算立即停止:

var01 == var02 && 3 in array03 && x == y

你可以用成对儿的括号去实现下列功能:

1.        改变求值顺序

2.        使你的意思更清楚

3.        当使用“否定”操作符(!)对取值为布尔值(真TRUE或者假FALSE)的逻辑表达式进行取反操作时,用括号将逻辑表达式括起来并紧跟在“否定”操作符(!)之后。


1.5 @操作符

@操作符代表在操作符后边的名字引用的是一个属性而非一个字段。它是必要的因为你可以使用一个设定值来为同属一个记录里的属性和字段设定数值。

复杂属性包含一个或多个属性字段。复杂属性需要用@操作符来区分它们自己和属性字段。否则这个操作数很少被使用。如果在同一个名字不一致的设定值里没有字段,那么EGL不需要@操作符来识别一个属性名字。

 

例子

一个EGL字典部分是一列名值对(name-value pairs)。使用一个设定值块来分配这些名值对;你可以使用相同的设定值块来给字典本身的属性分配数值。下面声明了一个新的字典变量:

myRef Dictionary {
    displayName = "myNewDictionary"
};

由于部分解决规则,EGL假设displayName = "myNewDictionary" 是新字典里的一个名值对。如果你想要给字典的displayname属性分配一个数值,那么你必须使用一个@操作符,就像下面的例子一样:

myRef Dictionary {@displayName {"myNewDictionary"}};

1.6 as操作符

as 操作符将一个EGL类型映射到另外一个类型。as 通常连接Java 通过外部类型(ExternalType) 语法返回的对象。这种访问是严格的静态访问,因此,需要把对象映射到已经定义成EGL的类型。as 操作符也常用于处理ANY类型的变量。

 语法:

Expression:  任何有效的EGL表达式

Type:  除了DataItem 以外的任何EGL类型。DataItem 部分不会定义区别于它所代表的原始类型的类型。如果是外部类型(ExternalType)引用, 运行时环境代码需要引用EGL外部类型(ExternalType)代表的实际类型。这种类型可以包括空类型说明字符“?”.

 

例如:

在下面的例子里,字典数值默认的原始类型是ANY。你不能再数字表达式中使用ANY类型,所以你必须把它的数值映射成一个数字类型。

aDict Dictionary{ a = 1, b = 4 };
result int;
result = (aDict.a as INT) + (aDict.b as INT);

错误处理

如果你试图将一个不合适的数值映射成一个目标类型,EGL 将抛出一个TypeCaseException异常。

 

1.7 连接操作符

EGL 除了加号以外还提供了两种连接操作符。你可以使用以下操作符进行连接操作:

:: 操作符

(两个冒号)将简单、赋值兼容类型转换成STRING 并将它们连接起来;这个操作符也能将一个元素追加到一个数组中去。可变长度为空的元素被忽略;固定长度为空的元素被认为是空格。如果两个操作数都为空,那么操作数返回空。

?: 操作符

除了空数值以外其他行为都和::相同。如果它连接的任何一个元素有空值,那么它的返回值为空。

如果你使用加号进行连接操作,左边的表达式决定结果的类型。如果左边的表达式是一个数字变量,结果就是一个数字; 如果左边的表达式是个文本变量,那么结果是个连接文本。

例如:

以下代码说明了使用三种不同的连接操作符将得出不同的结果:

result, var1, var2, var3 STRING?;
result2 INT?;
var1="Sun";
var3="day";
result = var1 :: var2 :: var3; // result is "Sunday"
result = var1 ?: var2 ?: var3; // result is null
var1 = "123";
var3 = "456";
result1 = var1 + var2 + var3; // result is "123456" (STRING)
result2 = var1 + var2 + var3; // result is 123456 (numeric)操作数操作数

1.8 in操作符

in 操作符的作用是在一个数组中查找一个数值。 如果找到要查找的数值,表达式的值设为真(TRUE) 并且 将sysVar.arrayIndex 系统变量设置成指向包含数值元素的指针。如果没有找到要查找的数值,表达式的值设为假(FALSE),并且将sysVar.arrayIndex 系统变量设置成0.

 语法

searchValue:一个表达式。

Array:一个一维数组,或是多维数组的一个元素

Start:一个整数或者一个值为整数的表达式。开始(start)的值指定了要查找的数值(searchValue)中的第一个元素。如果开始(start)的值大于数组中元素的数量,那么表达式的值为假(false),并且sysVar.arrayIndex被设置为0。如果in 表达式不包含 ‘from start’ 字段,那么就从数组或数表列的第一个元素开始查找。(EGL数组指针从1开始而不是0.)


1.9 new操作符

EGL 中的new操作符可以为一个特殊类型动态地创建存储空间。如果你创建一个引用类型变量,new创建一个指向存储空间的引用;否则它会创建一个存储空间本身。用new操作符你可以指定一个设定值的块(block)。注意对于一个可以为空的变量一个设定值的块会自动关闭空标记(null flag)。关于更多信息。

语法

partName:一个EGL部分的名字。

 

什么时候使用new操作符

new操作符唯一有效的用法是当你使用它去创建存储空间但不命名。在下面的例子中,函数以一个字典作为它的参数:

func( new Dictionary{ key1 = 3, key2 = "Hello", key3 = false } );

在下面的例子中,记录包含一个字段,这个字段是另外一种记录的数组。在这种情况下,必须使用new 操作符。

record CustomerArray
    myCustomers CustomerRec[] = [ new CustomerRec { idNum = 101 },new CustomerRec { idNum = 102 } ];
end

换句话说,不能声明CustomerRec变量并把它放在数组里。一个记录的初始化程序不能访问任何除了记录中的字段以外的变量。可以通过以下方法用new操作符声明变量:

myInt INT = new INT;

跟以下标准声明方法比起来这种声明方法没有任何好处而有一个主要缺点:

myInt INT;

当使用new 操作符时,空间呗保留了两次。首先赋值运算左边自己创建一个INT的空间和名字。然后new操作符又创建了一个INT,并且给它赋值为第一个。第二个INT就不会再被使用了。你可以使用以下声明方法去创建一个可以为空的变量(由问号所代表),它的初始值不为空:

myInt INT? = new INT;

左边创建一个可以为空的变量。New 操作符创建一个INT,它不为空并且被赋值成第一个INT。用以下的方式,创建一个单个变量,你可以得到相同的结果:

myInt INT?{};


2. EGL语句和语法

语句是EGL中最小的独立的计算单位,指定一个执行的行为。在大多数情况下,语句按照顺序执行。EGL支持下面几种语句:

1.     变量或者常量语句,需要保留存储

2.     强制语句,包括:函数调用、用来给已经声明的变量赋值的值块

3.     EGL关键字语句,包括下面几种:
数据移动语句、条件和循环语句、控制语句的转移、异常处理语句、数据访问语句、UI语句。

语句要么用分号结束,要么用end块结束。语句的名字是大小写不敏感的,例如,record1和RECORD1是一样的,add和ADD是同样的关键字。下面的情况是大小写敏感的:

1. generatable的名字,例如程序必须和相同的文件名一样,大小写敏感

2. EGL包名

3. 一些UI技术


2.1 注释

注释在生成过程中会被忽略掉,说明代码的作用。有两种方法来创建注释:第一种是开头用//来表明,一直到这行结束。第二中是用/*注释*/来表示

EGL不支持嵌入的注释,下面的是非法的

/* this line starts a comment /* and
this line ends the comment, */
but this line is not inside a comment at all */

可以把两种方法合在一起用,下面是合法的:

a = b; /* this line starts a comment // and
this line ends the comment */

对于内嵌的SQL代码, SQL注释是用(--)双连字号开始或者在空格后面直到这行结束。


2.2 条件和循环

条件语句在程序内部传送控制。EGL提供下面的条件语句:

case

if, else

循环语句测试一个条件,定义重复一套语句的次数。有时候循环会改变初始测试的条件。EGL提供下面的循环语句:

 for

forEach

while

此外,EGL有两个语句是用来在条件和循环语句中移动的:

continue

exit

 你可以有标记符循环语句,标记符用冒号结束,看下面的例子:

OuterLoop:
while(moreFood())
	meal string = getMeal();
	while(meal!="")
		course string = nextCourse(meal);
		eatCourse(course);
		if(indigestion())
			exit OuterLoop;
		end
		meal = remainingCourses(meal);
	end
end

OuterLoop是标记符。如果indigestion()返回为真,将退出OuterLoop循环。


Case语句

语法

Label:  exit指向的标识符,后面接冒号

Criterion:   变量,常量,表达式,字面值或者系统变量。如果你指定criterion(第一个语法),when后面必须包含一个或者多个matchExpression例子;如果你没有指定它(第二个语法),when后面必须包含一个logical expression。

When: 条件实例的开始。如果你指定criterion,when后面是第一个包含等于criterion的matchExpression;如果你没有指定它,when后面是第一个包含等于TRUE的logical expression。

MatchExpression:和criterion比较的表达式

logicalExpression:TRUE或者FALSE的表达式

statement:如果EGL匹配到when或者otherwise后面的表达式,这些语句会被运行

otherwise:如果不能匹配表达式,EGL调用的子句的开始

 

例子一:

case (myRecord.requestID)
    when (1)
        myFirstFunction();
    when (2, 3, 4)
        try
            call myProgram;
        onException(iex InvocationException)
            myCallFunction(fileEx);
        end
    otherwise
        myDefaultFunction();
end

例子二,没有criterion:

Program calc3
    x INT = 3;
    y INT = 5;
    z INT = 7;
 
function main()
    case
        when (x == 3)
            syslib.writeStdOut("x passes");
        when (y == 5)
            syslib.writeStdOut("y passes");
        when (z == 7)
            syslib.writeStdOut("z passes");
        otherwise
            syslib.writeStdErr("You should not see this msg");
    end
end

Continue语句

 

continue从for, forEach或者while中退出本次循环,但是不退出所有的循环。

语法

Statement:你可以指定你想继续的EGL语句(for,forEach或者while)

Label:附加在封闭for,forEach或者while后面的标识符

 

下面的例子打印数组的每个元素,每十个一行

for (i from 1 to 100 by 1)
    printReport(myArray[i]);
    if ((i % 10) != 0)
        continue;
    end // if
    printReport(blankLine);
end // for

Exit语句

EGL exit从函数或者函数某个部分或者条件/循环控制的块结构中全部退出。

语法


Statement:你可以指定代码块的种类退出

label1:    附加在case, for, forEach, if, while后面的标识符

returnValue: 一个整数或者变量,常量或者数字表达式可以解析成一个整数

sysVar.returnCode:包括返回给操作系统的值的系统变量

label2: 这个语法仅提供给迁移程序的兼容性。

 

这个例子打印头100个客户,他们的balance不是0

while (getCustomer() != 0)
	for(i from 1 to 100 by 1)
		if (myCustomer.customerBalance == 0)
			exit for;
		end
	printBalance(myCustomer);
	end
end

For语句

Label:标识符,后面跟冒号。Continue或者exit可以指向的标识符

Counter:十进制数字变量

Start:counter的初始化值

Finish:counter的上界(如果你用的是decrement,那么就是下界)

Decrement:缺省,EGL在每次循环结束后,增加delta给counter。Decrement表示减少

Statement:在EGL语言中的语句

下面的例子中,counter i在statement中的语句:

sum = 0;
// 给sum增加10个值
for (i int from 1 to 10 by 1)
    sum = inputArray[i] + sum;
end

forEach语句只用于相应的数据库设置的结果。

 

if,else语句

语法

Label:exit指向的标识符

logicalexpression:结果是真或者假的表达式

statement:EGL语句

示例

if (sysVar.systemType is WIN)
displayFormattedResults();
else
    displayTextResults();
end

While语句

语法

Label:continue,exit指向的标识符

logicalexpression:结果是真或者假的表达式

statement:EGL语句

示例

while (index < 7)
    myRec[index].airport="Airport" + index;
    myRec[index].city="City" + index;
    myRec[index].state="S" + index;
    index = index + 1;
end

2.3 在程序内部转移控制

在程序间传送控制最通用的方法是函数call,它使用return来返回控制给原始的函数

调用函数

用库或者包,或者关键字this的函数是合法的。你可以传下面的参数给函数:

1.直接量

2.常量

3.变量

4.一个复杂的数字,文本或者日期/时间的表达式

5.访问变量或者对于一个访问求值的表达式

如果测试成功,一个布尔函数返回真,一个数字函数返回非0的值

示例:

package com.CompanyB.CustomerPackage;
program BalanceCheck type BasicProgram
	customer INT = 1;
	balance DECIMAL(7,2) = 0;
	function main()
		while (balance >= 0)
			balance = getCustomerBalance(customer); // 返回 -1
			printBalance (balance);
		end // while
	end // 主函数
function getCustomerBalance (custNo INT in) returns (DECIMAL(7,2))
	myCustomer CustomerRecord; // 已经在库里定义
	myCustomer.customerNumber = custNo;
	try
		get myCustomer;
	onException (CustomerNotFound)
		myCustomer.customerBalance = -1; // 循环断点
	end // 尝试block
	return (myCustomer.customerBalance);
	end // 子函数
function printBalance (pBal DECIMAL(7,2) in)
	writeStdOut (strLib.formatNumber(pBal));
	end // 子函数
end // 程序

Return语句

EGL 从一个函数里返回语句退出或者可选地返回调用的函数的值

语法

returnValue:在EGL函数声明中和返回定义兼容的变量,直接值或者常量。


2.4 异常处理

EGL解释程序错误叫做异常。在EGL创建的程序执行下面的行为的时候,异常会发生:

1.访问文件,队列或者数据库

2.调用别的程序

3.调用函数

4.执行赋值,比较或者计算

处理异常意味着你不允许当前的程序终止,但是对于错误提供一些特殊的处理。

 

系统异常

messageID:  包括异常标识符的字符串,比如”EGL0050E”.

Message:     描述异常的字符串,

你可以通过使用多个onException语句来定义当前的异常:

if (userRequest = "A")
	try
		add record1;
	onException(ex1 FileIOException)
		myErrorHandler(1);
	onException(ex2 RuntimeException)
		myErrorHandler(2);
	onException(ex3 SQLException)
		myErrorHandler(3);
	onException(ex4 AnyException)
		myErrorHandler(4);
	end // try
end // if

Try语句

EGL try的语句用try块来标识开始,用end来作为结束符。一个典型的try块包含两组语句:

1.       你需要处理的错误条件。条件在try和第一个onException关键字之间。如果没有错误条件发生,在任意的onException块里的语句都可以被忽略。

2.      如果错误条件发生,语句会被运行。这些语句在第一个onException和 end关键字之间

 

语法


exceptionRecordVariable: 异常stereotype的记录语句。这个记录包括messageID和message。

 

 

Throw语句

语法

exceptionExpression: 一个和异常变量有同样类型的表达式

EGL throw指定你想要触发的异常。示例代码如下:

// 当异常已经被定义
nullEx NullValueException;
...
throw nullEx;
// 定义和语句
Record CustomerException type Exception
customerNumber INT;
end
...
throw new customerException {
customerNumber = custNum,
message = "Illegal customer number" };

3 Scope作用域

作用域是你可以用来区分相同名字的项的上下文。大部分过程语言有子界的概念;典型地,如果你在子界中声明变量myVar,它的值对于子界就是本地的。本地意味着程序的子界不能看见这个变量并且不能访问它的值。为了理解EGL的作用域,你需要理解在程序命名中提供作用域的结构。

 

3.1 Part

部分(part)在EGL中是一个重要的概念。部分指向应用程序独立的部分。一个部分不能存在于另一个部分中。部分可以和一个程序一样大,也可以和一个单一的DataItem一样小。你可以使用EGL编程中三种主要的部分:

1.      数据部分包括值

2.       逻辑部分执行数据上的操作

3.       用户界面部分提供和用户交互的指定的数据结构

Generatable部分不同于别的部分。它必须占用一个独立的源文件并且生成一个可编译的单元,例如FormGroup,库和程序。变量是一个在EGL逻辑部分或者记录里命名的项。变量基于数据部分,这意味着变量保留特殊的数据的存储。如果你在一个部分中声明一个变量或者常量,通过部分标识符有作用域:

1.       如果在一个函数中声明,标识符作用在函数的本地范围里。

2.      如果在generatable部分声明,比如程序,但是在任何函数之外(比如main()之外),名字对于部分来讲是全局的。

3.       如果在一个库部分里面声明但是在函数之外,标识符作用域在运行单元里


3.2 Type

类型(Type)和部分(Part)是相似的,但是术语是不能内部改变的。在任何的计算机语言中,类型就是限制对于变量一套合适的值的修改符。例如,INT是一个数字类型,这保证一个INT变量必须包含一个整数。EGL primitive 部分也是类型。EGL对于它的类型是严格的。例如,当你创建一个基于字典部分的变量时,如果使用变量构造一个表达式是有规则的。你不能把字典类型变量当作INT类型的变量

 

3.3 Qualifier限定符

你不能同时在作用域里有两个一样的名字。但是,从另一个部分你可以访问的限定符指向一块内存,这个内存逻辑上在一个容器(比如程序)里面。在那些情况下,你可以使用包装在容器里的名字来限定名字,使用点号,你可以用下面的方法来限定名字:

1.      记录里的域

2.      表格里的域

3.      在库里的变量或者函数

4.      在包里的部分

举个例子,比如变量customerBalance在一个叫做myCustomer的记录变量里,你的代码可以用下面的形式指向记录的域:

myCustomer.customerBalance

3.4 表达式中的名字解析

在EGL表达式中的名字可以指向下面的类型:

1.      参数

2.      变量

3.      域

4.      函数

5.      部分(如果名字合法)

不论表达式在哪里,名字解析过程是相同的。

为了在表达式中解析一个名字,EGL找下面的声明,按照顺序:

1.  当前的变量

2.  当前的I/O对象

3.  程序变量

4.  表名

5.  数据表名

6. 

7.  库变量

8.  系统变量


3. 5 this关键字

在一个handler中定义一个字符串变量a并且赋值b,调用函数ab(),在函数里也有个变量a赋值是a,用this.a调用handler中的变量a,所以最后的输出结果是ba

handler h1 type RUIhandler{initialUI =[ui], onConstructionFunction = start, cssFile = "css/tseet.css", title = "h1"}ui GridLayout{columns = 3, rows = 4, cellPadding = 4, children =[]};
	a string = "b";
function start()
    ab();
end

function ab()
  a string = "a";
  this.a = this.a + a;
  syslib.writeStdout(this.a);
end
end

在一些稀少的情况下,你可以使用this在一个赋值声明中覆盖一个设置值的块。这里this作用域就是设置值块所在的作用域,看下面的例子:

program myProgramA type BasicProgram
varX STRING = "program";
	function main()
		varX STRING = "main";
		myFunctionB();
	end
	function myFunctionB()
		varX STRING = "Function B";
		writeStdErr(this.varX);
	end
end
this.varX变量显示值”program“,作用域是myFunctionB()


3.6 命名空间

命名空间是一套独立的名字的标识符。在更大的上下文里面使用命名空间作为限制符来解决矛盾。例如,如果你有一个叫做CustomerLib的EGL库,在库里所有的名字必须是唯一的。因此,如果你在CustomerLib命名空间里声明一个名叫runningBalance的变量,你可以通过增加命名空间给变量名来指向命名空间外面的变量(使用点号):

CustomerLib.runningBalance = CustomerLib.runningBalance +
myCustomer.customerBalance;

3.7 EGLprojects,包和文件

projects和包是你可以用来组织你的EGL源文件的任意的类。使用它们使你的应用程序的一些部分在一起,而独立于别的部分。实际上,EGL体系结构尝试根据一个或者多个下面的标准,划分一个应用程序:

1.      要解决的商业问题

2.      要使用的技术类型

3.      做编码的开发组

4.       用来存储源代码或者维护源控制的归档方法

5.      最佳的程序大小

6.      测试策略

一个小的应用程序典型地包含单一的project。一个大的企业应用程序包含一些project,每个下面有几个包。你要专注于:

1.      这些商业问题是什么

2.      谁做的开发

3.       在哪里程序写,运行和维护

作为总体设计单位,project和包在EGL工作空间中代表不同的目录。Project是最高级的,下面是在EGLSource目录中创建的包。

Project和包在一个地方是不一样的。你可以通过使用包名作为限制符把部分和变量带到你当前的作用域。相反,你绝不能在一个EGL程序中使用project名字


3.8 Package关键字

语法


示例代码:

package com.companyb.customer;
Record CustomerRecord type SQLRecord
{ keyItems=["customerNumber"] }
	customerNumber INT; // key item
	customerName STRING;
	customerBalance DECIMAL(9,2);
end
Library CustomerLib
	myCustomer CustomerRecord;
	getCustomer()
	...
	end // end function
end // end libary

3.9 Import关键字

语法


packageName:这是搜索需要的部分的包名

partName:导入的部分名


3.10 Use关键字

语法

partName:你想增加到当前部分的作用域的部分的名字

partProperties:依赖于你指定的部分的类型,你可能指定use声明的属性

 

示例代码:

use CustomerLib;
function main
	getCustomer(); // function in CustomerLib
...
end

代替指向CustomerLib.getCustomer(),你可以创建CustomerLib的use声明并且简单地指向函数getCustomer()


3.11 Public/Private关键字

在EGL中没有“public”的关键字,所有的没有声明为“private”的都是”public”。如果你定义比如程序或者库为私有的,这部分对于它的包是私有的,别的包不能导入它的包。

如果在一个函数里变量是私有的,那么,函数外不能引用这个变量。在程序或者handler里你合理地使用private,最普通的你会在库或者服务里用它。下面的声明可能发生在一个税收的程序里,不允许外面的函数修改表格:

private taxTable INT[][]; // 别的程序不允许改变它
private function buildTaxTable() // 不允许访问
	...
end
function figureTaxes() // 缺省是public
	buildTaxTable();
	...
end
















Linux下X Server工作方式

Linux下X Server工作方式   2011-03-11 23:47:20|  分类: rh131笔记 |  标签:x11  server  linux  client  etc  |字号...

【OpenGL ES】EGL简介

【参考-khronos-egl】https://www.khronos.org/egl 【参考-khronos-egl-api(目前共34个API)】https://www.khronos.org/...
  • iEearth
  • iEearth
  • 2017年05月04日 20:28
  • 1489

EGL语言教程之一:变量与数据类型

变量与数据类型 计算机处理的对象是数据,而数据是以某种特定的形式存在的(例如整数、浮点数、字符等形式)。不同的数据之间往往还存在某些联系(例如由若干个整数组成一个整数数组)。数据结构指的是数...

【c语言问题系列教程之二】结构、联合和枚举

一、结构声明 1.两种结构声明的类型 ①struct x1{...};此方法声明了一个结构标签,使用该声明的结构标签时必须是 struct x1 a;② typedef struct {...} x2...

0602 c语言操作符和表达式

2016年06月02日学习日记c语言操作符和表达式 算数运算符中+ - *和数学中完全一样 / 1.整数除以整数结果是整数 2.如果操作数中有浮点型则结果一定为浮点型 % 对于“%”运算...

C语言操作符和表达式以及数据类型提升实例以及疑惑

先上源码 该源码的主要是用将unsigned int、unsigned char、unsigned float的三种数据类型 分别将这三种数据类型进行小减大 然后if判断该相减表达式的正负值,然...

C语言教程三之二 C语言C语言

  • 2010年05月22日 02:02
  • 14.31MB
  • 下载

Java小白进阶之二---移位操作符

前提:移位操作符操作的运算对象是二进制的“位”。移位操作符只可用来处理【整形值】 java中有三种移位运算符        左移的规则只记住一点:丢弃最高位,0补最低位 ...

重读《Java编程思想》之二:操作符

最近比较忙,没时间整理,其实不整理也无所谓,最终是想进一步理解一些机制和原理,整理在这里只是为了以后方便查阅,继续.....  1、  当编译器观察到一个string后面紧跟着一个+,而这个加号的后...

RxJava系列之二 变换类操作符详解1

1.回顾上一篇文章我们主要介绍了RxJava , RxJava 的Observables和 RxJava的just操作符。以及RxJava一些常用的操作。 没看过的抓紧点我去看吧。 其实R...
  • jys1115
  • jys1115
  • 2015年08月24日 16:07
  • 1776
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:EGL语言教程之二:表达式与操作符
举报原因:
原因补充:

(最多只允许输入30个字)