其中:
<新的值的名字>是以小写字母开头的标识符;
<该值的类型>可以是一个类型的名字,也可以是类型描述; <值描述>是基于整数、字符串、标识符的组合。 如:
counter Lottery-number ::= 45
sextuple Lottery-draw ::= { 7, 12, 23, 31, 33, 41 } pair Coordinates ::= { x 5, y -3 }
son-choice Afters ::= dessert:\date Date ::= \
在ASN.1的应用中,绝大多数的值都是动态获得的,但是指定某些值,特别是在约束型子类型中,提高描述的可读性。
如:
upper-bound INTEGER ::= 12 Interval ::= INTEGER (0..upper-bound) default-value Interval ::= 0 Pair ::= SEQUENCE {
first [0] Interval DEFAULT default-value, second [1] Interval DEFAULT default-value }
2.5 信息对象类和信息对象
<信息对象类> ::= CLASS <类描述> WITH SYNTAX <信息描述>
有时我们需要表达比注释更为正式的一些信息,例如我们要说明这样一个事实:一个结构类型的成员依赖于和这个结构类型相关的值。
如:
OPERATION ::= CLASS {
&number INTEGER UNIQUE, &Argument-type, &Return-result-type }
WITH SYNTAX {
OPERATION NUMBER &number
TAKES AN ARGUMENT OF TYPE &Argument-type AND RETURNS A VALUE OF TYPE &Return-result-type }
在ASN.1中我们没有指出操作的具体内容,但是我们给出了一个机器要求另一个机器执行这个操作所需要交换的数据结构。
域&number以小写字母开头,后面跟了类型INTEGER。这个整数值用作信息的标识符,因为后面加了UNIQUE关键字。
域&Argument-type和&Return-result-type以大写字母开头,后面什么都没有跟。他们是一些ASN.1类型的引用(这可能会因为类型没有定义而不能编码)。
WITH SYNTAX块定义了一个用户友好的语法,说明了这个类的成员。 上述信息对象类的一个对象定义如下:
plan-projection OPERATION ::= //为什么是小子字母开头 {
OPERATION NUMBER
12
TAKES AN ARGUMENT OF TYPE Coordinates AND RETURNS A VALUE OF TYPE Coordinates-in-plan }
因为两个通讯中的机器使用相同的描述,因此相同的信息对象就能在这两机器间共享。 一个给定类的所有对象,可以在描述中收集到一个对象集合中,如下:
SupportedOperations OPERATION ::= //为什么大写开头还要特别注明呢?一直不都是以大写开头的吗?
{
plan-projection | translation | symmetry, ... }
注意:和对象不同,对象集合以大写字母开头。字符“…”表明新的对象可以由通讯中的机器动态加入。
信息对象永远不会被编码,传递他们各项信息的唯一方法是在一个类型中引用他们。我们用上面这个信息对象集合来约束一个结构类型:
Execute-operation ::= SEQUENCE {
code OPERATION.&number({SupportedOperations}), argument OPERATION.&Argument-type ({SupportedOperations}{@code}) }
Receive-result ::= SEQUENCE {
code OPERATION.&number({SupportedOperations}), result OPERATION.&Return-result-type ({SupportedOperations}{@code}) }
这段晦涩的描述,声明了这样一种情况:
Execute-operation操作它的编号在code成员中,当其argument发送给对方时,一定要满足域&Argument-type的类型。链接(或者表约束)“@code”说明这个参数是依赖于操作的。
对方返回的Receive-result也有类似约束。
2.6 模块定义
<模块名字> DEFINITIONS <缺省Tag> ::= BEGIN
EXPORTS <导出描述> IMPORTS <导入描述> <模块体描述> END
一般协议由一个或者多个模块组成,模块用来收集数据结构定义。
模块名字必须以大写字母开头。模块能以一种“全局指针”(Universal Pointer)的方式来引用,称为对象标识符(Object Identifier),用花括号标识在名字之后。
如:
Module2 { iso member-body(2) f(250) type-org(1) ft(16) asn1-book(9) chapter5(0) module2(1) } DEFINITIONS AUTOMATIC TAGS ::= BEGIN
EXPORTS Type2;
IMPORTS Type1, value FROM Module1 {iso member-body(2) f(250) type-org(1) ft(16) asn1-book(9) chapter5(0) module1(0)}; Type2 ::= SEQUENCE OF Choice Choice ::= CHOICE {
a INTEGER (0..value), b Type1 } END
AUTOMATIC TAGS或者缺省,则说明不关注模块的tag交给编译器自己自动处理;如果需指明具体的tag值,则需要用“[]”来标识。此外tag的模式还可以是EXPLICIT TAGS和IMPLICIT TAGS。还可以使用EXTENSIBILITY IMPLIED来使模块中所有SEQUENCE、
SET、CHOICE和ENUMERATED类型可扩展。
条目IMPORTS和EXPORTS(不是必须的)定义模块的接口。其中IMPORTS声明在其它模块定义但在本模块会用到的类型或者值;EXPORT声明在本模块之外可以访问的类型或者值。
注意IMPORTS的语法为:
IMPORTS <名字>, value FROM < 其它模块的Object Identifier >; EXPORTS的语法为: EXPORTS <名字>;
使用IMPORTS时,没有类似IMPORTS ALL的语句能将一个模块中所有定义都导入,因此需要协议描述者逐条写出每个需要导入的符号。对于参数化的分配,需要使用花括号,如:
ModuleName DEFINITIONS ::= BEGIN
IMPORTS T{} FROM Module1; U ::= T{INTEGER} END
在BEGIN之后,IMPORTS之前的语句,则不使用导入的符号。
2.7 模块与分配(Assignment)
2.7.1 分配Assignment
有6种不同形式的数据与分配相关:类型、值、值的集合、信息对象类、信息对象和信息对象集合。 I. 定义一个新类型
如前所述,定义新类型,如:
TypeReference ::= CHOICE { }
integer INTEGER, boolean BOOLEAN

