@@ -11,10 +11,10 @@ function matcher(val::Any)
11
11
if iscall (val)
12
12
# if has two arguments and one of them is a DefSlot, create a term matcher with defslot
13
13
if length (arguments (val)) == 2 && any (x -> isa (x, DefSlot), arguments (val))
14
- return term_matcher_defslot (val)
14
+ return defslot_term_matcher_constructor (val)
15
15
# else return a normal term matcher
16
16
else
17
- return term_matcher (val)
17
+ return term_matcher_constructor (val)
18
18
end
19
19
end
20
20
@@ -40,18 +40,11 @@ function matcher(slot::Slot)
40
40
end
41
41
end
42
42
43
+ # this is called only when defslot_term_matcher finds the operation and tries
44
+ # to match it, so no default value used. So the same function as slot_matcher
45
+ # can be used
43
46
function matcher (defslot:: DefSlot )
44
- function defslot_matcher (next, data, bindings)
45
- ! islist (data) && return
46
- val = get (bindings, defslot. name, nothing )
47
- if val != = nothing
48
- if isequal (val, car (data))
49
- return next (bindings, 1 )
50
- end
51
- elseif defslot. predicate (car (data))
52
- next (assoc (bindings, defslot. name, car (data)), 1 )
53
- end
54
- end
47
+ matcher (Slot (defslot. name, defslot. predicate))
55
48
end
56
49
57
50
# returns n == offset, 0 if failed
@@ -110,7 +103,7 @@ function matcher(segment::Segment)
110
103
end
111
104
end
112
105
113
- function term_matcher (term)
106
+ function term_matcher_constructor (term)
114
107
matchers = (matcher (operation (term)), map (matcher, arguments (term))... ,)
115
108
116
109
function term_matcher (success, data, bindings)
@@ -129,7 +122,7 @@ function term_matcher(term)
129
122
end
130
123
# explenation of above 3 lines:
131
124
# car(matchers′)(b,n -> loop(drop_n(term, n), b, cdr(matchers′)), term, bindings′)
132
- # ------- next(b,n) -----------------------------
125
+ # < ------ next(b,n) ---------------------------->
133
126
# car = first element of list, cdr = rest of the list, drop_n = drop first n elements of list
134
127
# Calls the first matcher, with the "next" function being loop again but with n terms dropepd from term
135
128
# Term is a linked list (a list and a index). drop n advances the index. when the index sorpasses
@@ -140,25 +133,43 @@ function term_matcher(term)
140
133
end
141
134
end
142
135
143
-
144
- # ~x + ~!y
145
- function term_matcher_defslot (term)
146
- matchers = (matcher (operation (term)), map (matcher, arguments (term))... ) # create matchers for the operation and arguments of the term
147
-
148
- function term_matcher (success, data, bindings)
149
-
150
- ! islist (data) && return nothing # if data is not a list, return nothing
151
- if ! iscall (car (data))
152
- a = arguments (term)
153
- slot = a[findfirst (x -> isa (x, Slot), a)] # find the first slot in the term
154
- defslot = a[findfirst (x -> isa (x, DefSlot), a)] # find the first defslot in the term
155
-
156
- bindings = assoc (bindings, slot. name, car (data))
157
- bindings = assoc (bindings, defslot. name, defslot. default)
158
-
159
- return success (bindings, 1 ) # if first element is not a call, return success with bindings and 1
136
+ # creates a matcher for a term containing a defslot, such as:
137
+ # (~x + ...complicated pattern...) * ~!y
138
+ # normal part (can bee a tree) operation defslot part
139
+
140
+ # defslot_term_matcher works like this:
141
+ # checks wether data starts with the default operation.
142
+ # if yes (1): continues like term_matcher
143
+ # if no checks wether data matches the normal part
144
+ # if no returns nothing, rule is not applied
145
+ # if yes (2): adds the pair (default value name, default value) to the found bindings and
146
+ # calls the success function like term_matcher would do
147
+
148
+ function defslot_term_matcher_constructor (term)
149
+ a = arguments (term) # lenght two bc defslot term matcher is allowed only with +,* and ^, that accept two arguments
150
+ matchers = (matcher (operation (term)), map (matcher, a)... ) # create matchers for the operation and the two arguments of the term
151
+
152
+ defslot_index = findfirst (x -> isa (x, DefSlot), a) # find the defslot in the term
153
+ defslot = a[defslot_index]
154
+
155
+ function defslot_term_matcher (success, data, bindings)
156
+ # if data is not a list, return nothing
157
+ ! islist (data) && return nothing
158
+ # if data (is not a tree and is just a symbol) or (is a tree not starting with the default operation)
159
+ if ! iscall (car (data)) || (istree (car (data)) && string (defslot. operation) != string (operation (car (data))))
160
+ other_part_matcher = matchers[defslot_index== 2 ? 2 : 3 ] # find the matcher of the normal part
161
+
162
+ # checks wether it matches the normal part
163
+ # <-----------------(2)------------------------------->
164
+ bindings = other_part_matcher ((b,n) -> assoc (b, defslot. name, defslot. defaultValue), data, bindings)
165
+
166
+ if bindings === nothing
167
+ return nothing
168
+ end
169
+ return success (bindings, 1 )
160
170
end
161
171
172
+ # (1)
162
173
function loop (term, bindings′, matchers′) # Get it to compile faster
163
174
if ! islist (matchers′)
164
175
if ! islist (term)
0 commit comments