Fortran · 5331 bytes Raw Blame History
1 module bracket_matching_module
2 use text_buffer_module
3 implicit none
4 private
5
6 public :: find_matching_bracket, is_opening_bracket, is_closing_bracket
7 public :: get_bracket_pair
8
9 contains
10
11 logical function is_opening_bracket(ch)
12 character(len=1), intent(in) :: ch
13 is_opening_bracket = (ch == '(' .or. ch == '[' .or. ch == '{')
14 end function is_opening_bracket
15
16 logical function is_closing_bracket(ch)
17 character(len=1), intent(in) :: ch
18 is_closing_bracket = (ch == ')' .or. ch == ']' .or. ch == '}')
19 end function is_closing_bracket
20
21 character(len=1) function get_bracket_pair(ch)
22 character(len=1), intent(in) :: ch
23
24 select case(ch)
25 case('(')
26 get_bracket_pair = ')'
27 case(')')
28 get_bracket_pair = '('
29 case('[')
30 get_bracket_pair = ']'
31 case(']')
32 get_bracket_pair = '['
33 case('{')
34 get_bracket_pair = '}'
35 case('}')
36 get_bracket_pair = '{'
37 case default
38 get_bracket_pair = ''
39 end select
40 end function get_bracket_pair
41
42 subroutine find_matching_bracket(buffer, start_line, start_col, &
43 found, match_line, match_col)
44 type(buffer_t), intent(in) :: buffer
45 integer, intent(in) :: start_line, start_col
46 logical, intent(out) :: found
47 integer, intent(out) :: match_line, match_col
48 character(len=:), allocatable :: line
49 character(len=1) :: start_char, target_char
50 integer :: depth, current_line, current_col
51 integer :: line_count, line_len
52 logical :: search_forward
53
54 found = .false.
55 match_line = 0
56 match_col = 0
57
58 ! Get the character at the starting position
59 line = buffer_get_line(buffer, start_line)
60 if (start_col < 1 .or. start_col > len(line)) then
61 if (allocated(line)) deallocate(line)
62 return
63 end if
64
65 start_char = line(start_col:start_col)
66 if (allocated(line)) deallocate(line)
67
68 ! Check if it's a bracket
69 if (.not. is_opening_bracket(start_char) .and. &
70 .not. is_closing_bracket(start_char)) then
71 return
72 end if
73
74 ! Get the matching bracket character
75 target_char = get_bracket_pair(start_char)
76 if (target_char == '') return
77
78 ! Determine search direction
79 search_forward = is_opening_bracket(start_char)
80
81 ! Initialize depth counter
82 depth = 1
83 line_count = buffer_get_line_count(buffer)
84
85 if (search_forward) then
86 ! Search forward for closing bracket
87 current_line = start_line
88 current_col = start_col + 1
89
90 do while (current_line <= line_count)
91 line = buffer_get_line(buffer, current_line)
92 line_len = len(line)
93
94 ! If we're starting a new line, reset column
95 if (current_line > start_line) then
96 current_col = 1
97 end if
98
99 do while (current_col <= line_len)
100 if (line(current_col:current_col) == start_char) then
101 depth = depth + 1
102 else if (line(current_col:current_col) == target_char) then
103 depth = depth - 1
104 if (depth == 0) then
105 found = .true.
106 match_line = current_line
107 match_col = current_col
108 if (allocated(line)) deallocate(line)
109 return
110 end if
111 end if
112 current_col = current_col + 1
113 end do
114
115 if (allocated(line)) deallocate(line)
116 current_line = current_line + 1
117 end do
118 else
119 ! Search backward for opening bracket
120 current_line = start_line
121 current_col = start_col - 1
122
123 do while (current_line >= 1)
124 line = buffer_get_line(buffer, current_line)
125 line_len = len(line)
126
127 ! If we're starting a new line, reset column to end
128 if (current_line < start_line) then
129 current_col = line_len
130 end if
131
132 do while (current_col >= 1)
133 if (line(current_col:current_col) == start_char) then
134 depth = depth + 1
135 else if (line(current_col:current_col) == target_char) then
136 depth = depth - 1
137 if (depth == 0) then
138 found = .true.
139 match_line = current_line
140 match_col = current_col
141 if (allocated(line)) deallocate(line)
142 return
143 end if
144 end if
145 current_col = current_col - 1
146 end do
147
148 if (allocated(line)) deallocate(line)
149 current_line = current_line - 1
150 end do
151 end if
152 end subroutine find_matching_bracket
153
154 end module bracket_matching_module