Basic language elements

This topic includes information about the following basic language elements:

Character set

The basic unit of Synergy DBL is the ASCII character. (Appendix B: ASCII Character Set contains the complete ASCII character set.) ASCII characters are combined into sequences that represent the elements of Synergy DBL. Certain characters, called delimiters, separate adjacent language elements in a statement. Note that identifier names and keywords are case insensitive in DBL.

This documentation refers to the following ASCII character subsets:

Numeric

0, 1, 2, 3, 4, 5, 6, 7, 8, and 9

Alphabetic

Uppercase characters A through Z and lowercase characters a through z

Alphanumeric

Both numeric and alphabetical characters

Alpha

All ASCII characters except the nonprintable characters (for example, carriage return, line feed, and form feed)

Data types

Synergy DBL supports all of the data types listed in Data types.

Statements

Synergy DBL provides six types of statements:

Declarative statements declare the variables and definitions that the routine can access. Many, but not all, declarative statements appear in the data division or class definition of your program. The declared variables can be local to the routine, global to the routine, or used to exchange data with other routines.

Data manipulation statements directly change data.

File manipulation statements access records within a file or group of files.

When a routine is being executed, control begins with the statement that follows the PROC statement and flows sequentially to each successive statement. Control statements alter the order of execution by directing control to another statement, transferring control to another routine, ending processing of the current routine, or returning control to a referencing routine. This type of statement is used to create loops and internal functions within a program.

Input/output statements control the exchange of data between the executing program and the input/output devices attached to the computer system. Such devices include printers, terminals, mass storage devices (like disks and floppies), and any other data transmission devices attached to your computer system.

Interprogram communication statements pass and obtain data from interactive processes.

In this documentation, we refer to the statement name as a “keyword.” See Synergy DBL Statements for information about individual statements.

Preprocessor and compiler directives

Preprocessor directives are instructions for the preprocessor and are implemented before any code is compiled. Compiler directive statements instruct the Synergy compiler and are evaluated only when a program is compiled. Directives are not included in the resulting executable program. See Types of directives and syntax for more information.

Identifiers

Identifiers are used as names for namespaces, classes, methods, subroutines, functions, parameters, records, fields, and properties. Identifiers begin with an alpha character (or an underscore in Synergy .NET), optionally followed by a sequence of alphanumeric characters, underscores (_), and dollar signs ($) that identify a statement, variable, or routine to the compiler. For example, Read, a10, namelast, and TAX$RATE_single are all valid identifiers. Destructor method identifiers prefix a tilde (~) to the name of the class.

Identifiers are not case sensitive. For example, NAME_FIRST is the same as name_first and NAME_first.

An identifier section is one of the sections in a nested identifier which may include namespace, class, or member name. For example, the following identifier has three identifier sections:

mynamespace.myclass.myfield

The maximum length of an identifier section is 30 characters on Windows and Unix and 31 characters on OpenVMS.

All identifiers within a scope, such as classes and structures in a namespace or member identifiers in a class, must be distinct, independent of kind, except where the names are identical and resolved via overloading, such as two routines with the same name but different parameters. A scope is defined to be the smallest of one of the following groupings that has the identifier declared as one of its members, not including inherited members:

Thus, you cannot have two fields with the same name, or a field and a method with the same name in the same class, but you can have two methods with the same name in the same class if their method signatures are different. A field name and a property in the same class can have the same name as long as the case is different.

You can’t have two classes with the same name or a class and structure with the same name in the same namespace.

Two method signatures are considered to match if their identifier, number of arguments, and argument types match exactly. Two subroutine or function signatures are considered a match if their identifiers match exactly.

Keywords

Keywords (like READ, END, and .DEFINE) have predefined meanings in Synergy DBL and identify statements and compiler directives. They must be spelled exactly as documented.

Replacement identifiers

A replacement identifier defines a text string that is to be substituted for the identifier throughout the program. A replacement identifier is defined by the .DEFINE statement.

Variable names

Variable names are identifiers that refer to data records, groups, and fields. A variable name can have a maximum of 30 characters. Although variable names appear in a program listing exactly as you typed them, the compiler translates the names to uppercase. For example, the compiler recognizes both of the following identifiers as the identifier ABCDE:

aBcdE
abcDe

Statement labels

You can label any statement in the procedure division with a symbolic name. Several of the program control statements can reference this label, enabling you to transfer control to a specific statement during program execution. For example, you might use a label to transfer control to an error-trapping routine or when using a CALL statement.

The statement label must be the first nonblank item in the statement, followed by a comma and must be unique within the routine. A statement label can have a maximum of 30 characters on Windows and Unix and 31 characters on OpenVMS.

Here’s an example:

    call lbl02          ;Unlabeled, references label lbl02
      .
      .
      .
lbl02,                  ;Labeled
    incr flg
    return

Routine names

Routine names identify which main routine, external subroutine, or function is being referenced. Like all other identifiers, a routine name can have a maximum of 30 characters on Windows and Unix and 31 characters on OpenVMS.

To call a global routine from within a class that contains a routine of the same name, include ^global as part of the routine name path. For example,

xcall ^global.sub1()

Data reference operation names

A data reference operation name identifies a data reference operation. See Data reference operations for more information.

Textual literals

A textual literal is either a sequence of characters enclosed between matching delimiters (single or double quotation marks) or a sequence of numeric characters, which may be preceded by a plus or minus sign. A literal represents a specific value that is defined at compile time and cannot be changed during execution.

In Synergy .NET, a literal or literal cast as type object or passed to a parameter of type object has its type changed from a Synergy literal type to the corresponding .NET literal type, and then it is boxed. (For example, “abc” is type string, and 10 is @int.) If you want a Synergy literal type instead, cast the literal as the desired Synergy type (@a or @i).

Alpha literals

An alpha literal is a sequence of characters enclosed in matching single or double quotation marks. An alpha literal can be up to 255 characters long.

Here are some examples of alpha literals:

If an alpha literal contains either a single or double quotation mark and you’re using the same character as the delimiter, you must use two successive characters to represent a single embedded mark. The examples below illustrate embedded delimiters: two successive quotation marks are required to specify one quotation mark within the literal.

If the embedded character is different from the ones delimiting the literal, you don’t need to double the embedded character (as shown in the examples below).

Sometimes it’s more convenient to split an alpha literal into smaller physical parts. For example, you might do this if you’re using the literal to initialize an entire record and you want to append comments to each field. The Synergy compiler concatenates several alpha literals if they are separated only by blanks and tabs. (If sections of the alpha literal are on continuation lines, each line must begin with the continuation character [&].)

For example:

"This is "     "an alpha "     "literal"

and

"This is "
&"an alpha "
&"literal"

are functionally the single alpha literal

"This is an alpha literal"

The blanks and tabs between the separate alpha literals are not part of the concatenated literal. (See Continuation lines for a warning about splitting alpha literals across two or more physical lines.)

Alpha literals are case sensitive.

Decimal literals

A decimal literal is any consecutive sequence of numeric characters, which may be preceded by a plus (+) or minus (–) sign. A decimal literal can consist of a maximum of 28 digits. The compiler strips nonsignificant leading zeros to a minimum of one digit. For example, the literal 00003 is stored as 3. The literal 000 is stored as 0.

Here are some examples of decimal literals:

Implied-decimal literals

An implied-decimal literal is a sequence of not more than 56 numeric characters, which may be preceded by a plus or minus sign. A maximum of 28 digits can appear before the decimal point, and a maximum of 28 can occur after it. The decimal point cannot be the first or the last character in an implied-decimal literal; at least one leading and trailing digit must appear before and after the decimal point.

Here are some examples:

The compiler strips nonsignificant leading and/or trailing zeros prior to processing.

Integer literals

You cannot explicitly write an actual integer literal in a source line in the same way that you can specify alpha, decimal, and implied-decimal literals. However, if you include a decimal literal in an arithmetic expression with an integer variable, the compiler builds an integer literal into the code.

Tip

You can also use %INTEGER with a numeric literal argument to create an integer literal.

Error literals

An error literal has the format $ERR_mnemonic, where mnemonic is an error identification mnemonic. One error literal is defined for every trappable runtime error. (For example, $ERR_DIVIDE specifies the “Divide by zero” error.)

The entire error literal is treated as a decimal literal, and you can use error literals with ONERROR statements, in I/O error lists, and anywhere else in your program that you can use decimal literals. Here’s an example:

onerror($ERR_IOFAIL, $ERR_DIGIT) proc_err1, ($ERR_EOF) proc_err2
read(CHN, data, rec_id) [$ERR_IOFAIL=proc_err1]

The Synergy Errors tab contains a complete list of Synergy DBL error mnemonics, numbers, and messages.

Variables

A variable is an identifier that refers to a data location in your program. Before using a variable in statements in the procedure division, you must first define it in the data division. The data division statement that defines the name and data type of the variable also determines the characteristics of the variable’s data area: size, possible initial values, and position relative to the other variables.

Shared variables (common records, global records, and global literals) can be declared by any routine in a program and can be accessed by any routine in a program. A shared variable name must be unique. Variables that are not shared are local to the routine in which they are declared.

Variable path specifications

A path uniquely references a named record or a field within a data structure (as specified by the RECORD or GROUP statement). Variable path specifications have the following format:

[struct_name.][struct_name….]field_name

Paths have the following characteristics:

record a
    group b
      fld           ,a2
      group c
        nam         ,a20
        city        ,a10
      endgroup
    endgroup

You can reference the field city with the following paths:

city
a.city
b.city
c.city
a.b.city
a.c.city
b.c.city
a.b.c.city

Note that you don’t have to use the whole path name to reference a field.

record inhouse
    accnt           ,d5
    name            ,a30
    address         ,a40
    zip             ,d10
record client
    accnt           ,[100]d5
    group customer  ,[100]a
      name          ,a30
      group bldg    ,a
        group address ,a
          street    ,a4
          zip       ,d10
        endgroup
      endgroup
      group contact ,a
        name        ,a30
        group address ,a
          street    ,a40
          zip       ,d10
        endgroup
      endgroup
    endgroup

the following paths are valid:

contact.name
contact.address.street
customer[5].bldg.address.street
client.accnt
inhouse.accnt
inhouse.name

while the following paths are invalid because they are not unique:

name
customer[1].name
address.street
accnt

If you specify one of these paths, the compiler generates a “Path specification is ambiguous” error (AMBIGUOUS).

group customer      ,a
    name            ,a30
    group address   ,a
      street        ,a40
      zip           ,d10
    endgroup
    group contact   ,a
      name          ,a30
      group address ,a
        street      ,a40
        zip         ,d10
      endgroup
    endgroup
endgroup

Because partial path names can access fields, the second address group’s street field can be referenced in any of the following ways:

customer.contact.address.street 
customer.contact.street 
contact.street 

The path specification

customer.address.street 

generates a “Path specification is ambiguous” compiler error, because it could reference either the first address group or the second. The only way to reference the data in the first address group is by ranging. See Ranged references for information.

group var1          ,a
    group and       ,d4
      var2          ,d4
    endgroup
endgroup

and you reference it with the following path:

var1.and.var2

the Synergy compiler interprets this reference as a path, not a Boolean expression. (To use it as a Boolean expression, add a space before and after the .AND. operator.)

Object paths

You can refer to the current instance of a class within the class using the this keyword. For example,

this.mymethod()

Path specifications that contain classes are resolved in the following order:

Real arrays

When referencing a real array, you must specify each declared dimension. For example, if you declare a variable as follows:

record
    brk         ,[3,4]d1

the references brk[1,2] and brk[2,2] are valid because each dimension is referenced.

In contrast, brk[1] is not valid, and the compiler generates an “Incorrect number of dimensions” error (INVNUMDIM), because it specifies only one of the two dimensions.

The reference brk[ ], however, is valid and refers to the entire scope, or contents, of the dimensioned array as a single element. The maximum size of a scope reference is 65,535. If the array is larger than 65,535 bytes, the scope size is modulo 65,535.

If your dimension specification is larger than the declared size of its corresponding array dimension, you can reference outside the defined area up to the end of the data area, except for class data fields and when -qstrict or -qcheck is specified. We recommend using -qcheck in all development environments and -qstrict for all production builds.

Here’s an example that references a real array:

record demo
    alpha       ,[3,2]d2 ,      12 ,34,
  &                             56 ,78,
  &                             98 ,76
    beta        ,[2,4]a3,       "JOE" ,"JIM" ,"TED" ,"SAM",
  &                             "LOU" ,"NED" ,"BOB" ,"DAN"

Data is referenced as follows:

Variable reference

Data obtained

alpha[1,2]

34

alpha[3,1]

98

alpha[3]

INVNUMDIM error

alpha[3,3]

JO

alpha[4,1]

JO

alpha[ ]

123456789876

beta[ ]

JOEJIMTEDSAMLOUNEDBOBDAN

beta[1,3]

TED

beta[2,4]

DAN

Variable references

You can specify variables in a simple, subscripted, or ranged form. Each form is described below. (This information also applies to all Synergex array classes: Synergex.SynergyDE.Collections.ArrayList, System.Collections.ArrayList, and System.Array.)

Simple references

A simple reference consists of the name of a data area, without any subscripting or range specifications. If it’s not defined as an array, the reference refers to the entire data area. Otherwise, the simple reference refers to the first element of the array or the element of the array at the specific index specified inside square brackets ([]) next to the variable name (i.e., variable_name[indexer]). In Synergy .NET, you can also use the square bracket format to access the indexer of any class that has an integer indexer method.

Here are some examples of simple references:

Subscripted references

A subscripted reference refers to an individual element within a list of like elements. The variable name is followed by the subscript value, which is enclosed in parentheses. The subscript value can be any numeric expression greater than zero and defines which element in the list is being accessed. For example, a subscript value of 1 represents the first element in the list.

Any variable reference can be subscripted, provided the data area is accessible to the routine. If the data area is inaccessible, or if the subscript value is less than one, an “Invalid subscript specified” error ($ERR_SUBSCR) is generated. Note that you cannot subscript beyond the defined size of class data fields and records or when the -qcheck compiler option is specified.

To understand how subscripted variables work, consider the following example.

Assume the following data division statements:

record demo
    alpha               ,3d4,           3, 9876, 4321
    beta                ,a6,            "ABCDEF"
    gamma               ,d3,            545
    delta               ,4a2,           "LM", "NP", "RS" ,"TV"
    episilon            ,3d3.2,         6.75, 1.23, 8.00
    group theta         ,[3]a
      one                ,d3,           123
      two                ,a3,           "abc"
    endgroup

Data is allocated as follows (shaded boxes are not part of the data space):

Variable

Data area (characters)

alpha(1)

0

0

0

3

 

 

alpha(2)

9

8

7

6

 

 

alpha(3)

4

3

2

1

 

 

beta

A

B

C

D

E

F

gamma

5

4

5

 

 

 

delta(1)

L

M

 

 

 

 

delta(2)

N

P

 

 

 

 

delta(3)

R

S

 

 

 

 

delta(4)

T

V

 

 

 

 

epsilon(1)

6

7

5

 

 

 

epsilon(2)

1

2

3

 

 

 

epsilon(3)

8

0

0

 

 

 

theta[1].one

1

2

3

 

 

 

theta[1].two

a

b

c

 

 

 

theta[2].one

1

2

3

 

 

 

theta[2].two

a

b

c

 

 

 

theta[3].one

1

2

3

 

 

 

theta[3].two

a

b

c

 

 

 

Here are some sample variable references:

Variable reference

Data obtained

Explanation

demo

000398764321ABCDEF545LMNPRSTV675123800123abc123abc123abc

Refers to the entire data area.

alpha

0003

Refers to the first element of the array.

alpha(1)

0003

Refers to the first element of the array.

alpha(3)

4321

Refers to the third element of the array.

alpha(4)

ABCD

Refers to the fourth group of four characters after the beginning of alpha’s data area (because a single alpha data item is four characters).

alpha(5)

EF54

Refers to the fifth group of four characters after the beginning of alpha’s data area.

beta(2)

545LMN

Refers to the second group of six characters after the beginning beta’s data area (because a single beta data item is six characters).

gamma
(alpha(1))

PRS

Refers to the third group of three characters after the beginning of gamma’s data area (because the variable alpha(1) has a value of 3 and a single gamma data item is three characters).

delta(4)

TV

Refers to the fourth element of the array.

delta(-3)

$ERR_SUBSCR

The subscript value is less than one.

epsilon(3)

8.00

Refers to the third element of the array. (The decimal point is shown here for clarity; it is not stored in the data area.)

epsilon(4)

123

Refers to the fourth group of three characters after the beginning of epsilon’s data area.

theta[1].two(2)

123

Refers to the second set of three characters after the first array element in the group.

theta[3].two(2)

$ERR_SUBSCR

Refers to data outside of the data area accessible to the program.

Alpha(4) and alpha(5) are both valid references because they don’t extend beyond the total data space allocated by the data division statements. Theta[3].two(2), on the other hand, attempts to refer past the end of the data area, which is not possible.

Notice that beta and gamma can be subscripted even though they are simple variable references.

Ranged references

A ranged reference is a variable reference followed by a range specification, either in absolute or relative form, that is enclosed in parentheses. In either case, the specification indicates starting and ending character positions relative to the beginning of the variable’s data space. The ranged variable’s value is the sequence of characters between the starting and ending positions, inclusive. If the range in a variable reference goes beyond the first variable, Synergy DBL continues to the next variable to obtain data.

You can range real arrays. Here’s an example:

brk[1,2](1,23)

You cannot range subscripted arrays. The following generates an error:

array(4)(1,23)

If the variable being ranged is implied-decimal, it is interpreted as decimal. Note that you cannot range beyond the defined size of class data fields and records or when the -qcheck compiler option is specified.

Absolute ranging

The absolute form of a range specification indicates the starting and ending positions of a character sequence using two numeric expressions separated by a comma.

Absolute ranging has the following format:

variable(start_pos,end_pos)

Here’s an example:

record abs
    alpha               ,d8,            10203405
    beta                ,a13,           "ABCDEFGHIJKLM"
    gamma               ,[3,2]a3,       "ABC", "DEF",
  &                                     "GHI", "JKL",
  &                                     "MNO", "PQR"
    group theta         ,[3]a
      one               ,d3,            123
      two               ,a3,            "abc"
    endgroup

Variable reference

Data obtained

alpha(2,4)

020

alpha(8,13)

5ABCDE

beta(3,6)

CDEF

beta(alpha(2,3),alpha(7,8))

BCDE

beta(alpha(2,3)+2,5)

DE

beta(13,14)

MA

gamma[1,2](2,3)

EF

gamma[2,2](3,6)

LMNO

alpha(6,3)

$ERR_SUBSCR

theta[1].two(2,8)

bc123ab

Note that the ability to access characters that extend past (or in front of) the specified field has been deprecated. For backward compatibility, the Synergy Runtime will continue to support this type of access. However, we recommend that you compile and run with -qcheck and make the appropriate changes to avoid future memory access violations.

Relative ranging

The relative form of a range specification indicates the starting or ending character position and length of a character sequence range using two numeric expressions separated by a colon. The value that is referenced depends on the sign of the length. For positive lengths, the specified position is the starting point, and the value is the character sequence of the specified length that begins at that position. For negative lengths, the position is the ending point, and the value is the character sequence that begins the specified number of characters before that position.

Relative ranging has the following format:

variable(position:length)

Here’s an example of a data division:

record abs
    alpha       ,d8,            10203405
    beta        ,a13,           "ABCDEFGHIJKLM"
    gamma       ,[3,2]a3,       "ABC", "DEF",
  &                             "GHI", "JKL",
  &                             "MNO", "PQR"
    group theta         ,[3]a
      one       ,d3,    123
      two       ,a3,    "abc"
    endgroup 

Variable reference

Data obtained

alpha(3:1)

2

alpha(3:2)

20

alpha(6:-2)

34

beta(13:2)

MA

gamma[1,2](1:2)

DE

gamma[1,1](1:12)

ABCDEFGHIJKL

gamma[3,2](1:12)

PQR123abc123

beta(2:-15)

$ERR_SUBSCR

theta[2].one(3:10)

3abc123abc

Note that the ability to access characters that extend past (or in front of) the specified field is deprecated. For backward compatibility, the Synergy Runtime will continue to support this type of access. However, we recommend that you compile and run with -qcheck and make the appropriate changes to avoid future memory access violations.