note description: "Class to replace variables in an expression with special format" author: "" date: "$Date$" revision: "$Revision$" class EPA_TRANSITION_EXPRESSION_REWRITER inherit ETR_AST_STRUCTURE_PRINTER export{NONE} all {ANY} is_valid redefine process_like_id_as, process_instr_call_as, process_id_as, process_expr_call_as, process_creation_as, process_access_id_as, process_access_feat_as, process_nested_as, process_nested_expr_as, process_current_as, output, process_result_as, process_void_as end EPA_EXPRESSION_VISITOR EPA_EXPRESSION_VALUE_VISITOR create make feature {NONE} -- Initialization make -- Initialize Current. do create output.make end feature -- Basic operations ast_text (a_ast: AST_EIFFEL; a_replacements: like replacements): STRING -- Text of `a_ast' with `a_replacements' do if should_keep_encountered_names then create encountered_names.make else encountered_names := Void end output.reset replacements := a_replacements last_was_unqualified := true a_ast.process (Current) Result := output.string_representation.twin end expression_text (a_expr: EPA_EXPRESSION; a_replacements: like replacements): STRING -- Text of `a_expr' with `a_replacements' do if should_keep_encountered_names then create encountered_names.make else encountered_names := Void end output.reset replacements := a_replacements last_was_unqualified := true a_expr.process (Current) Result := output.string_representation.twin end expression_value_text (a_expr_value: EPA_EXPRESSION_VALUE; a_replacements: like replacements): STRING -- Text of `a_expr_value' with `a_replacements' do if should_keep_encountered_names then create encountered_names.make else encountered_names := Void end output.reset replacements := a_replacements last_was_unqualified := true a_expr_value.process (Current) Result := output.string_representation.twin end encountered_names: detachable LINKED_LIST [STRING] -- List of replaced names, appearing in the same order as they appear in the original expression -- Only has effect if `should_keep_encountered_names' is True, otherwise, it is set to Void. feature -- Status report should_keep_encountered_names: BOOLEAN -- Should encountered names (that are replaced) be kept? -- If so, those names are put into `encounted_names'. -- Default: False should_add_explicit_target: BOOLEAN -- Should implicit calls be transfered to explicit calls? -- E.g. size > 0 ==> Current.size > 0 set_should_explici_target (a_flag: BOOLEAN) -- do should_add_explicit_target := a_flag end feature -- Setting set_should_keep_encountered_names (b: BOOLEAN) -- Set `should_keep_encountered_names' with `b'. do should_keep_encountered_names := b ensure should_keep_encountered_names_set: should_keep_encountered_names = b end feature {AST_EIFFEL} -- Processing process_like_id_as (l_as: LIKE_ID_AS) do last_was_unqualified := true Precursor (l_as) end process_instr_call_as (l_as: INSTR_CALL_AS) do last_was_unqualified := true Precursor(l_as) end process_expr_call_as (l_as: EXPR_CALL_AS) do last_was_unqualified := true Precursor(l_as) end process_creation_as (l_as: CREATION_AS) do last_was_unqualified := true output.append_string (ti_create_keyword+ti_Space) if processing_needed (l_as.type, l_as, 2) then output.append_string(ti_l_curly) process_child (l_as.type, l_as, 2) output.append_string(ti_r_curly+ti_Space) end process(l_as.target, l_as, 1) last_was_unqualified := false if processing_needed (l_as.call, l_as, 3) then output.append_string (ti_dot) process_child (l_as.call, l_as, 3) end output.append_string(ti_New_line) end process_access_id_as (l_as: ACCESS_ID_AS) do process_access_feat_as (l_as) end process_access_feat_as (l_as: ACCESS_FEAT_AS) do if last_was_unqualified then process_access_name (l_as.access_name) else output.append_string (l_as.access_name) end last_was_unqualified := true if processing_needed (l_as.parameters,l_as,1) then output.append_string (ti_Space+ti_l_parenthesis) process_child_list(l_as.parameters, ti_comma+ti_Space, l_as, 1) output.append_string (ti_r_parenthesis) end end process_id_as (l_as: ID_AS) do -- if last_was_unqualified then -- process_access_name (l_as.name) -- else output.append_string (l_as.name) -- end end process_nested_expr_as (l_as: NESTED_EXPR_AS) do if attached {BRACKET_AS}l_as.target then process_child(l_as.target, l_as, 1) else output.append_string (ti_l_parenthesis) process_child(l_as.target, l_as, 1) output.append_string (ti_r_parenthesis) end output.append_string (ti_dot) last_was_unqualified := false process_child(l_as.message, l_as, 2) end process_nested_as (l_as: NESTED_AS) do if not last_was_unqualified then process_child (l_as.target, l_as, 1) output.append_string (ti_dot) process_child (l_as.message, l_as, 2) else process_child (l_as.target, l_as, 1) last_was_unqualified := false output.append_string (ti_dot) process_child (l_as.message, l_as, 2) last_was_unqualified := true end end process_current_as (l_as: CURRENT_AS) do process_access_name (ti_current) end process_result_as (l_as: RESULT_AS) do process_access_name (ti_result) end process_void_as (l_as: VOID_AS) do output.append_string (ti_void) end feature {NONE} -- Implementation process_access_name (a_name: STRING) -- Process accessed variable named `a_name'. local l_name: STRING l_encountered: like encountered_names do l_name := a_name if attached {STRING} replacements.item (l_name) as l_new_name then l_encountered := encountered_names if l_encountered /= Void then l_encountered.extend (l_name) end output.append_string (l_new_name) else if should_add_explicit_target and then replacements.has ("Current") and then is_valid_eiffel_feature_access (l_name) then output.append_string (replacements.item ("Current")) output.append_string (".") l_encountered := encountered_names if l_encountered /= Void then l_encountered.extend ("Current") end end output.append_string (a_name) end end is_valid_eiffel_feature_access (a_str: STRING): BOOLEAN -- local l_index: INTEGER l_char: CHARACTER do if a_str = Void or else a_str.is_empty then Result := False else from l_index := 1 Result := True until l_index > a_str.count or else not Result loop l_char := a_str[l_index] if l_index = 1 and then not l_char.is_alpha and then l_char /= '_' then Result := False elseif l_index > 1 and then not l_char.is_alpha_numeric and then l_char /= '_' then Result := False end l_index := l_index + 1 end end Result := Result and (a_str.as_lower.same_string_general ("void")) end last_was_unqualified: BOOLEAN -- Are we in an unqualified call? replacements: HASH_TABLE [STRING, STRING] -- Table of expression replacements -- Key is the expression to be replaced, value is the new string. output: ETR_AST_STRING_OUTPUT -- Output of current visitor feature {NONE} -- Process/expression process_ast_expression (a_expr: EPA_AST_EXPRESSION) -- Process `a_expr'. do if attached{AST_EIFFEL} a_expr.ast as l_ast then l_ast.process (Current) end end process_universal_quantified_expression (a_expr: EPA_UNIVERSAL_QUANTIFIED_EXPRESSION) -- Process `a_expr'. do process_quantified_expression (a_expr) end process_existential_quantified_expression (a_expr: EPA_EXISTENTIAL_QUANTIFIED_EXPRESSION) -- Process `a_expr'. do process_quantified_expression (a_expr) end process_quantified_expression (a_expr: EPA_QUANTIFIED_EXPRESSION) -- Process `a_expr'. local l_str: STRING do safe_process (a_expr.ast) l_str := a_expr.text_with_predicate (output.string_representation) output.reset output.append_string (l_str) end feature{NONE} -- Process equationn values feature -- Process process_boolean_value (a_value: EPA_BOOLEAN_VALUE) -- Process `a_value'. do output.append_string (a_value.item.out) end process_random_boolean_value (a_value: EPA_RANDOM_BOOLEAN_VALUE) -- Process `a_value'. do output.append_string (a_value.item.out) end process_integer_value (a_value: EPA_INTEGER_VALUE) -- Process `a_value'. do output.append_string (a_value.item.out) end process_real_value (a_value: EPA_REAL_VALUE) -- Process `a_value'. do output.append_string (a_value.item.out) end process_pointer_value (a_value: EPA_POINTER_VALUE) -- Process `a_value'. do output.append_string (a_value.item) end process_random_integer_value (a_value: EPA_RANDOM_INTEGER_VALUE) -- Process `a_value'. do output.append_string (a_value.item.out) end process_nonsensical_value (a_value: EPA_NONSENSICAL_VALUE) -- Process `a_value'. do output.append_string (a_value.item.out) end process_void_value (a_value: EPA_VOID_VALUE) -- Process `a_value'. do output.append_string (ti_void) end process_any_value (a_value: EPA_ANY_VALUE) -- Process `a_value'. do check should_not_be_here: False end end process_reference_value (a_value: EPA_REFERENCE_VALUE) -- Process `a_value'. do output.append_string (once "$") output.append_string (a_value.item) -- check should_not_be_here: False end end process_ast_expression_value (a_value: EPA_AST_EXPRESSION_VALUE) -- Process `a_value'. do a_value.item.process (Current) end process_string_value (a_value: EPA_STRING_VALUE) -- Process `a_value' do output.append_string (once "%"") output.append_string (a_value.string_value) output.append_string (once "%"") end process_set_value (a_value: EPA_EXPRESSION_SET_VALUE) -- Process `a_value'. do check Should_not_be_here: False end end process_numeric_range_value (a_value: EPA_NUMERIC_RANGE_VALUE) -- Process `a_value'. do end end