/*----------------------------------------------------------------------------- * * exprrex.mod - module file for exprrex.l * * exprrex Example dialog for REXX schema * * Written: 96/05/11 Pieter Hintjens * Revised: 96/05/21 * * Skeleton generated by LIBERO 2.10 on 11 May, 1996, 12:59. *---------------------------------------------------------------------------*/ end_mark_priority = 1 /* Relative priority of tokens */ left_par_priority = 2 /* which may occur in exression */ right_par_priority = 3 /* - higher number means higher */ term_op_priority = 4 /* priority, ie. executed first. */ factor_op_priority = 5 lowest_op_priority = 4 end_mark_token = "$" /* Indicates end of operator stack */ operator_max = 30 /* Max size of operator stack */ operand_max = 30 /* Max size of operand stack */ /************************* INITIALISE THE PROGRAM ************************/ initialise_the_program: Parse Arg expr /* Get expression argument */ result = 0 /* Assume result is zero */ operand_ptr = 0 /* Operand stack holds zero */ operator_ptr = 0 /* Operator stack holds end mark */ op_number.0 = 0 op_token.0 = end_mark_token op_priority.0 = end_mark_priority expr_ptr = 1 /* Move to start of expression */ expr = expr || end_mark_token /* Append end-of-expression mark */ the_next_event = ok_event Return /***************************** GET NEXT TOKEN ****************************/ get_next_token: Do Until the_token /= " " /* Skip spaces */ the_token = Substr(expr, expr_ptr, 1) expr_ptr = expr_ptr + 1 End Select When the_token = "+" | the_token = "-" Then Do the_next_event = term_op_event the_priority = term_op_priority End When the_token = "*" | the_token = "/" Then Do the_next_event = factor_op_event the_priority = factor_op_priority End When the_token = "(" Then Do the_next_event = left_par_event the_priority = left_par_priority End When the_token = ")" Then Do the_next_event = right_par_event the_priority = right_par_priority End When the_token = end_mark_token Then Do the_next_event = end_mark_event the_priority = end_mark_priority End Otherwise Do If the_token >= "0" & the_token <= "9" Then Do the_next_event = number_event Call collect_number End Else Do Say "Invalid token:" the_token Call raise_exception (exception_event) End End End Return /* Pick-up the_number at expr_ptr; first digit is already in the_token */ collect_number : the_digit = Substr(expr, expr_ptr, 1) Do While the_digit >= "0" & the_digit <= "9" the_token = the_token || the_digit expr_ptr = expr_ptr + 1 the_digit = Substr(expr, expr_ptr, 1) End the_number = Value(the_token) Return /**************************** STACK THE NUMBER ***************************/ stack_the_number: If operand_ptr < operand_max Then Do operand_ptr = operand_ptr + 1 op_number.operand_ptr = the_number End Else Do Say "Operand stack overflowed" Call raise_exception (exception_event) End Return /*************************** STACK THE OPERATOR **************************/ stack_the_operator: If operator_ptr < operator_max Then Do operator_ptr = operator_ptr + 1 op_token.operator_ptr = the_token op_priority.operator_ptr = the_priority End Else Do Say "Operator stack overflowed" Call raise_exception (exception_event) End Return /************************** ALLOW SIGNED NUMBER **************************/ allow_signed_number: cur_sign = the_token the_token = Substr(expr, expr_ptr, 1) If the_token >= "0" & the_token <= "9" Then Do expr_ptr = expr_ptr + 1 Call collect_number If cur_sign = "-" Then the_number = 0 - the_number /* Go handle number as operand in this state */ Call raise_exception (number_event) End Return /************************** UNSTACK IF LEFT PAR **************************/ unstack_if_left_par: If op_token.operator_ptr = "(" Then Do operator_ptr = operator_ptr - 1 End Else Do Call raise_exception (exception_event) Say "Too many right parentheses in expression" End Return /************************* UNSTACK ALL OPERATORS *************************/ unstack_all_operators: Do While op_priority.operator_ptr >= lowest_op_priority Call unstack_operator End Return unstack_operator : the_operator = op_token.operator_ptr operator_ptr = operator_ptr - 1 op_1 = op_number.operand_ptr If Pos(the_operator, "+-/*") /= 0 Then Do operand_ptr = operand_ptr - 1 op_2 = op_1 op_1 = op_number.operand_ptr End Select When the_operator = "+" Then op_1 = op_1 + op_2 When the_operator = "-" Then op_1 = op_1 - op_2 When the_operator = "*" Then op_1 = op_1 * op_2 When the_operator = "/" Then op_1 = op_1 / op_2 When the_operator = end_mark_token Then Say op_1 /* Echo result value */ Otherwise Do Say "Internal Error" Call raise_exception (exception_event) End End op_number.operand_ptr = op_1 Return /************************** UNSTACK GE OPERATORS *************************/ unstack_ge_operators: Do While op_priority.operator_ptr >= the_priority Call unstack_operator End Return /************************** UNSTACK IF END MARK **************************/ unstack_if_end_mark: If op_token.operator_ptr = end_mark_token Then Do Call unstack_operator End Else Do Say "Right parenthesis is missing" Call raise_exception (exception_event) End Return /************************** SIGNAL INVALID TOKEN *************************/ signal_invalid_token: Say "Token is invalid at this point:" the_token Return /************************** SIGNAL TOKEN MISSING *************************/ signal_token_missing: Say "Unexpected end of expression" Return /*************************** GET EXTERNAL EVENT **************************/ get_external_event: Return /************************* TERMINATE THE PROGRAM ************************/ terminate_the_program: the_next_event = terminate_event Return