Ronaldo
Ronaldo

Reputation: 41

Dynamic logical expression evaluating

I need to evaluate a dynamic logical expression and I know that in ABAP it is not possible. I found the class cl_java_script and with this class I could achieve my requeriment. I've try something like this:

result = cl_java_script=>create( )->evaluate( `( 1 + 2 + 3 ) == 6 ;` ).

After the method evaluate execution result = true as espected. But my happiness is over when I look into the class documentation that says This class is obsolete.

My question is, there is another way to achieve this?

Upvotes: 1

Views: 1181

Answers (2)

Jonas Wilms
Jonas Wilms

Reputation: 138457

Using any turing complete language to parse a "dynamic logical expression" is a terrible idea, as an attacker might be able to run any program inside your expression, i.e. while(true) { } will crash your variant using cl_java_script. Also although I don't know the details of cl_java_script, I assume it launches a separate JS runtime in a separate thread somewhere, this does not seem to be the most efficient choice to calculate such a small dynamic expression.

Instead you could implement your own small parser. This has the advantage that you can limit what it supports to the bare minimum whilst being able to extend it to everything you need in your usecase. Here's a small example using reverse polish notation which is able to correctly evaluate the expression you've shown (using RPN simplifies parsing a lot, though for sure one can also build a full fledged expression parser):

REPORT z_expr_parser.

TYPES:
 BEGIN OF multi_value,
  integer TYPE REF TO i,
  boolean TYPE REF TO bool,
 END OF multi_value.

CLASS lcl_rpn_parser DEFINITION.
  PUBLIC SECTION.
    METHODS:
      constructor
        IMPORTING
          text TYPE string,
      parse
        RETURNING VALUE(result) TYPE multi_value.
   PRIVATE SECTION.
     DATA:
       tokens TYPE STANDARD TABLE OF string,
       stack  TYPE STANDARD TABLE OF multi_value.

     METHODS pop_int
       RETURNING VALUE(result) TYPE i.
     METHODS pop_bool
       RETURNING VALUE(result) TYPE abap_bool.
ENDCLASS.

CLASS lcl_rpn_parser IMPLEMENTATION.
  METHOD constructor.
    " a most simple lexer:
    SPLIT text AT ' ' INTO TABLE tokens.
    ASSERT lines( tokens ) > 0.
  ENDMETHOD.

  METHOD pop_int.
    DATA(peek) = stack[ lines( stack ) ].
    ASSERT peek-integer IS BOUND.
    result = peek-integer->*.
    DELETE stack INDEX lines( stack ).
  ENDMETHOD.


  METHOD pop_bool.
    DATA(peek) = stack[ lines( stack ) ].
    ASSERT peek-boolean IS BOUND.
    result = peek-boolean->*.
    DELETE stack INDEX lines( stack ).
  ENDMETHOD.

  METHOD parse.
    LOOP AT tokens INTO DATA(token).
      IF token = '='.
        DATA(comparison) = xsdbool( pop_int( ) = pop_int( ) ).
        APPEND VALUE #( boolean = NEW #( comparison ) ) TO stack.
      ELSEIF token = '+'.
        DATA(addition) = pop_int( ) + pop_int( ).
        APPEND VALUE #( integer = NEW #( addition ) ) TO stack.
      ELSE.
        " assumption: token is integer
        DATA value TYPE i.
        value = token.
        APPEND VALUE #( integer = NEW #( value ) ) TO stack.
      ENDIF.
    ENDLOOP.

    ASSERT lines( stack ) = 1.
    result = stack[ 1 ].
  ENDMETHOD.
ENDCLASS.


START-OF-SELECTION.

" 1 + 2 + 3 = 6 in RPN:
DATA(program) = |1 2 3 + + 6 =|.
DATA(parser) = NEW lcl_rpn_parser( program ).
DATA(result) = parser->parse( ).
ASSERT result-boolean IS BOUND.
ASSERT result-boolean->* = abap_true.

Upvotes: 4

phil soady
phil soady

Reputation: 11348

SAPs BRF is an option, but potentially massive overkill in your scenario.
Here is a blog on calling BRF from abap. And here is how Rules/Expressions can be defined dynamically.

BUT, if you know enough about the source problem to generate 1 + 2 + 3 = 6

Then it is hard to imagine why a simple custom parser cant be used. Just how complex should the expressions be ?
Id probably write my own parser before investing in calling BRF.

Since some/many BSPs use server side JAVAscript and not ABAP as the scripting language, i cant see SAP removing the Kernel routine anytime soon. SYSTEM-CALL JAVA SCRIPT EVALUATE.
SO maybe consider Just calling the cl_java_script anyway until it is an issue. Then worry about a parser if and when it is really no longer a valid call.

But definitely some movement in the obsolete space here. SAP is pushing/forcing you to cloud with the SDK, to execute such things.

https://sap.github.io/cloud-sdk/docs/js/overview-cloud-sdk-for-javascript

Upvotes: 1

Related Questions