Source code:
FUNCTION zformel_compute.
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" VALUE(FORMEL) TYPE CHAR1024
*" EXPORTING
*" REFERENCE(DATA) TYPE STRING
*" EXCEPTIONS
*" FORMEL_ERROR
*"----------------------------------------------------------------------
* TYPES: formel(255).
DATA: result TYPE TABLE OF formel WITH HEADER LINE.
DATA: i TYPE i,ch,line TYPE i,m TYPE i.
DATA:top_operator TYPE formel,ture,theta TYPE formel,a TYPE formel,b TYPE formel,xtheta TYPE formel.
CLEAR:lt_vs[],lt_optr[],lt_opdn[].
PERFORM. init.
CONDENSE formel NO-GAPS.
IF formel IS INITIAL.
EXIT.
ENDIF.
* 判断是否为数字表达式
DATA:tmp_formel TYPE formel,p TYPE p DECIMALS 6.
tmp_formel = formel.
SPLIT tmp_formel AT '+' INTO TABLE result.
CONCATENATE LINES OF result INTO tmp_formel SEPARATED BY space.
SPLIT tmp_formel AT '-' INTO TABLE result.
CONCATENATE LINES OF result INTO tmp_formel SEPARATED BY space.
SPLIT tmp_formel AT '*' INTO TABLE result.
CONCATENATE LINES OF result INTO tmp_formel SEPARATED BY space.
SPLIT tmp_formel AT '/' INTO TABLE result.
CONCATENATE LINES OF result INTO tmp_formel SEPARATED BY space.
SPLIT tmp_formel AT '(' INTO TABLE result.
CONCATENATE LINES OF result INTO tmp_formel SEPARATED BY space.
SPLIT tmp_formel AT ')' INTO TABLE result.
CONCATENATE LINES OF result INTO tmp_formel SEPARATED BY space.
SPLIT tmp_formel AT space INTO TABLE result.
LOOP AT result.
CATCH SYSTEM-EXCEPTIONS arithmetic_errors = 1
THERS = 2.
p = result.
ENDCATCH.
IF sy-subrc <> 0.
RAISE formel_error.
ENDIF.
* CATCH cx_sy_conversion_no_number.
ENDLOOP.
CLEAR result[].
*
i = STRLEN( formel ) - 1.
ch = formel+i(1).
SPLIT formel AT '+' INTO TABLE result.
CONCATENATE LINES OF result INTO formel SEPARATED BY ' + '.
SPLIT formel AT '-' INTO TABLE result.
CONCATENATE LINES OF result INTO formel SEPARATED BY ' - '.
SPLIT formel AT '*' INTO TABLE result.
CONCATENATE LINES OF result INTO formel SEPARATED BY ' * '.
SPLIT formel AT '/' INTO TABLE result.
CONCATENATE LINES OF result INTO formel SEPARATED BY ' / '.
SPLIT formel AT '(' INTO TABLE result.
CONCATENATE LINES OF result INTO formel SEPARATED BY ' ( '.
SPLIT formel AT ')' INTO TABLE result.
CONCATENATE LINES OF result INTO formel SEPARATED BY ' ) '.
IF ch = ')'.
CONCATENATE formel ' )' INTO formel.
ENDIF.
* REPLACE - the '' charactor is ignored
* REPLACE ALL OCCURRENCES OF '+' IN formel WITH ' + '.
* REPLACE ALL OCCURRENCES OF '-' IN formel WITH ' - '.
* REPLACE ALL OCCURRENCES OF '*' IN formel WITH ' * '.
* REPLACE ALL OCCURRENCES OF '/' IN formel WITH ' / '.
CONCATENATE formel ' #' INTO formel.
FIND '#' IN formel.
IF sy-subrc <> 0.
* formel长度不够
RAISE formel_error.
ENDIF.
SPLIT formel AT space INTO TABLE result.
LOOP AT result.
IF result = ''.
DELETE result.
CONTINUE.
ELSE.
CONDENSE result NO-GAPS.
MODIFY result.
ENDIF.
ENDLOOP.
* DESCRIBE TABLE result LINES line.
m = 1.
READ TABLE result INDEX m.
PERFORM. gettop TABLES lt_optr CHANGING top_operator.
WHILE result <> '#' OR top_operator <> '#'.
PERFORM. is_operator USING result CHANGING ture.
IF ture <> 'X'.
PERFORM. push_opdn TABLES lt_opdn USING result.
m = m + 1.
READ TABLE result INDEX m.
ELSE.
PERFORM. gettop TABLES lt_optr CHANGING top_operator.
READ TABLE lt_vs WITH KEY op1 = top_operator op2 = result.
IF sy-subrc = 0.
CASE lt_vs-vs.
WHEN '>'.
PERFORM. pop_optr TABLES lt_optr CHANGING theta.
PERFORM. pop_opdn TABLES lt_opdn CHANGING b.
PERFORM. pop_opdn TABLES lt_opdn CHANGING a.
PERFORM. oprate TABLES lt_opdn USING a b theta.
WHEN ' PERFORM. push_optr TABLES lt_optr USING result .
m = m + 1.
READ TABLE result INDEX m.
WHEN '='.
PERFORM. pop_optr TABLES lt_optr CHANGING xtheta.
m = m + 1.
READ TABLE result INDEX m.
WHEN OTHERS.
RAISE formel_error.
ENDCASE.
ENDIF.
* CLEAR top_operator.
ENDIF.
PERFORM. gettop TABLES lt_optr CHANGING top_operator.
ENDWHILE.
READ TABLE lt_opdn INDEX 1.
data = lt_opdn-opdn.
* WRITE data.
ENDFUNCTION.
Global Data:
FUNCTION-POOL zgroup. "MESSAGE-ID ..
TYPES:formel(1024).
* 规则
TYPES:BEGIN OF vs,
op1,
op2,
vs,
END OF vs.
DATA lt_vs TYPE TABLE OF vs WITH HEADER LINE.
* 运算符
TYPES:BEGIN OF wc,
optr,
END OF wc.
DATA lt_optr TYPE TABLE OF wc WITH HEADER LINE.
* 运算数
TYPES:BEGIN OF wd,
opdn TYPE formel,
END OF wd.
DATA lt_opdn TYPE TABLE OF wd WITH HEADER LINE.
Form:
*&---------------------------------------------------------------------*
*& Form INIT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* *----------------------------------------------------------------------*
FORM. init .
* init lt_optr
lt_optr = '#'.
APPEND lt_optr.
* +
lt_vs-op1 = '+'.
lt_vs-op2 = '+'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '+'.
lt_vs-op2 = '-'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '+'.
lt_vs-op2 = '*'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '+'.
lt_vs-op2 = '/'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '+'.
lt_vs-op2 = '('.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '+'.
lt_vs-op2 = ')'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '+'.
lt_vs-op2 = '#'.
lt_vs-vs = '>'.
APPEND lt_vs.
* -
lt_vs-op1 = '-'.
lt_vs-op2 = '+'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '-'.
lt_vs-op2 = '-'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '-'.
lt_vs-op2 = '*'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '-'.
lt_vs-op2 = '/'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '-'.
lt_vs-op2 = '('.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '-'.
lt_vs-op2 = ')'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '-'.
lt_vs-op2 = '#'.
lt_vs-vs = '>'.
APPEND lt_vs.
* *
lt_vs-op1 = '*'.
lt_vs-op2 = '+'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '*'.
lt_vs-op2 = '-'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '*'.
lt_vs-op2 = '*'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '*'.
lt_vs-op2 = '/'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '*'.
lt_vs-op2 = '('.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '*'.
lt_vs-op2 = ')'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '*'.
lt_vs-op2 = '#'.
lt_vs-vs = '>'.
APPEND lt_vs.
* /
lt_vs-op1 = '/'.
lt_vs-op2 = '+'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '/'.
lt_vs-op2 = '-'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '/'.
lt_vs-op2 = '*'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '/'.
lt_vs-op2 = '/'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '/'.
lt_vs-op2 = '('.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '/'.
lt_vs-op2 = ')'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = '/'.
lt_vs-op2 = '#'.
lt_vs-vs = '>'.
APPEND lt_vs.
* (
lt_vs-op1 = '('.
lt_vs-op2 = '+'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '('.
lt_vs-op2 = '-'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '('.
lt_vs-op2 = '*'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '('.
lt_vs-op2 = '/'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '('.
lt_vs-op2 = '('.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '('.
lt_vs-op2 = ')'.
lt_vs-vs = '='.
APPEND lt_vs.
lt_vs-op1 = '('.
lt_vs-op2 = '#'.
lt_vs-vs = ''.
APPEND lt_vs.
* )
lt_vs-op1 = ')'.
lt_vs-op2 = '+'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = ')'.
lt_vs-op2 = '-'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = ')'.
lt_vs-op2 = '*'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = ')'.
lt_vs-op2 = '/'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = ')'.
lt_vs-op2 = '('.
lt_vs-vs = ''.
APPEND lt_vs.
lt_vs-op1 = ')'.
lt_vs-op2 = ')'.
lt_vs-vs = '>'.
APPEND lt_vs.
lt_vs-op1 = ')'.
lt_vs-op2 = '#'.
lt_vs-vs = '>'.
APPEND lt_vs.
* #
lt_vs-op1 = '#'.
lt_vs-op2 = '+'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '#'.
lt_vs-op2 = '-'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '#'.
lt_vs-op2 = '*'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '#'.
lt_vs-op2 = '/'.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '#'.
lt_vs-op2 = '('.
lt_vs-vs = ' APPEND lt_vs.
lt_vs-op1 = '#'.
lt_vs-op2 = ')'.
lt_vs-vs = ''.
APPEND lt_vs.
lt_vs-op1 = '#'.
lt_vs-op2 = '#'.
lt_vs-vs = '='.
APPEND lt_vs.
ENDFORM. " INIT
*&---------------------------------------------------------------------*
*& Form GETTOP
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_LT_OPTR text
* *----------------------------------------------------------------------*
FORM. gettop TABLES p_lt_optr
CHANGING p_top_operator TYPE formel.
DATA line TYPE i.
DATA wa TYPE wc.
CLEAR p_top_operator.
DESCRIBE TABLE p_lt_optr LINES line.
READ TABLE p_lt_optr INDEX line INTO wa.
IF sy-subrc = 0.
p_top_operator = wa-optr.
ENDIF.
ENDFORM. " GETTOP
*&---------------------------------------------------------------------*
*& Form IS_OPERATOR
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_RESULT text
* *----------------------------------------------------------------------*
FORM. is_operator USING p_result
CHANGING p_ture.
CLEAR p_ture.
IF p_result = '+' OR p_result = '-' OR p_result = '*' OR p_result = '/' OR p_result = '(' OR p_result = ')' OR p_result = '#'.
p_ture = 'X'.
ELSE.
CLEAR p_ture.
ENDIF.
ENDFORM. " IS_OPERATOR
*&---------------------------------------------------------------------*
*& Form PUSH_OPTR
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_LT_OPTR text
* -->P_RESULT text
*----------------------------------------------------------------------*
FORM. push_optr TABLES p_lt_optr
USING p_result TYPE formel.
DATA wa TYPE wc.
wa-optr = p_result.
APPEND wa TO p_lt_optr.
ENDFORM. " PUSH_OPTR
*&---------------------------------------------------------------------*
*& Form PUSH_OPDN
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_LT_OPDN text
* -->P_RESULT text
*----------------------------------------------------------------------*
FORM. push_opdn TABLES p_lt_opdn
USING p_result TYPE formel.
DATA wa TYPE wd.
wa-opdn = p_result.
APPEND wa TO p_lt_opdn.
ENDFORM. " PUSH_OPDN
*&---------------------------------------------------------------------*
*& Form POP_OPTR
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_LT_OPTR text
* *----------------------------------------------------------------------*
FORM. pop_optr TABLES p_lt_optr
CHANGING p_theta TYPE formel.
CLEAR p_theta.
DATA line TYPE i.
DATA wa TYPE wc.
DESCRIBE TABLE p_lt_optr LINES line.
READ TABLE p_lt_optr INDEX line INTO wa.
IF sy-subrc = 0.
p_theta = wa-optr.
DELETE p_lt_optr INDEX line.
ENDIF.
ENDFORM. " POP_OPTR
*&---------------------------------------------------------------------*
*& Form POP_OPDN
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_LT_OPDN text
* *----------------------------------------------------------------------*
FORM. pop_opdn TABLES p_lt_opdn
CHANGING p_opdn TYPE formel.
CLEAR p_opdn.
DATA line TYPE i.
DATA wa TYPE wd.
DESCRIBE TABLE p_lt_opdn LINES line.
READ TABLE p_lt_opdn INDEX line INTO wa.
IF sy-subrc = 0.
p_opdn = wa-opdn.
DELETE p_lt_opdn INDEX line.
ENDIF.
ENDFORM. " POP_OPDN
*&---------------------------------------------------------------------*
*& Form OPRATE
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_LT_OPDN text
* -->P_A text
* -->P_B text
* -->P_THETA text
*----------------------------------------------------------------------*
FORM. oprate TABLES p_lt_opdn
USING p_a TYPE formel
p_b TYPE formel
p_theta TYPE formel.
DATA:formel TYPE formel,wa TYPE wd.
CASE p_theta.
WHEN '+'.
formel = p_a + p_b.
WHEN '-'.
formel = p_a - p_b.
WHEN '*'.
formel = p_a * p_b.
WHEN '/'.
formel = p_a / p_b.
WHEN OTHERS.
ENDCASE.
* wa-opdn = formel.
* APPEND wa TO p_lt_opdn.
CONDENSE formel NO-GAPS.
PERFORM. push_opdn TABLES p_lt_opdn USING formel.
ENDFORM. " OPRATE
运行效果:
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10842258/viewspace-609590/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/10842258/viewspace-609590/