ABAP Syntax

«« Previous
Next »»

The following sections describe the syntax of ABAP:

1. ABAP statements 

ABAP statements consist of the following tokens and end with a period (.).

◉ ABAP words
◉ Operands
◉ Operators

Certain ABAP words, operands, and operators form

◉ expressions,

which can be specified at certain operand positions.

The tokens of a statement must be separated by at least one blank or a line break. Otherwise, blanks and line breaks between tokens are not significant. An ABAP statement is not restricted to a line in the source code.

No distinction is made between upper and lowercase letters. Apart from ABAP words, operands and operators, the following special characters can also be used:

◉ If a number of expressions of the same type with operators are joined as an expression, the priority of the individual operations can be defined using parentheses (()).
◉ For the purpose of calling functions and methods, parentheses (()) can sometimes be used.
◉ Lists of operands are expressed by parentheses (()) and commas (,) in certain positions.
◉ When forming a chained statement, a colon (:) and commas (,) can be used.

A number of standalone special characters, such as parentheses for setting the priority, need to be separated from other tokens using a blank. Other special characters (as well as the period at the end) do not have to be separated by a blank.

Notes

◉ Obsolete syntax forms can still occur in all objects apart from classes. In such cases, the separators between the tokens can be omitted.
◉ The absolute maximum length of an ABAP statement is 128 x 1024 characters = 131072 characters. However, the actual maximum number of characters in a statement also depends on the number of tokens and the use of literals. A statement usually consists of almost 130,000 characters. In chained statements, however, it is only a maximum of 28400 characters per statement.

Example

ABAP statement with the keyword DELETE, the addition WHERE, the operators =, <, >, AND, OR, the operands itab, col1, op1, col2, op2, col3, op3, parentheses.

DELETE itab
  WHERE ( col1 = op1 AND ( col2 > op2 OR col3 < op3 ) ).

1.1 ABAP Words

ABAP words are the vocabulary of the ABAP language. ABAP statements are composed of ABAP words, operands, and operators according to defined syntax rules. ABAP words are taken from the English language and are grouped into ABAP language elements and ABAP language element additions that express the semantics of a statement. In addition to letters, ABAP words can also contain hyphens (-) to form multi-word expressions. As well as ABAP words, some operators are also made up of letters.

If a statement is introduced using an ABAP word, the word is an ABAP keyword. The remaining ABAP words are additions of a keyword. A single ABAP word can be used both as a keyword and as a non-keyword. For example, DATA is used as a keyword as well as an addition of other keywords. Not all statements are introduced using a keyword or contain ABAP words. Assignments with the assignment operator = or method calls, for example, do not contain a keyword and do have to contain any other ABAP word.

ABAP words are not reserved names as in some programming languages. Although the use of an ABAP word for naming conventions is not forbidden, it should be avoided if possible. Even if this rule is followed, the introduction of new elements can cause similar situations and therefore suitable naming conventions should be observed for reserved names to avoid conflicts with language elements.

1.2 Operands

Typical operands are:

◉ Data objects from the same ABAP program 

Data objects in operand positions are modified ( writer positions) or read ( reader positions).

◉ Functions and expressions 

In many reader positions (and in some writer positions), functions and expressions can be specified instead of data objects. In these cases, the statement works with the return value of the function or the result of the expression.

◉ Types from the same program or the repository 

Types such as data types, classes, or interfaces are specified in declarations, typings, or when addressing components.

◉ Callable units from the same program or the repository 

Call units such as ABAP programs, procedures, or dynpros are called during the execution of the statement.


◈ Names for Individual Operands


An individual operand, meaning an operand that is not an expression, can be elementary or made up of components. Composite operands are:

◈ Structured data types or data objects (structure)
◈ Instances of classes (objects)
◈ Classes
◈ Interfaces

Accordingly, names for operands are either elementary names or names constructed from multiple names separated by component selectors. An elementary name is used for addressing:

◈ elementary operands
◈ components that are unique in the current context
◈ superunits made up of components

Naming conventions apply to the elementary names. Composite names with component selectors are used for addressing individual components. A component can itself be a superunit of further components. Subcomponents can be addressed by chaining multiple names.

Note: As well as the component selectors listed here, Open SQL has a column selector (~).

- - Structure Component Selector

A component comp of a structured data type or a structure struct is accessed using the name

struct-comp

In this case, the character - is the structure component selector. A structured data type or a structure struct must be specified as follows on the left of the structure component selector:

◈ Name of a structure or a structured type (which can itself be composite).
◈ Functional method call or method chaining with a structured result.
◈ Single or chained table expression that returns a structured table row.

The name comp of the component must be on the right of the structure component selector.

Example

Declares a structure struc with the structured data type spfli from ABAP Dictionary and accesses its component carrid.

DATA struc TYPE spfli.

...

... struc-carrid ...

- - Object Component Selector 

A component comp of an object is accessed using the name

ref->comp

In this case, the character -> is the object component selector. A reference variable ref must be specified on the left of the object component selector as follows

◈ Name of a reference variable (can itself be a composite).
◈ Functional method call or method chaining with reference variable as a result.
◈ Single or chained table expression whose result is a reference variable.
◈ Constructor expression with the instance operator NEW or the casting operator CAST.

The name comp of the component must be on the right of the object component selector. If an attempt is made to access an object component with a reference variable that contains the null reference, a non-handleable exception is raised. Dereferencing of a data reference in the statement ASSIGN is an exception to this.

The object component selector dereferences the reference variable ref and makes the components of the referenced object accessible.

◈ If ref is an object reference variable, the components comp of the object (attributes and methods) to which the object reference variable points are addressed using the object component selector.
◈ If ref is a data reference variable that is typed as a structure, the components comp of the structure to which the data reference variable points are addressed using the object component selector.

Note

If ref is a data reference variable, the character * can be specified after the object component selector ->. This creates the general dereferencing operator ->*. The expression ref->* names the entire data object to which the data reference variable points. The dereferencing operator is the only way to dereference data references. In the case of untyped data reference variables, this was only possible using the statement ASSIGN. The dereferencing operator cannot be specified after object reference variables. The instance components of classes can only be accessed using the expression ref->comp.

Example

Accesses the public attribute a1 of a class c1 by using the object reference variable oref.

CLASS c1 DEFINITION.
  PUBLIC SECTION.
    DATA a1 TYPE string READ-ONLY.
ENDCLASS.

...

DATA oref TYPE REF TO c1.

... oref->a1 ...

Example

The data reference variable dref is typed as a structure and the component carrid of the referenced structure is accessed using the object component selector. The expression dref->carrid has the same meaning as the chaining dref->*-carrid.

DATA dref TYPE REF TO sflight.

...

... dref->carrid ...

- - Class Component Selector 

A static component comp of a class can be accessed using the name

class=>comp

In this case, no instance of the class needs to be created. The characters => are the class component selector. The name class of a class must be on the left of the class component selector. The name comp of the component must be on the right of the class component selector.

The class component selector can also be used to access the data types and constants of an interface.

intf=>type, intf=>const

The name intf of an interface must be on the left of the class component sector. The name type of a data type defined using TYPES or the name const of a constant defined using CONSTANTS must be on the right of the object component selector.

Note

It is also possible to access the static components of a class using the object component selector if an instance of the class was created.

Example

Declares a class factory and accesses its static attribute oref.

CLASS factory DEFINITION CREATE PRIVATE.
  PUBLIC SECTION.
    CLASS-DATA oref TYPE REF TO factory.
    CLASS-METHODS class_constructor.
    METHODS do_something.
ENDCLASS.

...

factory=>oref->do_something( ).

...

CLASS factory IMPLEMENTATION.
  METHOD class_constructor.
    CREATE OBJECT oref.
  ENDMETHOD.
  METHOD do_something.
    ...
  ENDMETHOD.
ENDCLASS.

- - Interface Component Selector 

A component comp of an interface is accessed using the name

intf~comp

In this case, the character ~ is the interface component selector. The name intf of an interface must be on the left of the interface component selector. The name comp of the component must be on the right of the object component selector.

The name intf~comp identifies the components of interfaces in classes or component interfaces in composite interfaces.

Note

An interface contains each component exactly once, regardless of how it is composed of component interfaces. All the interface components are at the same hierarchical level. The name of an interface component is uniquely defined using intf~comp. intf is always the interface in which the component is declared. A direct chaining of interface names intf1~...~intfn~comp is not possible.

Example

Declaration of interfaces and access to their components.

INTERFACE i1.
  TYPES t1 TYPE string.
ENDINTERFACE.

INTERFACE i2.
  INTERFACES i1.
  METHODS m2 IMPORTING p1 TYPE i1~t1.
ENDINTERFACE.

CLASS c1 DEFINITION.
  PUBLIC SECTION.
    INTERFACES i2.
ENDCLASS.

...
DATA oref TYPE REF TO c1.

oref->i2~m2( ... ).

...

CLASS c1 IMPLEMENTATION.
  METHOD i2~m2.
    ...
  ENDMETHOD.
ENDCLASS.

- - Chainings 

Whenever operands are grouped together from components, which themselves contain components, the names of these components are composed from chains with multiple component selectors. The following rules apply to these chained names:

◈ The names on the left of each structure component selector must, as a combined group, address a structured data type or a structure.
◈ The names on the left of each object component selector must, as a combined group, address a reference variable.
◈ The class component selector can occur in a name exactly once as the first selector.
◈ The interface component selector can only occur more than once in a name if other component selectors are specified between the individual interface component selectors.

Note

The following chainings are possible alongside chainings or names:

◈ Method chainings with the object component selector
◈ Chainings of table expressions

Chainings can be combined in any way as long as their rules are respected.

Example

Declares a nested structured data type struc2 in struc1 and a structure struc3 in an interface i1.

The component comp of struc3 is a data reference variable of the static type struc1. The i1 interface is the component interface of i2 and the latter is implemented in c1. In c2, a static attribute is declared as the object reference of the static type c1. The expression in the last line can be at an operand position that expects a data object, and names the component comp of the structure struc2 in a chaining that starts at class c2. A prerequisite for use of the expression is that both reference variables, oref and dref, point to the respective instances.

INTERFACE i1.
  TYPES: BEGIN OF struc1,
           ...
           BEGIN OF struc2,
             ...,
             comp TYPE ...,
             ...,
           END OF struc2,
           ...
         END OF struc1.
  DATA: BEGIN OF struc3,
          ...
          dref TYPE REF TO struc1,
          ...
        END OF struc3.
ENDINTERFACE.

INTERFACE i2.
  INTERFACES i1.
ENDINTERFACE.

CLASS c1 DEFINITION.
  PUBLIC SECTION.
    INTERFACES i2.
ENDCLASS.

CLASS c2 DEFINITION.
  PUBLIC SECTION.
    CLASS-DATA oref TYPE REF TO c1.
ENDCLASS.

...

... c2=>oref->i1~struc3-dref->struc2-comp ...

◈ Escape Character for Names


The character ! can be written directly before a name to distinguish it from an ABAP word with the same name in a statement. With the exception of the first word, each word of a statement that is preceded by the escape character is interpreted as an operand, and not as an ABAP word, when the program is generated. The escape character itself is not part of a name and is ignored when the statement is executed.

Note

The escape character may be required on rare occasions in which the compiler cannot tell the difference between an operand and a reserved word of the same name. Otherwise, it can be used for the documentation of operands in the source code.

Example

Without the escape character ! before CHANGING after USING, the following program extract would have incorrect syntax, because a formal parameter must be entered after USING. Although the second escape character is not necessary, it is used to document USING after CHANGING as a formal parameter.

FORM test USING !CHANGING
          CHANGING !USING.
  using = changing.
ENDFORM.

◈ Specifying Individual Operands


There are three ways to specify the names of operands:

1. Specifying Names Statically

The name of the operand must be specified directly. If the name of a data object is specified, the specified name is used and not the content of the data object.

Example

SUBMIT report.

2. Specifying Names Dynamically in Parentheses

For some statements that are designed to be specified statically, there is a syntax form that allows the name of a character-like data object to be specified in parentheses in the operand position. At the time of execution, the data object must contain the actual name of the operand.

Example

SUBMIT (dobj).

For statements that contain lists of operands or whole parts of statements, an internal table with a character-like row type can often be specified in parentheses. The table rows must then contain the names of the individual operands.

Example

SELECT ... WHERE (where_tab).

3. Specifying Names Dynamically

In many operand positions, the system expects character-like data objects that contain the actual names of the individual operands at the time of execution. To enable these operands tp be specified statically, literals must be used.

Example

CALL FUNCTION dobj.

Note

In some rare cases, there may be exceptions to these rules, where operands must be set in parentheses or quotation marks as literals, but no data objects can be specified. This is noted in the corresponding syntax descriptions.

◈ Operand Type


An operand position is typed using an operand type, which is complete or generic and can also be dependent on other operand positions, as is the case for statements, for example. When a statement is executed, an operand with a suitable data type is expected. If a data object specified at an operand position has a different data type than the operand type, an attempt is usually made to convert the content of the data object to the operand type on the basis of the conversion rules in writing positions, and in the other direction in reading positions. Note that every conversion leads to a longer runtime. If no appropriate conversion rules have been defined, or the content cannot be converted, a syntax error occurs or an exception is raised. Deviations from this rule, for example that the data object must exactly match the operand type, or the data object is to be interpreted as an operand type, regardless of its actual type (casting), are described in the individual statements.

1. Operand Positions for Elementary Data Objects

For operand positions for elementary data objects, the following must be specified when the statement is executed, depending on the operand type:

◈ character-like data objects
◈ numeric data objects
◈ byte-like data objects

Generic, typed formal parameters or field symbols can also be specified statically if they are typed more generally than the expected type.

Flat structures with only character-like components of the types c, n, d, or t can also be used in all operand positions that expect elementary fields.. Structures like this are handled in the same way as a single data object of type c (implicit casting).

2. Operand Positions for Structures

Structures must be specified at operand positions for structures when the statement is executed. Formal parameters or field symbols of generic type data or any can also be specified statically.

3. Operand Positions for Internal Tables

Internal tables must be specified at operand positions for internal tables (statically identifiable and when the statement is executed). Generic formal parameters and field symbols can only be specified if they are typed with at least the generic type any table. Only index tables can be specified at operand positions that include index access, and generic formal parameters and field symbols must be typed with at least the generic type index table.

4. Operand Positions for Reference Variables

Internal tables must be specified at operand positions for internal tables (statically identifiable and when the statement is executed). Generic formal parameters and field symbols can only be specified if they are typed with at least the generic type any table. Only index tables can be specified at operand positions that include index access, and generic formal parameters and field symbols must be typed with at least the generic type index table.

◈ Data Objects in Operand Positions


For data objects in operand positions, you must distinguish between read and write positions. The data type and content of the specified data objects must also be appropriate for the operand position.

1. Read positions

In a reading position, the content of an operand is only read, and not changed, when the statement is executed. Data objects can be specified as followed in reading positions:

◾ As a literal.

◾ As a data object visible at this point using a name dobj, a field symbol <fs>, or a data reference dref->* dereferenced using the dereferencing operator ->* (providing dref is specified in full).

Here, the names of data objects also include any text symbols specified using

... text-idf ...,

where idf is the three character ID of the text symbol, or chainings of reference variables. If a field symbol is used, it must be assigned to a memory area and a data reference must point to a data object. Otherwise a non-handleable exception is raised. As an alternative to specifying a text symbol using text-idf, the three-character code of a text symbol can be appended to the text field literal in parentheses:

... '...'(idf) ...

◾ If the text symbol exists in the currently loaded text pool, the content of the text symbol is used instead of the text field literal, otherwise the literal is used.
If the data object is an internal table, the expressions dobj[], <fs>[], or dref->*[] can also be used. An exception to this is when specifying the internal table of a table expression, where [] cannot be appended to the name. In the case of dobj[], this ensures that the table body is addressed and no header lines. If an internal table does not have a header line, its simple name dobj (without []) is interpreted as the table body at all operand positions. However, if an internal table does have a header line, its simple name dobj (without []) is interpreted as the header line and not the table body at almost all operand positions. The operand positions in which the name of an internal table with a header line is interpreted as the internal table are specified under internal tables with headers.

◾ As a subarea of a character-like or byte-like data object (or a character-like initial part of a structure) by specifying an offset/length.

◾ In some positions, number values must be specified directly as digits, although it is often not possible to specify a sign (which is not the case with numeric literals). Examples are numbers specified in declarative statements for the length of elementary data objects or for the initial memory requirements of internal tables.

Notes

◾ Text symbols cannot be specified in all reading positions. For example, they are not permitted for specifying the target of dynamic executions.
◾ A system field should only be specified as an operand in a reading position if its content is not set by the same statement, since otherwise undefined behavior may occur.
◾ The predicate expressions IS ASSIGNED and IS BOUND can be used to check whether field symbols or data references.
◾ A data reference variable with a generic static type can only be deserialized using the statement ASSIGN dref->* TO <fs>.
◾ In many reading positions, functions or expressions can be specified as well as data objects.

2. Write positions

In a writer position, the content of the operand is changed when the statement is executed. Only modifiable data objects (that is, no literals, text symbols, constants, or non-modifiable formal parameters) can be specified as follows in writer positions:

◾ A visible data object specified at this place using a name dobj, a field symbol <fs>, or a dereferenced data reference dref->* (if dref is typed in full). Similar to reader positions, [] can be appended for internal tables, to address the table body.
◾ A subarea of a flat character-like or byte-like data object specified, using an offset/length. An offset or length cannot be specified in writer positions for data objects of the deep data types string and xstring.
◾ In a declaration position, an inline declaration of a data object or field symbol can be made using a declaration expression.
◾ Writable expressions can be specified in a result position.

Writer-only positions, where an operand is overwritten without being read, and writer positions where an operand is read and written are both available.

Note: Certain expressions can also be specified in some writer positions.

3. Subfield access

In operand positions, subareas of certain data objects can be accessed by specifying an offset/length:

Syntax

dobj[+off][(len)]

<fs>[+off][(len)]

dref->*[+off][(len)]

Effect

A specified offset or length is directly appended to either the dobj descriptor of the data object, an <fs> field symbol, or a dereferenced data reference variable dref->*: Offsets/lengths can be specified for:

◾ Elementary byte-like data objects
◾ Elementary character-like data objects
◾ Flat structures where one of the following prerequisites must be met:
    ◾ The structure contains flat character-like components only.
    ◾ The first fragment of the structure fragment view is flat and character-like, and the substring addressed by specifying the offset and length is located within this fragment.

The following restrictions apply:

◾ In write positions, only flat data objects are permitted; it is not possible to write to substrings of strings.
◾ Access to substrings of strings is also not possible in the following reading positions:
    ◾ dobj[+off][(len)] specified as a memory area mem_area of the statement ASSIGN.
    ◾ dobj[+off][(len)] specified as an argument of the statement GET REFERENCE or the reference operator REF.
    ◾ dobj[+off][(len)] specified as an actual parameter for input parameters in calls of methods, function modules, and subroutines.
◾ Offsets/lengths cannot be specified for literals or text symbols.
◾ In the case of dynamically specified operands in parentheses, no lengths can be specified.
◾ A dereferenced data reference variable dref->* must be typed in full.
◾ For a writable expression, offsets/lengths cannot be specified as memory areas in the statement ASSIGN or as arguments of the reference operator REF (table expressions only).

The segment of the data object is used that has the offset specified in off and the length (in characters or bytes) specified in len. A memory area must not be addressed outside the field boundaries, except in the case of the statement ASSIGN. For an offset specified without a length, the entire substring is addressed from off characters; for a length specified without an offset, the first len characters are addressed (different rules apply to the statement ASSIGN).

The operands off and len expect data objects of the type i. These data objects must contain positive integers, with the following exceptions.

◾ The length 0 can be specified for strings.
◾ A negative offset (but never length 0) can be specified if an <fs> field symbol is specified in the statement ASSIGN for dobj.
◾ If off is less than the length of dobj, an asterisk (*) can be specified for len. The upper limit of dobj then determines the upper limit of the memory area.

If the prerequisites are not met or if the subarea defined by off and len is not completely contained in the data object (except in the case of ASSIGN), a syntax error occurs (if statically identifiable). Otherwise, an exception of class CX_SY_RANGE_OUT_OF_BOUNDS is raised. If off is specified as a numeric literal, this literal cannot be prefixed with a sign.

The offset and length specified are counted in characters for character-like data objects and in bytes for all other data objects.

A substring specified by an offset or length is handled like a data object of the specified length for which the data type depends on the data type of the original data object, the field symbol, or the data reference variable, as shown below:

Original Data Type Data Type of Substring
c c
string  string 
xstring  xstring 
Structure type  c

If the length of the substring exactly corresponds to the length of the structure in a substring access to a structure, the substring does not have data type c; instead, it is handled like the structure itself.

Notes

◉ For reads on substrings of character-like data objects, predefined substring functions that allow searches by specifying both substring and offset/lengths are available.

◉ It is a good idea to specify offsets with the value 0 explicitly too (that is, dobj+0(len) instead of dobj(len)). This distinguishes a substring access in the source code clearly from other language constructs that also use parentheses, such as dynamic specifications, method calls, or inline declarations.

◉ dobj+0(*), dobj+0, or dobj(*) are always interpreted as dobj. In this case, dobj can also be a data object where substring access according to the rules above is not possible.

◉ No substring access cnt(len), sum(len) can be performed on data objects called cnt and sum unless an offset is specified explicitly. The compiler always interprets this as a number or sum of a field len in the control level processing of an extract dataset.
◉ Obsolete syntax forms can still occur with substring access (apart from with classes).

◉ The statement MOVE PERCENTAGE indicates an obsolete form of substring access.

Example

The following structure has both character-like and non-character-like components:

DATA: 
  BEGIN OF struc, 
    a TYPE c LENGTH 3,    "Length 3 characters 
    b TYPE n LENGTH 4,    "Length 4 characters 
    c TYPE d,             "Length 8 characters 
    d TYPE t,             "Length 6 characters 
    e TYPE decfloat16,    "Length 8 bytes 
    f TYPE c LENGTH 28,   "Length 28 characters 
    g TYPE x LENGTH 2,    "Length 2 bytes 
  END OF struc.

The fragment view splits the structure into five areas, F1 - F5.

[ aaa | bbbb | cccccccc | ddd | AAA | eeee | fffffffffffff | gg ] 
[            F1               |  F2 |  F3  |       F4      | F5 ]

Offset/length accesses are possible on the character-like initial fragment F1 only, for example struc(21) or struc+7(14). An access such as struc+57(2), for example, is not permitted.

Substrings

This example demonstrates how substrings can be accessed.

Source Code

REPORT demo_data_process_fields.

CLASS demo DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS main.
ENDCLASS.

CLASS demo IMPLEMENTATION.
  METHOD main.
    DATA time TYPE t VALUE '172545'.

    DATA: f1(8)  TYPE c VALUE 'ABCDEFGH',
          f2(20) TYPE c VALUE '12345678901234567890'.

    DATA: f3(8) TYPE c VALUE 'ABCDEFGH',
          f4(8) TYPE c.
    DATA: o     TYPE i VALUE 2,
          l     TYPE i VALUE 4.

    DATA: string(20) TYPE c,
          number(8)  TYPE c VALUE '123456',
          offset     TYPE i VALUE 8,
          length     TYPE i VALUE 12.

    DATA(out) = cl_demo_output=>new(
      )->begin_section( |Example 1|
      )->write( time
      )->write( time+2(2)
      )->write( time+2(4) ).
    CLEAR time+2(4).
    out->write( time ).

    out->next_section( |Example 2| ).
    f2+6(5) = f1+3(5).
    out->write( f1
      )->write( f2 ).

    out->next_section( |Example 3| ).
    f4 = f3.
    out->write( f4 ).
    f4 = f3+o(l).
    out->write( f4 ).
    f4+o(l) = f3.
    out->write( f4 ).
    CLEAR f4.
    f4+o(l) = f3.
    out->write( f4 ).
    f4+o(l) = f3+o(l).
    out->write( f4 ).

    out->next_section( |Example 4| ).
    WRITE number(6) TO string+offset(length) LEFT-JUSTIFIED.
    out->write( string ).
    CLEAR string.
    WRITE number(6) TO string+offset(length) CENTERED.
    out->write( string ).
    CLEAR string.
    WRITE number TO string+offset(length) RIGHT-JUSTIFIED.
    out->display( string ).
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  demo=>main( ).

Description


In the first part, the minutes of a time field are selected by specifying an offset. Then the minutes and seconds are set to their initial values by specifying an offset in the CLEAR statement.

In the second part, the five character sequence 78901 from the field f2 is replaced with DEFGH from f1 by specifying offsets and lengths.

In the third part, assignments are used. First, the content of f1 is assigned to f2 without offsets. This is repeated with offsets and lengths for f1. The next three assignments overwrite the content of f2 with an offset of 2. Note that f2 is padded on the right with blanks, in accordance with the conversion rules for source type c.

In part four, the WRITE TO statement is used. The first six positions of the field number are written left-justified, centered, and right-justified into the last 12 positions of the string field.

◈ Functions and Expressions in Operand Positions


Functions and expressions can be specified in certain reading positions.

1. Functions and Expressions for Operand Positions

- Writing Positions
- Reading Positions

Writing Positions

Expressions that can be specified in writing positions are
  • Declaration expressions
    • ... DATA(...) ...
    • ... FIELD-SYMBOL(...) ...
  • Writable expressions
    • The constructor expressions NEW class( ... )->attr and CAST type( ... )->dobj
    • Table expressions itab[ ... ] and their chainings
Reading Positions

◉ Functions that can be specified in reading positions are

◈ Predefined functions 

... func( arg ) ...
... func( val = arg p1 = arg1 p2 = arg2 ... ) ...

◈ Functional methods 

... meth( ) ...
... meth( a ) ...
... meth( p1 = a1 p2 = a2 ... ) ...
... meth( [EXPORTING  p1 = a1 p2 = a2 ...]
          [IMPORTING  p1 = a1 p2 = a2 ...]
          [CHANGING   p1 = a1 p2 = a2 ...] ) ...

◈ Method chaining 

Chained method call:

... ...->meth1( ... )->meth2( ... )->...->meth( ... ) ...

Chained attribute access:

... ...->meth1( ... )->meth2( ... )->...->attr ...

◉ Expressions that can be specified in reading positions are 

Calculation expressions:

◈ Arithmetic expressions

... arith_exp ...

◈ Bit expressions

... bit_exp ...

◈ String expressions

... string_exp ...

Constructor expressions:

◈ Instance operator

NEW

◈ Value operator

VALUE

◈ Conversion operator

CONV

◈ Component operator

CORRESPONDING

◈ Casting operator

CAST

◈ Reference operator

REF

◈ Lossless operator

EXACT

◈ Reduction operator

REDUCE

◈ Filter operator

FILTER

◈ Conditional operator

COND, SWITCH

Notes

◉ Functions with numeric return values and arithmetic expressions are combined in numeric expressions.
◉ Functions with character-like return values and string expressions are combined as character-like expressions.
◉ Functions with a byte-like return values and bit expressions are combined as byte-like expressions.

Example

Numeric expression as an index specified for an internal table.

DATA: itab TYPE STANDARD TABLE OF i,
      wa   LIKE LINE OF itab,
      n    TYPE i.

...

READ TABLE itab INDEX lines( itab ) - n
                INTO wa.

2. Operand Positions for Functions and Expressions

2.1 Writer Positions for Functions and Expressions

⇨ Declaration Positions

Declaration positions are writing-only positions in which a declaration expression can be specified for an inline declaration. There are no declaration positions within expressions.

The following declaration positions are possible:

🔵 Positions for the inline declaration of variables with DATA(var). These are the following writing positions, where the operand type can be determined in full and where the content of the operand is completely overwritten but not evaluated.
Left side of an assignment with the assignment operator =

lhs = ...

● Actual parameters for output parameters and return values of methods for standalone method calls:

meth( IMPORTING p1 = a1 p2 = a2...
      RECEIVING r  =  a )

If a method call is on the right side of an assignment or is part of an expression, these actual parameters are not declaration positions.

● Target fields when catching an exception:

CATCH EXCEPTION INTO oref

CLEANUP INTO oref

● Target fields in statements for string processing and byte string processing:

FIND ... MATCH COUNT mcnt
         MATCH OFFSET moff
         MATCH LENGTH mlen
         RESULTS result_tab|result_wa
         SUBMATCHES s1 s2 ...

REPLACE  ... REPLACEMENT COUNT rcnt
            REPLACEMENT OFFSET moff
            REPLACEMENT LENGTH mlen
            RESULTS result_tab|result_wa

CONCATENATE ... INTO result

SPLIT ... INTO result1 result2 ...
          INTO TABLE result_tab

CONVERT TEXT ... INTO SORTABLE CODE hex

GET BIT ... INTO val.

● Target fields in statements for time stamps:

GET TIME STAMP time_stamp

CONVERT TIME STAMP ... INTO DATE dat TIME tim DAYLIGHT SAVING TIME dst

CONVERT ... INTO TIME STAMP time_stamp

● Target fields in statements for internal tables:

READ TABLE ... [REFERENCE] INTO dobj

LOOP AT ... [REFERENCE] INTO dobj

INSERT ... [REFERENCE] INTO dobj

COLLECT    ... [REFERENCE] INTO dobj

APPEND     ... [REFERENCE] INTO dobj

MODIFY ... [REFERENCE] INTO dobj

FIND ... IN TABLE MATCH COUNT mcnt
         IN TABLE MATCH LINE mlin
         IN TABLE MATCH OFFSET moff
         IN TABLE MATCH LENGTH mlen
         IN TABLE RESULTS result_tab|result_wa
         IN TABLE SUBMATCHES s1 s2 ...

REPLACE  ... IN TABLE REPLACEMENT COUNT rcnt
            IN TABLE REPLACEMENT LINE rlin
            IN TABLE REPLACEMENT OFFSET moff
            IN TABLE REPLACEMENT LENGTH mlen
         IN TABLE RESULTS result_tab|result_wa

● Target fields of the Open SQL statement SELECT

SELECT ... INTO (dobj1, dobj2, ... )

SELECT ... INTO wa

SELECT ... INTO TABLE itab

● Target fields of the statement DESCRIBE:

DESCRIBE FIELD ... TYPE typ [COMPONENTS com] LENGTH ilen DECIMALS dec
                   OUTPUT-LENGTH olen HELP-ID hlp EDIT MASK mask

DESCRIBE TABLE ... KIND knd LINES lin OCCURS n

DESCRIBE DISTANCE ... INTO dst

● Target fields of various GET statements:

GET PARAMETER ... FIELD dobj

GET PF-STATUS status

GET REFERENCE INTO dref

GET RUN TIME FIELD rtime

GET TIME FIELD tim

● Work area in statement for dynpros:

LOOP AT SCREEN ... INTO wa

● Target field for message output:

MESSAGE ... INTO text

● Target fields in file interface statements:

READ DATASET ... LENGTH alen

GET DATASET ... POSITION pos ATTRIBUTES attr

● Target field for a serialization:

CALL TRANSFORMATION ... RESULT XML rxml

● All writing positions used when generating programs:

GENERATE GENERATE SUBROUTINE POOL ... NAME prog error_handling

🔵 Positions for the inline declaration of field symbols with FIELD-SYMBOL(<fs>). These are all places where a memory area can be assigned to a field symbol.

● Field symbol in the statement ASSIGN:

ASSIGN... TO <fs>

● Field symbols in statements for internal tables:

READ TABLE ... ASSIGNING <fs>

LOOP AT ... ASSIGNING <fs>

INSERT ... ASSIGNING <fs>

COLLECT    ... ASSIGNING <fs>

APPEND     ... ASSIGNING <fs>

MODIFY ... ASSIGNING <fs>

⇨ Result Positions

Result positions are writer positions in which writable expressions can be specified. Writes are performed on the result of the expression. The following result positions are possible:

● Left side of an assignment with the assignment operator =
● Operand dobj of the statement CLEAR
● Memory area mem_area of the statement ASSIGN mem_area TO
● Structure struc of the statement ASSIGN COMPONENT comp OF STRUCTURE struc
● Actual parameter in method calls for output parameters, input/output parameters, and return values.
● The right side in the declaration of a local field symbol in a LET expression.

2.2 Reader Positions for Functions and Expressions

⇨ General Expression Positions 

General expression positions are reading positions in which suitable data objects, constructor expressions, table expressions, calculation expressions, predefined functions, or functional methods and method chainings can be specified. The following general expression positions exist:
  • Right side of an assignment with the assignment operator =
  • Operands of arithmetic expressions and of bit expressions,
  • Embedded expressions in string templates,
  • Operands of comparison expressions in logical expressions
  • Operand of the statement CASE,
  • Actual parameters for input parameters of methods in meth( ... ), RAISE EVENT, CREATE OBJECT, and RAISE EXCEPTION or THROW in a conditional expression.
  • Actual parameters for input parameters of function modules in the case of CALL FUNCTION.
  • Arguments of predefined numeric functions if they are themselves executed in an arithmetic expression.
  • The operands behind the addition WITH TABLE KEY of the statements READ TABLE itab and DELETE TABLE itab.
  • The operands behind the addition WITH KEY of the statement READ TABLE itab.
  • Work area wa of the statements
    • APPEND wa TO ...
    • INSERT wa INTO ...
    • MODIFY ... FROM wa ...
  • Expression exp for dynamic sorts in the case of
    • SORT itab BY exp
  • Source fields of the statements WRITE and WRITE TO, with the restriction that arithmetic expressions and bit expressions cannot be specified directly, only as embedded expressions in string templates.
The type restrictions defined by the operand type apply in the operand positions. For example, no numeric functions can be specified in a bit expression.

Notes

◾ Specifying functional methods as actual parameters of methods enables the nesting of method calls in an operand position.
◾ The three types of calculation expression can be executed as operands of relational expressions, but they cannot be mixed in one calculation expression.

⇨ Numeric Expression Positions 

Numerical expression positions are reader positions in which numeric data objects, arithmetic expressions, and predefined functions, or functional methods and method chainings whose return value has a numeric data type, can be specified. The following numeric expression positions exist:
  • Arguments of functions
    • Numeric arguments of string functions
    • Numeric arguments of extremum functions
  • Counters and positions:
    • Operand comp of the statement 
      • ASSIGN COMPONENT comp OF STRUCTURE
    • Operand n of the statement 
      • DO n TIMES
    • Operand sec of the statement 
      • WAIT UP TO sec SECONDS
    • Operand num of the statement 
      • SHIFT ... BY num PLACES
    • Operands bitpos and val of the statement 
      • SET BIT bitpos ... TO val.
    • Operand bitpos of the statement 
      • GET BIT bitpos ....
  • Positions specified in the statements FIND and REPLACE:
    • Operands off and len of the statements 
      • FIND ... IN SECTION ... OF 
      • REPLACE  ... IN SECTION ... OF
    • Operands lin1, off1, lin2, and off2 of the statements 
      • FIND ... IN TABLE ... FROM lin1 OFFSET off1 TO lin2 OFFSET off2 ... 
      • REPLACE  ... IN TABLE ... FROM lin1 OFFSET off1 TO lin2 OFFSET off2 ...
    • Operands off and len of the statement 
      • REPLACE SECTION OFFSET off LENGTH len OF ...
  • The row number idx specified with respect to a table index when accessing an internal table in:
    • READ TABLE itab INDEX idx ...
    • LOOP AT itab ...FROM idx1 TO idx2 ...
    • INSERT itab ... INDEX idx ...
    • INSERT LINES OF jtab FROM idx1 TO idx2  ...
    • APPEND LINES OF jtab FROM idx1 TO idx2  ...
    • MODIFY itab INDEX idx  ...
    • DELETE itab INDEX idx  ...
    • DELETE itab FROM idx1 TO idx2 ...
⇨ Character-Like Expression Positions 

Character-like expression positions are reading positions in which character-like data objects, string expressions, and predefined functions, or functional methods and method chainings whose return value has a character-like data type, can be specified. The following character-like expression positions exist:

◆ Operand positions in string expressions
◆ Character-like arguments in processing functions
◆ Character-like arguments in description functions
◆ Operand comp of the statement
ASSIGN COMPONENT comp OF STRUCTURE
◆ Regular expression regex in the statements
FIND ... REGEX regex ... IN ...
REPLACE  ... REGEX regex ... IN ...
◆ Search pattern substring in the statements
FIND ... SUBSTRING substring ... IN ...
REPLACE  ... SUBSTRING substring ... IN ...
◆ Operand dobj in the statement
FIND ... IN dobj ...
◆ Operand new in the statement
REPLACE  ... WITH new ...
REPLACE  ... IN TABLE ... WITH new ...
◆ Operand substring in the statement
SHIFT ... UP TO substring
◆ Operand mask in the statement
SHIFT ... DELETING ... mask
◆ Operands dobj and sep in the statement
SPLIT dobj AT sep INTO ...
◆ Operand text in the statement
CONVERT text INTO SORTABLE CODE ...
◆ Operands text2 and text2 in the statement
OVERLAY ... WITH text2 USING mask
◆ Operand mask in the statement
TRANSLATE ... USING mask
◆ Operand sub in the statement
ASSERT ... SUBKEY sub ...
LOG-POINT ... SUBKEY sub ...
◆ Operands text and dobj1 through dobj4 in the statements
MESSAGE text ...
MESSAGE ...WITH dobj1 ... dobj4

⇨ Functional Operand Positions

Functional operand positions are reading positions in which suitable data objects and functional methods or method chainings plus constructor expressions and table expressions whose return values or results have a suitable data type, can be specified. The following functional operand positions exist:
  • Functional operand positions in ABAP Objects:
    • Operand oref of the statement 
      • SET HANDLER ... FOR oref.
  • Functional operand positions in relational expressions:
    • Operand ref of the predicate expression 
      • ... ref IS [NOT] BOUND ...
  • Functional operand positions in assignments:
    • Operand struc1 of the statement 
      • MOVE-CORRESPONDING struc1 TO ...
    • Operand val of the statement 
      • CLEAR ... WITH val
  • Functional operand positions in string processing and byte string processing
    • Character-like or byte-like arguments of the predefined functions 
      • dbmaxlen, xstrlen
    • Operand itab of the statement 
      • CONCATENATE LINES OF itab INTO ...
    • Operand itab of the statement 
      • FIND ... IN TABLE itab ...
  • Functional operand positions in statements for internal tables:
    • Internal table itab of the statement 
      • READ TABLE itab ...
    • Work area wa of the statement 
      • READ TABLE ... FROM wa ...
    • Internal table itab of the statement 
      • LOOP AT itab ...
    • Internal table jtab of the statement 
      • INSERT LINES OF jtab INTO ...
    • Work area wa of the statement 
      • COLLECT wa INTO ...
    • Internal table jtab of the statement 
      • APPEND LINES OF jtab TO ...
    • Work area wa of the statement 
      • DELETE TABLE ... FROM wa ...
  • Functional operand positions in statements for time stamps:
    • Operands time_stamp and tz of the statement 
      • CONVERT TIME STAMP time_stamp TIME ZONE tz INTO...
    • Operands dat, tim, dst, and tz of the statement 
      • CONVERT DATE dat TIME tim DAYLIGHT SAVING TIME dst INTO ... TIME ZONE tz
  • Functional operand positions in message processing:
    • Operand oref of the statement 
      • MESSAGE oref ...
    • Operands dobj1 to dobj4 of the statement 
      • MESSAGE ...WITH dobj1 ... dobj4
  • Functional operand positions in statements for checkpoints:
    • Operands val1 val2 of the statement 
      • ASSERT ... FIELDS val1 val2 ...
    • Operands val1 val2 ... of the statement 
      • LOG-POINT ... FIELDS val1 val2 ...
Notes

◆ Alongside the regular functional operand positions, three extended functional operand positions exist that can be used to specify certain predefined functions. These operand positions are obsolete and should no longer be used.
◆ Special functional operand positions are all places in which a relational expression can be specified. A single functional method call can be specified as a predicative method call here. Other expressions (with the exception of predicate functions or single data objects (with the exception of an obsolete short form)), on the other hand, cannot be specified as predicates of a relational expression.
◆ In any expressions in string templates embedded in the formatting options, (dobj) and expr for fixed values (if specified) represent a summary functional operand position.

1.3 Operators and Expressions

Normally an operater links two operands with an expression or forms an expression with an operand. During the execution of a statement containing such expressions, the result of the expression is determined (operation) and used in the statement. Operators are represented either by special characters or reserved indicators.

1. Operators

ABAP contains the following operators:
  • Operators that perform special operations in operand positions:
    • Declaration operators 
      • The declaration operators DATA and FIELD-SYMBOL declare variables or field symbols in operand positions.
    • Constructor operators 
      • The constructor operators NEW, VALUE, CONV, CORRESPONDING, CAST, REF, EXACT, REDUCE, FILTER, COND, and SWITCH construct values for data objects of specific data types in constructor expressions.
  • Operators that join multiple operands in a single expression:
    • Assignment operators 
      • The assignment operator = joins the source field and target field of an assignment. In the case of assignments, the special casting operator ?= performs a down cast. The operator = also joins actual parameters with formal parameters, for example in procedure calls or when working with data clusters.
    • Arithmetic operators 
      • The arithmetic operators +, -, *, /, DIV, MOD, and ** join two or more numeric operands with an arithmetic expression. In addition, the characters + and - act as signs in arithmetic expressions.
    • Bit operators 
      • The bit operators BIT-AND, BIT-OR, and BIT-XOR join two or more byte-like operands with a bit expression. The bit operator BIT-NOT negates a byte-like operand.
    • String operators 
      • The string operator && chains two character-like operands to a string expression.
    • Relational operators 
      • Relational operators occur in relational expressions, which themselves are components of logical expressions. The relational operators =, <>, <, >, <=,>=, BETWEEN, and so on join two or more operands of any data type as a comparison expression. There are additional relational operators for specific data types. The predicate operator IS qualifies an operand.
    • Boolean operators 
      • The Boolean operators AND, OR, and EQUIV join the results of individual logical expressions with a logical expression. The result of a logical expression is either true or false. The Boolean operator NOT negates the result of a logical expression.
  • Operator that joins two operands in compilations:
    • Literal operator 
      • The literal operator & joins two literals or two string templates with a literal or a string template.
2. Expressions

The following expressions can be constructed in certain operand positions:
  • Writer positions
    • Declaration expressions
    • Certain constructor expressions
    • Certain table expressions
  • Reader positions
    • Logical expressions
    • Constructor expressions
    • Table expressions and mesh path expressions
    • Arithmetic expressions
    • String expressions
    • Bit expressions
An expression in a writer position produces a result to which a value is assigned.

An expression in a reader position produces a result that is used as an operand in the statement. Logical expressions can contain calculation expressions (arithmetic expressions, string expressions, and bit expressions) as relational expressions. The three different calculation expression types cannot currently be mixed in a single calculation expression.

Note: Although the calculation expression types cannot be mixed directly, a different type of expression can be used as an argument of a permitted function in another expression. In the same way, logical expressions can be used as arguments of Boolean functions in calculation expressions.

3. Examples of Expression-Oriented Programming

◈ Jawbreaker


Expression-oriented implementation of a Jawbreaker game.

Source Code

PROGRAM demo_jawbreaker_html_740.

CLASS game DEFINITION.
  PUBLIC SECTION.
    METHODS:
      constructor,
      display.
  PRIVATE SECTION.
    TYPES:
      t_vector TYPE STANDARD TABLE OF i WITH EMPTY KEY,
      t_matrix TYPE STANDARD TABLE OF t_vector WITH EMPTY KEY,
      BEGIN OF coord,
        x TYPE i,
        y TYPE i,
      END OF coord.
    DATA:
      n      TYPE i,
      field  TYPE t_matrix,
      moves  TYPE i,
      filled TYPE i,
      colors TYPE TABLE OF string WITH EMPTY KEY,
      header TYPE string.
    METHODS:
      at_click FOR EVENT sapevent OF cl_abap_browser IMPORTING action,
      delete IMPORTING VALUE(cursor) TYPE coord
                       VALUE(color) TYPE i OPTIONAL,
      slide.
ENDCLASS.

CLASS game IMPLEMENTATION.
  METHOD constructor.
    colors = VALUE #( ( `lightblue`)
                      ( `cornflowerblue`)
                      ( `darkblue`)
                      ( `steelblue`) ).
    header = `<html><head><style type="text/css">` &
             `a{text-decoration:none;width:18px;height:18px}` &&
             REDUCE string(
               INIT s = `` FOR co IN colors INDEX INTO ci
               NEXT s = |{ s }.c{ ci }\{background-color:{ co }\}| ) &&
                        `</style></head><body leftmargin="35" ` &&
                        `topmargin="60" scroll="no">` &&
                        `<table border="0">`.

    DATA(size) = 5.
    cl_demo_input=>request( CHANGING field = size ).
    n = COND #( WHEN size < 2
                  THEN 2
                WHEN size > 15
                  THEN 15
                  ELSE size ).

    field = VALUE #( LET r = cl_abap_random_int=>create(
                               seed = CONV i( sy-uzeit )
                               min  = 1
                               max = lines( colors ) ) IN
                     FOR i = 1 UNTIL i > n
                     ( VALUE #( FOR j = 1 UNTIL j > n
                                ( r->get_next( ) ) ) ) ).
    filled = n * n.
    SET HANDLER at_click.
  ENDMETHOD.

  METHOD display.
    cl_abap_browser=>show_html(
     title        = CONV cl_abap_browser=>title( sy-title )
     size         = cl_abap_browser=>small
     format       = cl_abap_browser=>portrait
     context_menu = 'X'
     html_string  = COND #( WHEN filled > 0 THEN
       REDUCE string(
        INIT  h = header
        FOR   y = 1  UNTIL y > n
        NEXT  h = h && `<tr>` &&
         REDUCE string( INIT k = ``
          FOR  x = 1  UNTIL x > n
          LET  c = field[ x ][ y ] IN
          NEXT k = k &&
                   COND #( WHEN c = 0
                             THEN `<td><a/></td>`
                             ELSE |<td class=c{ c }>| &
                                  |<a href="sapevent:| &
                                  |x{ x WIDTH = 2
                                        ALIGN = right
                                        PAD   = '0' }| &
                                  |y{ y WIDTH = 2
                                        ALIGN = right
                                        PAD    = '0' }"/></td>| ) )
         && `</tr>` )
       && `</table></body></html>`
      ELSE |Finished in { moves } moves!| )
    ).
  ENDMETHOD.

  METHOD at_click.
    moves = moves + 1.
    delete( VALUE #( x = CONV i( action+1(2) )
                     y = CONV i( action+4(2) ) ) ).
    slide( ).
    display( ).
  ENDMETHOD.

  METHOD delete.
    CHECK cursor-x >= 1 AND cursor-x <= n AND
          cursor-y >= 1 AND cursor-y <= n.
    ASSIGN field[ cursor-x ][ cursor-y ] TO FIELD-SYMBOL(<color>).
    IF color IS NOT SUPPLIED.
      color = <color>.
    ELSEIF <color> <> color OR color = 0.
      RETURN.
    ENDIF.
    <color> = 0.
    filled = filled - 1.

    delete( cursor = VALUE #( x = cursor-x - 1
                              y = cursor-y ) color = color ). "left
    delete( cursor = VALUE #( x = cursor-x + 1
                              y = cursor-y ) color = color ). "right
    delete( cursor = VALUE #( x = cursor-x
                              y = cursor-y - 1 ) color = color ). "up
    delete( cursor = VALUE #( x = cursor-x
                              y = cursor-y + 1 ) color = color ). "down
  ENDMETHOD.

  METHOD slide.
    field = VALUE #( LET fld = field IN
      FOR <column> IN fld
        LET rest = VALUE t_vector(
                      FOR j IN <column>
                      WHERE ( table_line <> 0 ) ( j ) )
            zeroed = n - lines( rest ) IN
        ( VALUE t_vector( FOR k = 1 UNTIL k > n
                          ( COND #( WHEN k <= zeroed THEN 0
                                    ELSE rest[ k - zeroed ] ) ) ) ) ).
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
  NEW game( )->display( ).

Description

This example uses the implementation of a Jawbreaker game to demonstrate expression-oriented ABAP programming (as introduced in Release 7.40). As a comparison, the program DEMO_JAWBREAKER_HTML_700 shows the same function implemented without expressions, mainly using language elements from Release 7.00 only.

To play the game, use the left mouse button to remove adjacent blocks with the same color.

◈ Minesweeper


Expression-oriented implementation of a Minesweeper game.

Source Code

PROGRAM demo_minesweeper_740.

CLASS game DEFINITION.
  PUBLIC SECTION.
    METHODS:
      constructor,
      display.
  PRIVATE SECTION.
    TYPES:
      BEGIN OF t_cell,
        bomb  TYPE abap_bool,  " cell contains bomb y/n
        bombs TYPE i,          " # of neighboring bombs
        state TYPE char1,      " [h]idden, [v]isible, [f]lagged
      END OF t_cell,
      t_cells TYPE STANDARD TABLE OF t_cell  WITH EMPTY KEY,
      t_field TYPE STANDARD TABLE OF t_cells WITH EMPTY KEY.
    DATA:
      field  TYPE t_field,
      n      TYPE i,        " dimension of field
      bombs  TYPE i,        " # of existing bombs
      hidden TYPE i,        " # of hidden cells
      flags  TYPE i,        " # of flagged cells
      moves  TYPE i,        " # of moves
      over   TYPE char1,    " game over: [w]in, [d]ead
      header TYPE string.   " HTML header string
    METHODS:
      at_click FOR EVENT sapevent OF cl_abap_browser IMPORTING action,
      detect IMPORTING VALUE(x) TYPE i VALUE(y) TYPE i.
ENDCLASS.

CLASS game IMPLEMENTATION.
  METHOD constructor.
    header = replace(
      occ = 0 sub = `@` with = `background-color:` val =
     `<html><head><style type="text/css">` &&
     `a{text-decoration:none;width:13px;height:9px}` &&
     `.hid{@#404080} .flg{@red} .bmb{@black}` &&
     `.b0{@#e0e0e0} .b1{@lightblue} .b2{@lightgreen} .b3{@orange}` &&
     `</style>` &&
     `<script>function setloc(e){window.location=e;}</script>` &&
     `</head><body scroll="no"><table border="0">` ) ##NO_TEXT.
    DATA(size) = 10.
    DATA(level) = 3.
    cl_demo_input=>add_field( CHANGING field = size ).
    cl_demo_input=>request(   CHANGING field = level ).
    " size: 2..32
    n     = nmax( val1 = 2 val2 = nmin( val1 = size val2 = 32 ) ).
    " level: 1..5
    level = nmax( val1 = 1 val2 = nmin( val1 = level val2 = 5 ) ).
    DATA(threshold) = 100 - level * 10.
    " place hidden bombs randomly
    field = VALUE #(
      LET r = cl_abap_random_int=>create( seed = CONV i( sy-uzeit )
                                          min  = 0
                                          max  = 99 ) IN
      FOR i = 1 UNTIL i > n
      ( VALUE #( FOR j = 1 UNTIL j > n
                 ( state = 'h'
                   bomb = COND #( WHEN r->get_next( ) > threshold
                                    THEN 'X' ) ) ) ) ).
    " compute neighboring-bombs count for each cell, and overall count
    LOOP AT field ASSIGNING FIELD-SYMBOL(<cells>).
      DATA(y) = sy-tabix.
      LOOP AT <cells> ASSIGNING FIELD-SYMBOL(<cell>).
        IF <cell>-bomb = 'X'.
          bombs = bombs + 1.
        ELSE.
          DATA(x) = sy-tabix.
          <cell>-bombs = REDUCE i(
            INIT b = 0
            FOR  i = nmax( val1 = 1 val2 = y - 1 )
            WHILE i <= nmin( val1 = y + 1 val2 = n )
            FOR  j = nmax( val1 = 1 val2 = x - 1 )
            WHILE j <= nmin( val1 = x + 1 val2 = n )
            LET <f> = field[ i ][ j ] IN
            NEXT b = COND #( WHEN <f>-bomb = 'X' THEN b + 1 ELSE b ) ).
        ENDIF.
      ENDLOOP.
    ENDLOOP.
    hidden = n * n.
    SET HANDLER at_click.
  ENDMETHOD.

  METHOD display.
    cl_abap_browser=>show_html(
     title        = CONV cl_abap_browser=>title( sy-title )
     size         = COND #( WHEN n < 20 THEN cl_abap_browser=>small
                                        ELSE cl_abap_browser=>medium )
     format       = cl_abap_browser=>portrait
     context_menu = 'X'
     html_string  =
       REDUCE string(
        INIT  h = header
        FOR   y = 1 UNTIL y > n
        NEXT  h = h && |<tr{ COND #( WHEN over <> '' THEN
                          ` onclick="setloc('sapevent:ovr');"` ) }>| &&
         REDUCE string(
          INIT k = ``
          FOR  x = 1  UNTIL x > n
          LET  c = field[ y ][ x ]
               " CSS style (hid,flg,b0,...,b3) of cell
               style = COND string(
                         WHEN over <> '' AND
                              c-bomb = 'X'  " bomb
                           THEN `bmb`
                         WHEN c-state = 'f' " flagged
                           THEN `flg`
                         WHEN c-state = 'v' " visible
                           THEN |b{ nmin( val1 = c-bombs val2 = 3 ) }|
                         WHEN over <> ''    " empty
                           THEN `b0`
                         ELSE  `hid` ) " hidden
               pos = |x{ x WIDTH = 2 ALIGN = RIGHT PAD = '0' }| &
                     |y{ y WIDTH = 2 ALIGN = RIGHT PAD = '0' }|
          IN
          NEXT k = |{ k }<td class={ style }| &&
                   COND #( WHEN c-state = 'v'
                    THEN |><a>{ c-bombs }</a>| " bombs value
                    ELSE " HTML events on cell (left: try; right: flag)
                     | oncontextmenu="setloc('sapevent:flg{ pos }');| &
                     |return false;"><a href="sapevent:try{ pos }"/>| )
                   && `</td>` )
         && `</tr>` )
       && `</table><br>`
       && COND #(
           WHEN over = 'd' THEN `*** Bomb  -  Game over ***`
           WHEN over = 'w' THEN |Finished in { moves } moves!| )
       && `</body></html>` ).
  ENDMETHOD.

  METHOD at_click.
    IF over <> ''.  " game is over, final click
      cl_abap_browser=>close_browser( ).
      LEAVE PROGRAM.
    ENDIF.
    moves = moves + 1.
    DATA(x) = CONV i( action+4(2) ).
    DATA(y) = CONV i( action+7(2) ).
    ASSIGN field[ y ][ x ] TO FIELD-SYMBOL(<cell>).
    IF action(3) = 'try'.
      IF <cell>-bomb = 'X'.
        over = 'd'.  " hit bomb -> game over
      ELSE.
        detect( x = x y = y ).
      ENDIF.
    ELSE.  " action(3) = 'flg'
      IF <cell>-state = 'h'.
        <cell>-state = 'f'.  flags = flags + 1.  hidden = hidden - 1.
      ELSE.
        <cell>-state = 'h'.  flags = flags - 1.  hidden = hidden + 1.
      ENDIF.
    ENDIF.
    IF hidden = 0 AND flags = bombs .
      over = 'w'.  " all cells opened, all bombs found -> win
    ENDIF.
    display( ).
  ENDMETHOD.

  METHOD detect.
    CHECK x >= 1 AND x <= n AND y >= 1 AND y <= n.
    ASSIGN field[ y ][ x ] TO FIELD-SYMBOL(<cell>).
    CASE <cell>-state.
      WHEN 'v'.  RETURN.
      WHEN 'h'.  hidden = hidden - 1.
      WHEN 'f'.  flags = flags - 1.
    ENDCASE.
    <cell>-state = 'v'.
    CHECK <cell>-bombs = 0.
    DATA(u) = y - 1.
    DATA(d) = y + 1.
    DATA(l) = x - 1.
    DATA(r) = x + 1.
    detect( y = u x = l ).
    detect( y = u x = x ).
    detect( y = u x = r ).
    detect( y = y x = l ).
    detect( y = y x = r ).
    detect( y = d x = l ).
    detect( y = d x = x ).
    detect( y = d x = r ).
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
  NEW game( )->display( ).

Description

This example uses the implementation of a Minesweeper game to demonstrate expression-oriented ABAP programming (as introduced in Release 7.40). As a comparison, the program DEMO_MINESWEEPER_700 shows the same function implemented without expressions, mainly using language elements from Release 7.00 only.

To play the game, use the left and right mouse buttons to enter or select fields.

◈ 2048 Game


Expression-oriented implementation of a 2048 game.

Source Code

PROGRAM demo_game_2048_740.

CLASS game DEFINITION.
  PUBLIC SECTION.
    METHODS:
      constructor,
      display.
  PRIVATE SECTION.
    TYPES:
      BEGIN OF t_cell,
        value TYPE i,
        id    TYPE string,
        born  TYPE i,
      END OF t_cell,
      t_cells  TYPE STANDARD TABLE OF t_cell  WITH EMPTY KEY,
      t_field  TYPE STANDARD TABLE OF t_cells WITH EMPTY KEY,
      t_ref    TYPE REF TO t_cell,
      t_refs   TYPE STANDARD TABLE OF t_ref WITH EMPTY KEY.
    CONSTANTS tile_colors TYPE string VALUE
      `eee4da ede0c8 f2b179 f59563 f67c5f f65e3b ` &
      `edcf72 f67c5f edc850 edc53f edc22e` ##NO_TEXT.
    DATA:
      mark_new_tiles TYPE abap_bool,
      rnd     TYPE REF TO cl_abap_random_int,
      field   TYPE t_field,
      n       TYPE i,             " dimension of field
      nsq     TYPE i,             " n * n
      target  TYPE i VALUE 2048,  " target value
      score   TYPE i,             " current score
      moves   TYPE i,             " # of moves
      header  TYPE string,        " HTML header string
      over    TYPE string,        " game-over message
      line    TYPE t_refs.
    METHODS:
      at_click FOR EVENT sapevent OF cl_abap_browser IMPORTING action,
      build_line IMPORTING VALUE(direction) TYPE char1 VALUE(i) TYPE i,
      move_lines IMPORTING VALUE(direction) TYPE char1
                 RETURNING VALUE(valid) TYPE abap_bool,
      move_line  RETURNING VALUE(valid) TYPE abap_bool,
      new_tiles  IMPORTING VALUE(factor) TYPE i DEFAULT 1,
      check_game.
ENDCLASS.

CLASS game IMPLEMENTATION.
  METHOD constructor.
    DATA(size) = 4.
    cl_demo_input=>add_field( CHANGING field = size ).
    cl_demo_input=>add_field( CHANGING field = target ).
    cl_demo_input=>add_field( EXPORTING text = 'Mark new tiles'
      as_checkbox = 'X'  CHANGING field = mark_new_tiles ) ##NO_TEXT.
    cl_demo_input=>request( ).
    n      = nmax( val1 = 3 val2 = nmin( val1 = size val2 = 8 ) ).
    nsq    = n * n.
    " target tile value must be a power of 2, at least 8
    target = nmax( val1 = 8 val2 = target ).
    target = ipow( base = 2 exp = ceil( log( target ) / log( 2 ) ) ).

    rnd = cl_abap_random_int=>create( seed = CONV i( sy-uzeit )
                                      min = 0  max = nsq - 1 ).
    field = VALUE #( FOR i = 1 UNTIL i > n
                     ( VALUE #( FOR j = 1 UNTIL j > n
                                ( id = |{ i }{ j }| born = -1 ) ) ) ).
    new_tiles( 2 ).  " place initial tiles in field

    " build header with styles for tiles; cell/font sizes depend on n
    header = REDUCE string( ##NO_TEXT
      LET  w = 360 / n IN
      INIT h =
        `<html><head><style type="text/css">` &
        `.t0{background-color:#cbbdb0}` &
        `td{border:1px solid bbada0;color:#776e65` &
        `;text-align:center;vertical-align:center` &
        `;font-family:'Century Gothic',sans-serif;font-weight:bold` &&
        |;width:{ w }px;height:{ w }px;font-size:{ w / 2 }px\}|
      FOR i = 1 UNTIL i > 11
      NEXT h =
        |{ h }.t{ ipow( base = 2 exp = i ) }\{| &
        |background-color:#{ segment( val   = tile_colors
                                      index = i ) }| &
        |{ COND #( WHEN i >= 3  THEN `;color:#f9f6f2` ) }| &
        |{ COND #( WHEN i >= 10 THEN |;font-size:{ w / 4 }px|
                   WHEN i >= 7  THEN |;font-size:{ w / 3 }px| ) }\}| ).
    header = header && ##NO_TEXT
     `div{text-align:center}</style><script type="text/javascript">` &
     `function okd(e)` &
     `{c=window.event.keyCode;window.location='sapevent:'+c;}` &
     `document.onkeydown = okd;</script></head> <body scroll=no ` &
     `style="background-color:#bbada0;color:white;font-size:20pt">`.
    SET HANDLER at_click.
  ENDMETHOD.

  METHOD display.
    cl_abap_browser=>show_html(
     title        = |Join the numbers and get to the { target } tile!|
     size         = cl_abap_browser=>small
     format       = cl_abap_browser=>portrait
     context_menu = 'X'
     html_string  =
       REDUCE string(
        INIT h = |{ header }<p align=right>Score { score }</p>| &
                 |<table align=center>|
        FOR  <cells> IN field
        NEXT h = h && |<tr>| &&
         REDUCE string(
          INIT k = ``
          FOR  <c> IN <cells>
          NEXT k = |{ k }<td class=t{ <c>-value }| &
                   |{ COND #( WHEN <c>-born = moves
                              THEN ` style="border-color:red"` ) }| &
                   |>{ COND #( WHEN <c>-value = 0 THEN `&nbsp;`
                               ELSE <c>-value ) }</td>| )
         && `</tr>` )
       && `</table>` &&
       COND #( WHEN over = ``
                 THEN `<div>Use arrow keys to join tiles</div>`
                 ELSE |<br>{ over }| )
       && `</body></html>` ).
  ENDMETHOD.

  METHOD at_click.
    DATA(direction) = SWITCH #( action  WHEN 37 THEN 'L'
                                        WHEN 38 THEN 'U'
                                        WHEN 39 THEN 'R'
                                        WHEN 40 THEN 'D' ).
    IF over <> ``.  " game is over; leave game with any non-arrow key
      IF direction IS INITIAL.
        cl_abap_browser=>close_browser( ).
        LEAVE PROGRAM.
      ENDIF.
      RETURN.
    ENDIF.
    IF move_lines( direction ).
       moves = moves + 1.
       new_tiles( ).
       check_game( ).
       display( ).
    ENDIF.
  ENDMETHOD.

  METHOD check_game.
    CONSTANTS dirs TYPE char4 VALUE 'LRUD'.
    " find highest tile value and check if an empty cell exists
    DATA(fill) = REDUCE t_cell(
      INIT m = VALUE #( )
      FOR  <cells> IN field
      FOR  <c>     IN <cells>
      NEXT m-value = nmax( val1 = m-value val2 = <c>-value )
           m-id    = COND #( WHEN <c>-value = 0 THEN `!` ELSE m-id ) ).
    " game is won if target value is reached
    IF fill-value >= target.
      over = |<div>Finished in { moves } moves!</div>|.
    ELSEIF fill-id <> `!`.
      " no empty cell -> check if stuck: try move in all 4 directions
      DO 4 TIMES.
        DATA(off) = sy-index - 1.
        DO n TIMES.
          build_line( direction = dirs+off(1) i = sy-index ).
          LOOP AT line FROM 2 ASSIGNING FIELD-SYMBOL(<curr>).
            IF <curr>->value = line[ sy-tabix - 1 ]->value.
              RETURN.  " found a possible move; game not over
            ENDIF.
          ENDLOOP.
        ENDDO.
      ENDDO.
      over = `<div>*** Stuck  -  Game over ***</div>`.
    ENDIF.
  ENDMETHOD.

  METHOD move_lines.
    CHECK direction IS NOT INITIAL.
    DO n TIMES.
      build_line( direction = direction i = sy-index ).
      valid = cmax( val1 = move_line( ) val2 = valid ).
    ENDDO.
    CLEAR line.
  ENDMETHOD.

  METHOD build_line.
    " build cell references to line i, starting at end (wrt direction)
    line = VALUE #(
      FOR j = n THEN j - 1 UNTIL j = 0  " j = n...1
      LET y = SWITCH i( direction
                WHEN 'L' OR 'R' THEN i
                WHEN 'D'        THEN j
                WHEN 'U'        THEN n + 1 - j )
          x = SWITCH i( direction
                WHEN 'U' OR 'D' THEN i
                WHEN 'R'        THEN j
                WHEN 'L'        THEN n + 1 - j )
      IN ( REF #( field[ y ][ x ] ) ) ).
  ENDMETHOD.

  METHOD move_line.
    DATA: idx TYPE i VALUE 1, next_idx TYPE i VALUE 2.
    DATA(curr) = line[ 1 ].
    WHILE next_idx <= n.
      DATA(next) = line[ next_idx ].
      IF curr->value > 0.
        IF curr->value = next->value.
          curr->value = curr->value * 2.  " join tiles
          next->value = 0.
          valid = abap_true.
          score = score + curr->value.
          idx = idx + 1.  curr = line[ idx ].  " proceed
        ELSEIF next->value > 0 OR next_idx = n.
          idx = idx + 1.  curr = line[ idx ].  " proceed
          next_idx = idx.
        ENDIF.
      ELSEIF next->value <> 0.
        curr->value = next->value.  " shift tile to empty cell
        next->value = 0.
        valid = abap_true.
      ENDIF.
      next_idx = next_idx + 1.
    ENDWHILE.
  ENDMETHOD.

  METHOD new_tiles.
    " place 1 or more (for n>4) new tiles (* 2 at start of game)
    DO nmax( val1 = n - 3 val2 = 1 ) * factor TIMES.
      DATA(pos) = rnd->get_next( ).
      DATA(attempts) = nsq.
      DO. " try to place new tile at this or next free position
        ASSIGN field[ 1 + pos DIV n ][ 1 + pos MOD n ]
          TO FIELD-SYMBOL(<cell>).
        IF <cell>-value = 0.
          " free position found - tile value: 2 (likelihood 75%) or 4
          <cell>-value = COND #( WHEN rnd->get_next( ) > nsq / 4
                                 THEN 2 ELSE 4 ).
          " remember when tile was born, to display it as 'new'
          <cell>-born = COND #( WHEN moves > 0 AND
                                     mark_new_tiles = abap_true
                                THEN moves ELSE -1 ).
          EXIT.
        ENDIF.
        pos = ( pos + 1 ) MOD nsq.
        attempts = attempts - 1.
        IF attempts = 0.
          RETURN.
        ENDIF.
      ENDDO.
    ENDDO.
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
  NEW game( )->display( ).

Description

This example uses the implementation of a 2048 game to demonstrate expression-oriented ABAP programming (as introduced in Release 7.40). The program DEMO_GAME_2048_700 shows the same function implemented without expressions, mainly using language elements from Release 7.00 only.

To play the game, use the arrow keys on the keyboard to move all tiles in one of the four directions.

2. Naming conventions 


2.1 Naming Conventions

The following conventions apply to the names of all definable objects within ABAP programs, such as data types, data objects, classes, macros, or procedures:
  • A name can be up to 30 characters in length.
  • Permitted characters are letters from "A" to "Z", digits from "0" to "9", and underscores (_).
  • The name must start with a letter or an underscore (_). Only outside of ABAP objects can the name also start with a different character.
  • The name can have a namespace prefix. A namespace prefix consists of at least three characters that are enclosed by two forward slashes (/.../). The entire length of prefix and name cannot exceed 30 characters.
  • The names of predefined ABAP types or predefined data objects cannot be used for data types or data objects.
  • The use of IDs that are reserved for ABAP words and so on for custom definitions is not actually forbidden, but is strongly advised against.
  • Field symbols are special in that their names have to be enclosed in angle brackets (<...>). The angle brackets are a part of the name, which means that a field symbol could potentially be called <> (but this is not recommended).
Notes

◉ All types possible in ABAP are in a namespace. Data types and object types do not have separate namespaces. A global class, for example, cannot be created with a name that is already being used for a data type in ABAP Dictionary.
◉ The naming conventions presented here must be followed. They are not checked in full by the syntax check, but they must not be broken more than absolutely necessary.
◉ The program DEMO_CHARACTERS_IN_ABAP_NAMES demonstrates how these checks run in the current system.

2.2 Namespaces

Outside of class declarations, different objects have separate namespaces, so it is possible that data types, data objects or procedures can have the same name. Classes and interfaces thus lie within the same namespace as data types. The namespace is valid for the respective context. Within a context, the names of the same objects must be unique. For example, there can only be one subroutine with the same name in an ABAP program and only one function module with the same name in the entire AS ABAP.

Within a class declaration, the name of every class component (data type, attribute, method, event, or alias name) must be unique.

3. Chained statements 


Consecutive statements that have the same initial part can be combined into one chained statement. To do this, the identical initial part is specified once and closed with a colon (:). The remaining parts are then specified separately, divided by commas (,) and closed with a period (.). When the syntax is checked and the program executed, the chained statement is handled the same way as the single ABAP statements would be in their defined sequence.

Notes

◉ The identical starting parts are not restricted to the keyword.
◉ When using chained statements, care must be taken to not mistakenly produce any statements that have correct syntax but the wrong behavior. This mistake is most commonly made with more complex statements such as when using expressions or function calls where chained statements must be avoided all together.

Examples

Typical use of a chained statement:

DATA: BEGIN OF struc,
        col1 TYPE c LENGTH 4,
        col2 TYPE c LENGTH 4,
      END OF struc.
The complete syntax of the four statements is:

DATA BEGIN OF struc.
DATA   col1 TYPE c LENGTH 4.
DATA   col2 TYPE c LENGTH 4.
DATA END OF struc.
Chained statement in which more than just the keyword is cut off:

CALL FUNCTION func EXPORTING para = : '1', '2', '3'.
The complete syntax of the three statements is:

CALL FUNCTION func EXPORTING para = '1'.
CALL FUNCTION func EXPORTING para = '2'.
CALL FUNCTION func EXPORTING para = '3'.
Incorrect use of a chained statement in Open SQL:

UPDATE scustom SET:  discount  = '003',
                     telephone = '0621/444444'
               WHERE id        = '00017777'.

The code fragment does not represent an individual statement that updates the discount and phone number of customer 00017777. Instead, these are two statements. The first changes the discount for all customers and the second changes the phone number of customer 00017777.

4. Comments 


A comment is an explanation that is added to the source code of a program to help the person reading the program to understand it. Comments are ignored when the program is generated by ABAP Compiler. From a technical perspective, a comment can have any type of content. Two language elements are available for creating comments:

◈ The * character at the start of a program line indicates that the entire line is a comment.
◈ The " character, which can be entered at any position in the line, indicates that the remaining content in the line is a comment. This rule does not apply to the " character in character literals and pseudo comments.

These language elements enable create two categories of comment to be created:

◈ Comment lines

A comment line contains a comment and nothing else. It can be defined either by the * character at the start of the program line, or by the " character at any point of an otherwise blank program line.

◈ End of line comments

An end of line comment is a comment that is added using the " character and that appears after an ABAP statement or part of an ABAP statement.

Note

A special category of line end comments are ABAP Doc comments introduced using "!. These comments can be evaluated by an ABAP development environment and support ABAP Doc.

Example

The following example demonstrates how to use comments. Comment lines added with * are used to structure the program. End of line comments are added after declarations and statements at the end of blocks. All other comments appear before the statements described and are indented accordingly.

*----------------------------------------------------------*
* Class implementations                                    *
*----------------------------------------------------------*
CLASS application IMPLEMENTATION.
  METHOD main.
    DATA: items    TYPE STANDARD TABLE
                   OF REF TO item,     "Item table
          item_ref LIKE LINE OF items. "Item reference
    DATA: amount       TYPE i, "Amount per item
          total_amount TYPE i. "Total amount of items
    ...
    "Loop over all items to compute total amount
    LOOP AT items INTO item_ref.
      IF item_ref IS BOUND AND
        item_ref->is_valid( ) = abap_true.
        "Compute total amount for valid items
        amount = item_ref->get_amount( ).
        ADD amount TO total_amount.
        ...
      ELSE.
        ...
      ENDIF. "item_ref IS BOUND AND...
    ENDLOOP.
    ...
  ENDMETHOD. "main
ENDCLASS. "application

5. Program directives 

The ABAP program directives enable source-code-based development objects to be documented or modify the check results of various check tools.

5.1 ABAP Doc


ABAP Doc allows declarations in ABAP programs to be documented, based on special ABAP Doc comments. ABAP development environments that support ABAP Doc, such as ABAP Development Tools (ADT), analyze the content of ABAP Doc comments, convert it to HTML and display it appropriately.

ABAP Doc Comments

A comment for ABAP Doc is introduced using the string "!. This is a special form of a normal line end comment that is introduced using ". The following rules must be applied if an ABAP Doc comment is to be read correctly:
  • An ABAP Doc comment is either
    • an single comment line that only contains the comment,
    • or a multiline block of consecutive comment lines. The content of a block is summarized into a single ABAP Doc comment.
  • An ABAP Doc comment (a line or a block of lines) must be linked to one declaration statement only:
    • If the declaration statement does not create a chained statement, an ABAP Doc comment can be placed directly in front of the declaration statement, without using spaces as separators.
    • If the declaration statement makes a chained statement, the colon must be placed after the keyword. An ABAP Doc comment can be placed in front of the identifier of every declared entity.
  • ABAP Doc comments are not allowed anywhere else.
  • A one-line ABAP Doc comment cannot be empty. Lines without content can be used as formatting in blocks.
  • An ABAP Doc comment can only contain 7 bit ASCII characters.
  • An ABAP Doc comment can contain special tokens and tags for documenting the parameter interface of procedures, or for formatting.
  • In ABAP Doc comments, the special characters ", ', <, > and @ must be escaped using &quot;, &apos;, &lt;, &gt; and &#64;.
If this rule is broken, a syntax check warning is produced.

Example

Basic use of ABAP Doc - comments as single lines, blocks and chained statements.

"! Basic usage of ABAP Doc
CLASS demo DEFINITION.
  PUBLIC SECTION.
    "! Constant character string for a single blank.
    CONSTANTS blank TYPE string VALUE ` `.
    "! Method to fill the private structure struct with values
    "! and append it to internal table itab.
    METHODS meth.
  PRIVATE SECTION.
    DATA:
      "! Three-component structure
      BEGIN OF struct,
        "! Component one
        comp1 TYPE i,
        "! Component two
        comp2 TYPE i,
        "! Component three
        comp3 TYPE i,
      END OF struct,
      "! Internal table of structure struct
      itab LIKE TABLE OF struct.
ENDCLASS.

Parameter Interface of Procedures

The parameter interface for procedures and for events in classes can be documented in the corresponding ABAP Doc commentary with a special syntax:

Documentation for Syntax
Interface parameters @parameter name|documentation
Class-based exception @raising name|documentation
Classic exceptions @exception name|documentation

The name (name) of an existing parameter or an exception must be specified after @parameter, @raising, @exception. This must be followed by the documentation (separated by |). This documentation is completed by the next @parameter, @raising, @exception or by the end of the ABAP Doc comment. In other words, no further documentation or interface documentation can be placed behind the interface documentation. Every interface parameter or every exception can only be specified once.

Note

The arrangement of the documentation for procedure parameters is not dependent on the arrangement of lines in an ABAP Doc block. However, every parameter or exception should occupy a separate line, to make the documentation easier to read. This is also the reason why the order of the parameters and exceptions in the ABAP Doc comment should be the same as the order of the declarations.

Example

Use of ABAP Doc comments for the parameter interface of a method.

"! Method to check if two sources are identical 
"! and that returns a corresponding boolean value. 
"! 
"! @parameter source1     | First source 
"! @parameter source2     | Second source 
"! @parameter ignore_case | Pass abap_true to ignore case 
"! 
"! @parameter result      | Returns abap_true if sources are identic 
"! 
"! @raising   cx_invalid_source 
"!                        | One of the sources is empty 
METHODS compare 
  IMPORTING 
    source1       TYPE text 
    source2       TYPE text 
    ignore_case   TYPE abap_bool DEFAULT abap_false 
  RETURNING 
    VALUE(result) TYPE abap_bool 
  RAISING 
    cx_invalid_source.

Formatting

Formatting Tag 
Header, level1 <h1>...</h1>
Header, level2 <h2>...</h2>
Header, level3 <h3>...</h3>
Paragraph <p>...</p> 
Italic text   <em>...</em> 
Bold text   <strong>...</strong> 
Unnumbered list   <ul><li>...</li>...<li>...</li></ul> 
Numbered list   <ol><li>...</li>...<li>...</li></ol>
Line break <br/> or <br></br>

An open tag must be closed before a new section of the ABAP Doc comment is started. A new section is introduced using @parameter, @raising or @exception.

The tags are a subset of HTML tags that must be specified in an XHTML notation.

◈ The opening and closing tags must be specified in uppercase letters or in lowercase letters. Apart from this, uppercase and lowercase characters are not important.
◈ Nesting of lists is not currently supported.
◈ The tags <h1>, <h2>, <h3>, <p>, <em> or <strong> cannot contain any <p>, <ul> or <ol> tags.
◈ Text cannot be directly entered into <ol>, <ul>, and <br> tags.

Example

Use of formatting in an ABAP Doc comment for a class. The ABAP Development Tools display the documentation with the appropriate formatting.

"!<h1>Class demo</h1>
"!<p>This class must <strong>not</strong> be used productively.</p>
"!The class serves the following tasks:
"!<ul><li>Demo 1</li>
"!    <li>Demo 2</li>
"!    <li>Demo 3</li></ul>
"!<br/><br/>
CLASS demo DEFINITION.
  ...
ENDCLASS.

Short Texts and Their Synchronization

Parts of ABAP Doc comments can be flagged as short texts and the short texts of classes and function modules and their components can be synchronized with ABAP Doc comments. A part of an ABAP Doc comment can be flagged as a short text by being tagged as follows:

<p class="shorttext">...</p>

A paragraph tagged like this is displayed as a header in the display of the ADT documentation, instead of the short text shown in ABAP Workbench.

To synchronize the ABAP Doc short texts and the short texts shown in ABAP Workbench, the tag can be specified as follows (this is optional):

<p class="shorttext synchronized">...</p>

In this case, the length of the short text in ABAP Doc is restricted to the length of the matching short text in ABAP Workbench and is synchronized with the associated short text in the original language of the class or function module as follows:

◈ When an ABAP Doc short text is created or modified in the source code, the associated short text of the repository object is used when the source code is saved. If the short text in ABAP Doc is empty, the short text of the repository object is deleted. If class="shorttext synchronized" is used to remove a full paragraph, the short text of the repository object is preserved. This synchronization works regardless of the tool used.

◈ If a short text of a method or a function module is modified in ABAP Workbench in which a paragraph with class="shorttext synchronized" occurs in ABAP Doc, the short text is replaced accordingly in the source text when saved. When a short text in ABAP Workbench is deleted, an empty paragraph is produced. When a new short text is created in ABAP Workbench for which there is not yet a short text in ABAP Doc, the paragraph is not currently created in the source code.
An ABAP Doc short text is part of the source code and is not translatable. This short text replaces the translatable short text of the repository object in its original language when synchronized, which means it must also be specified in the original language. This is an exception to the rule that ABAP Doc comments must always be in English. The original language can be flagged in the source by being specified as follows (this is optional):

<p class="shorttext" lang="...">...</p>

The attribute lang uses the HTML standard and must be used to specify the original language of the repository object as a two character ISO code. If not, a syntax check warning occurs. In the source code, this attributes clearly indicates in which language the short text is specified and is also reserved for future developments to the translatability of short texts.

Example

See the class CL_DEMO_ABAP_DOC in a source code editor. It contains ABAP Doc comments for the class itself, for a type, for a method and its parameters, and for an attribute. The ABAP Doc comments include short texts that are synchronized with the short texts in ABAP Workbench in the original language English. The class can be copied to a standalone temporary class to test the synchronization.

Guidelines

Programming Guidelines

The following guidelines for general comments also specifically apply to ABAP-DOC comments.

◈ Write program comments in English 
Adhering to this rule is particularly important, because documentation created in an ABAP Doc as part of the source code is not translated into other languages. One exception are synchronized short texts.

◈ Arrange comments correctly 
This rule affects the horizontal indents because the vertical alignment is fixed in the syntax before declarations.

◈ Character set of source code 
This rule is checked by the syntax check.

5.2 Pragmas


Pragmas are program directives that can be used to hide warnings from various check tools. The following are supported:

◈ Warnings from the ABAP Compiler syntax check
◈ Warnings from the extended program check

Syntax of Pragmas

A pragma is structured as follows:

##code[par][par]... ,

is not case-sensitive and does not contain blanks. The pragma code (code) specifies the effect; parameters (par) may further limit the effect.

A message is affected by a pragma if all the parameters specified match the concrete parameters. The concrete parameters can also be found in the long text of the message. Compulsory parameters are underlined in the long text and must not be omitted. Some parameters are optional. Optional parameters can be omitted by using an empty pair of square brackets [] in the appropriate position or by completely omitting an end part.

Notes

◈ The existence of a pragma for a specific warning from the system check can be checked using the long text of the message (which in this case always exists). The description of a message for the extended program check is also specified by the pragma, which can be used to hide it.
◈ Pragmas replace the previously common pseudo comments to hide warnings from the extended program check. Pseudo comments are now obsolete and should no longer be used. The program ABAP_SLIN_PRAGMAS shows which pragmas are to be used instead of the obsolete pseudo comments.
◈ Do not use statement SET EXTENDED CHECK and the pseudo comment #EC * in programs that use pragmas to deactivate warnings. This causes an extended program check warning that cannot be deactivated.
◈ A pragma in a type definition made using TYPES (for example, for hiding the warning about redundant secondary keys of table types) can also be applied to data declarations using DATA (in the case of non-generic types) and associated statements that reference the data type using TYPE. In the case of references to a generic data type defined using TYPES (that is a table type for which no primary table key is defined), a specified pragma is not applied to the data declaration. This is because the declaration uses a full table type implicitly and the pragma must potentially be specified again.

Example

An example of a pragma for syntax check warnings is:

##SHADOW

This pragma can be used to hide a syntax warning in a method definition that warns that a predefined function is obscured. The pragma has an optional parameter in which the name of the function can be specified as well.

##SHADOW[SUBSTRING]

Warnings about "SUBSTRING" is suppressed using

◈ ##SHADOW
◈ ##SHADOW[SUBSTRING]
◈ ##SHADOW[]

but not using SHADOW[FIND].

Example

An example of pragmas for hiding warnings from the extended program check is provided below.

DATA TEXT TYPE STRING   ##needed.
text  = 'Hello Pragmas' ##no_text.

Examples

In some examples for key accesses to internal tables (read, delete), syntax warnings are hidden by the relevant pragma. The pragmas were found in the long text of the syntax warnings (i button selected).

Positioning of Pragmas in ABAP Source Code

A pragma applies to the current statement, that is, for the statement that ends at the next "." or ",". Pragmas in front of the ":" of a chained statement apply to the whole chained statement. Pragmas that occur when calling a macro apply to all statements of the macro.

Pragmas must only occur at certain positions in the source code for reasons of readability:

◈ at the start of a line, after any number of blanks
◈ at the end of a line, at the most followed by ".", ",", or ":".
◈ but not after ".", ",", or ":".
Multiple pragmas may be entered one after another (separated by blanks) at permitted positions.

Unknown pragmas or pragmas with formal errors or pragmas in the wrong position or with incorrect parameters themselves produce syntax warnings. Pragmas in the wrong position for syntax check warnings are ignored.

5.3 Pseudo Comments


Pseudo comments are program directives that influence check and test procedures. Pseudo comments have mostly become obsolete and have been replaced by pragmas or real additions.

Non-Obsolete Pseudo Comments

◈ Pseudo Comments for Code Inspector

Obsolete Pseudo Comments

◈ Pseudo Comments for the Extended Program Check
◈ Pseudo Comments for Test Classes

Note

It is only possible to specify one pseudo comment for each program line. If multiple pseudo comments are required for a single statement, they must span multiple lines.

5.3.1 Pseudo Comments for Code Inspector

The character string "#EC after a statement or a part of a statement, which is followed by an ID with the prefix "CI_", defines a pseudo comment for Code Inspector.

These pseudo comments can be used to hide certain warnings from Code Inspector for the statement in question. The possible IDs are documented in Code Inspector or in the output of its messages.

Notes

◈ Until now, only the pseudo comments for Code Inspector have not been replaced by other language elements.
◈ To hide multiple warnings from a statement with pseudo comments, the statement must span multiple lines.

Example

The following join expression bypasses SAP buffering, which triggers a warning from Code Inspector. If the SELECT statement is part of an application that buffers selected data itself, however, the warning can be hidden as shown here. An additional normal comment is included to make it clear to the reader why the pseudo comment is being used.

SELECT d~object, h~dokldate, h~dokltime   "#EC CI_BUFFJOIN
  FROM dokil AS d                         "Buffering is done
       INNER JOIN dokhl AS h              "by application
         ON h~id         = d~id     AND   "with Shared Objects
            h~object     = d~object AND
            h~typ        = d~typ    AND
            h~langu      = d~langu  AND
            h~dokversion = d~version
  WHERE d~id     = 'SD'     AND
        d~typ    = 'E'      AND
        d~langu = @langu AND
        d~object LIKE 'AB%'
  INTO CORRESPONDING FIELDS OF TABLE @docu_tab.

6. Syntax conventions

The ABAP keyword documentation uses the following syntax conventions:

◈ ABAP words are displayed in uppercase letters.

Example: 

APPEND, NON-UNIQUE, INTO

◈ Operands are displayed in lowercase letters.

Example: 

dobj, dbtab

◈ Parts of statements whose syntax diagrams are shown in another place are displayed as pseudo syntax.

Example: 

selscreen_options, list_options

◈ Periods, commas, colons, and parentheses are displayed as normal. They are part of the ABAP syntax.

Example: 

. : , ()

◈ Operators are displayed as normal. They are part of the ABAP syntax.

Example: 

+, -, *, /

◈ Parts of statements that are optional are displayed in square brackets [ ]. A list of parts of statements in square brackets like this means that some or all of the parts can be used. If at least one part must be used, this is noted in the text. When used as part of the ABAP syntax, square brackets [ ] are shown in the same color as all other language elements and are not shown in italics.

Example:: 

[NO-GROUPING] [NO-SIGN] [NO-ZERO]

◈ Light-colored vertical slashes (|) between parts of statements mean that only one of the parts specified within a statement can be used. A vertical slash like this always joins immediate neighbors. When used as part of the ABAP syntax, vertical slashes | are shown in the same color as all other language elements.

Example: 

DDMMYY | MMDDYY | YYMMDD

◈ Light-colored curly brackets ({ }) in italics group together related parts of statements, for example on the right or left of vertical slashes. When used as part of the ABAP syntax, curly brackets { } are shown in the same color as all other language elements and are not shown in italics.

Example: 

{NO EDIT MASK}|{EDIT MASK mask}

◈ A string of dots means that other parts of the statement can be included at this point.

Example:

... AS CHECKBOX

Note: The syntax diagrams of the ABAP keyword documentation show the language elements in an order that is correct syntax. In many statements, other orders are also possible but are not mentioned. For the documentation, the order chosen is the one that best suits the semantics of a statement and which describes the different variants of a statement are most consistently.

«« Previous
Next »»

No comments:

Post a Comment