blob: 07f61e964a7afeaa9e41572363c1a5295d51e86b [file] [log] [blame]
Akron22322ec2025-05-21 11:17:30 +02001package parser
2
3import (
4 "testing"
5
Akronfa55bb22025-05-26 15:10:42 +02006 "github.com/KorAP/KoralPipe-TermMapper/ast"
Akron22322ec2025-05-21 11:17:30 +02007 "github.com/stretchr/testify/assert"
8 "github.com/stretchr/testify/require"
9)
10
11func TestGrammarParserSimpleTerm(t *testing.T) {
12 tests := []struct {
13 name string
14 input string
15 defaultFoundry string
16 defaultLayer string
17 expected *SimpleTerm
18 expectError bool
19 }{
20 {
21 name: "Foundry layer key value",
22 input: "[opennlp/p=PIDAT:new]",
23 defaultFoundry: "opennlp",
24 defaultLayer: "p",
25 expected: &SimpleTerm{
26 WithFoundryLayer: &FoundryLayerTerm{
27 Foundry: "opennlp",
28 Layer: "p",
29 Key: "PIDAT",
30 Value: "new",
31 },
32 },
33 },
34 {
35 name: "Foundry layer key",
36 input: "[opennlp/p=PIDAT]",
37 defaultFoundry: "opennlp",
38 defaultLayer: "p",
39 expected: &SimpleTerm{
40 WithFoundryLayer: &FoundryLayerTerm{
41 Foundry: "opennlp",
42 Layer: "p",
43 Key: "PIDAT",
44 },
45 },
46 },
47 {
48 name: "Layer key",
49 input: "[p=PIDAT]",
50 defaultFoundry: "opennlp",
51 defaultLayer: "p",
52 expected: &SimpleTerm{
53 WithLayer: &LayerTerm{
54 Layer: "p",
55 Key: "PIDAT",
56 },
57 },
58 },
59 {
60 name: "Simple key",
61 input: "[PIDAT]",
62 defaultFoundry: "opennlp",
63 defaultLayer: "p",
64 expected: &SimpleTerm{
65 SimpleKey: &KeyTerm{
66 Key: "PIDAT",
67 },
68 },
69 },
Akron121c66e2025-06-02 16:34:05 +020070 {
71 name: "Special symbol",
72 input: "[$\\(]",
73 defaultFoundry: "opennlp",
74 defaultLayer: "p",
75 expected: &SimpleTerm{
76 SimpleKey: &KeyTerm{
77 Key: "$(",
78 },
79 },
80 },
81 {
82 name: "Multiple escaped characters",
83 input: "[\\&\\|\\=]",
84 defaultFoundry: "opennlp",
85 defaultLayer: "p",
86 expected: &SimpleTerm{
87 SimpleKey: &KeyTerm{
88 Key: "&|=",
89 },
90 },
91 },
Akroncc25e932025-06-02 19:39:43 +020092 {
93 name: "Foundry wildcard key",
94 input: "[opennlp/*=PIDAT]",
95 defaultFoundry: "opennlp",
96 defaultLayer: "p",
97 expected: &SimpleTerm{
98 WithFoundryWildcard: &FoundryWildcardTerm{
99 Foundry: "opennlp",
100 Key: "PIDAT",
101 },
102 },
103 },
Akron22322ec2025-05-21 11:17:30 +0200104 }
105
106 for _, tt := range tests {
107 t.Run(tt.name, func(t *testing.T) {
108 parser, err := NewGrammarParser(tt.defaultFoundry, tt.defaultLayer)
109 require.NoError(t, err)
110
Akronbb5065f2025-05-21 12:44:05 +0200111 grammar, err := parser.tokenParser.ParseString("", tt.input)
Akron22322ec2025-05-21 11:17:30 +0200112 if tt.expectError {
113 assert.Error(t, err)
114 return
115 }
116 require.NoError(t, err)
Akronbb5065f2025-05-21 12:44:05 +0200117 require.NotNil(t, grammar.Token, "Expected token expression")
Akron121c66e2025-06-02 16:34:05 +0200118
119 // For testing purposes, unescape the key in the simple term
120 if grammar.Token.Expr.First.Simple.SimpleKey != nil {
121 grammar.Token.Expr.First.Simple.SimpleKey.Key = unescapeString(grammar.Token.Expr.First.Simple.SimpleKey.Key)
122 }
123
Akron22322ec2025-05-21 11:17:30 +0200124 assert.Equal(t, tt.expected, grammar.Token.Expr.First.Simple)
125 })
126 }
127}
128
Akron6b4c9eb2025-07-03 14:31:58 +0200129// TestGrammarParser was removed as the Parse method is no longer supported
130// The functionality is now only available through ParseMapping method
Akronbb5065f2025-05-21 12:44:05 +0200131
132func TestMappingRules(t *testing.T) {
133 tests := []struct {
134 name string
135 input string
136 expected *MappingResult
137 wantErr bool
138 }{
139 {
140 name: "Simple PIDAT mapping",
141 input: "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]",
142 expected: &MappingResult{
143 Upper: &ast.Token{
144 Wrap: &ast.Term{
145 Key: "PIDAT",
146 Match: ast.MatchEqual,
147 },
148 },
149 Lower: &ast.Token{
150 Wrap: &ast.TermGroup{
151 Relation: ast.AndRelation,
152 Operands: []ast.Node{
153 &ast.Term{
154 Foundry: "opennlp",
155 Layer: "p",
156 Key: "PIDAT",
157 Match: ast.MatchEqual,
158 },
159 &ast.Term{
160 Foundry: "opennlp",
161 Layer: "p",
162 Key: "AdjType",
163 Value: "Pdt",
164 Match: ast.MatchEqual,
165 },
166 },
167 },
168 },
169 },
170 },
171 {
172 name: "PAV mapping",
173 input: "[PAV] <> [ADV & PronType:Dem]",
174 expected: &MappingResult{
175 Upper: &ast.Token{
176 Wrap: &ast.Term{
177 Key: "PAV",
178 Match: ast.MatchEqual,
179 },
180 },
181 Lower: &ast.Token{
182 Wrap: &ast.TermGroup{
183 Relation: ast.AndRelation,
184 Operands: []ast.Node{
185 &ast.Term{
186 Key: "ADV",
187 Match: ast.MatchEqual,
188 },
189 &ast.Term{
190 Key: "PronType",
191 Value: "Dem",
192 Match: ast.MatchEqual,
193 },
194 },
195 },
196 },
197 },
198 },
199 {
Akron76b87972025-06-02 16:59:59 +0200200 name: "PAV mapping with special character",
201 input: "[$\\(] <> [ADV & PronType:Dem]",
202 expected: &MappingResult{
203 Upper: &ast.Token{
204 Wrap: &ast.Term{
205 Key: "$(",
206 Match: ast.MatchEqual,
207 },
208 },
209 Lower: &ast.Token{
210 Wrap: &ast.TermGroup{
211 Relation: ast.AndRelation,
212 Operands: []ast.Node{
213 &ast.Term{
214 Key: "ADV",
215 Match: ast.MatchEqual,
216 },
217 &ast.Term{
218 Key: "PronType",
219 Value: "Dem",
220 Match: ast.MatchEqual,
221 },
222 },
223 },
224 },
225 },
226 },
Akron6b4c9eb2025-07-03 14:31:58 +0200227 // Additional tests to cover functionality from removed TestGrammarParser
228 {
229 name: "Simple term with foundry and layer",
230 input: "[opennlp/p=PIDAT] <> [PIDAT]",
231 expected: &MappingResult{
232 Upper: &ast.Token{
233 Wrap: &ast.Term{
234 Foundry: "opennlp",
235 Layer: "p",
236 Key: "PIDAT",
237 Match: ast.MatchEqual,
238 },
239 },
240 Lower: &ast.Token{
241 Wrap: &ast.Term{
242 Key: "PIDAT",
243 Match: ast.MatchEqual,
244 },
245 },
246 },
247 },
248 {
249 name: "Term group with and relation",
250 input: "[opennlp/p=PIDAT & opennlp/p=AdjType:Pdt] <> [PIDAT]",
251 expected: &MappingResult{
252 Upper: &ast.Token{
253 Wrap: &ast.TermGroup{
254 Operands: []ast.Node{
255 &ast.Term{
256 Foundry: "opennlp",
257 Layer: "p",
258 Key: "PIDAT",
259 Match: ast.MatchEqual,
260 },
261 &ast.Term{
262 Foundry: "opennlp",
263 Layer: "p",
264 Key: "AdjType",
265 Value: "Pdt",
266 Match: ast.MatchEqual,
267 },
268 },
269 Relation: ast.AndRelation,
270 },
271 },
272 Lower: &ast.Token{
273 Wrap: &ast.Term{
274 Key: "PIDAT",
275 Match: ast.MatchEqual,
276 },
277 },
278 },
279 },
280 {
281 name: "Term group with or relation",
282 input: "[opennlp/p=PronType:Ind | opennlp/p=PronType:Neg] <> [PRON]",
283 expected: &MappingResult{
284 Upper: &ast.Token{
285 Wrap: &ast.TermGroup{
286 Operands: []ast.Node{
287 &ast.Term{
288 Foundry: "opennlp",
289 Layer: "p",
290 Key: "PronType",
291 Value: "Ind",
292 Match: ast.MatchEqual,
293 },
294 &ast.Term{
295 Foundry: "opennlp",
296 Layer: "p",
297 Key: "PronType",
298 Value: "Neg",
299 Match: ast.MatchEqual,
300 },
301 },
302 Relation: ast.OrRelation,
303 },
304 },
305 Lower: &ast.Token{
306 Wrap: &ast.Term{
307 Key: "PRON",
308 Match: ast.MatchEqual,
309 },
310 },
311 },
312 },
313 {
314 name: "Complex term group with nested parentheses",
315 input: "[opennlp/p=PIDAT & (opennlp/p=PronType:Ind | opennlp/p=PronType:Neg)] <> [COMPLEX]",
316 expected: &MappingResult{
317 Upper: &ast.Token{
318 Wrap: &ast.TermGroup{
319 Operands: []ast.Node{
320 &ast.Term{
321 Foundry: "opennlp",
322 Layer: "p",
323 Key: "PIDAT",
324 Match: ast.MatchEqual,
325 },
326 &ast.TermGroup{
327 Operands: []ast.Node{
328 &ast.Term{
329 Foundry: "opennlp",
330 Layer: "p",
331 Key: "PronType",
332 Value: "Ind",
333 Match: ast.MatchEqual,
334 },
335 &ast.Term{
336 Foundry: "opennlp",
337 Layer: "p",
338 Key: "PronType",
339 Value: "Neg",
340 Match: ast.MatchEqual,
341 },
342 },
343 Relation: ast.OrRelation,
344 },
345 },
346 Relation: ast.AndRelation,
347 },
348 },
349 Lower: &ast.Token{
350 Wrap: &ast.Term{
351 Key: "COMPLEX",
352 Match: ast.MatchEqual,
353 },
354 },
355 },
356 },
357 {
358 name: "Wildcard pattern",
359 input: "[opennlp/*=PIDAT] <> [PIDAT]",
360 expected: &MappingResult{
361 Upper: &ast.Token{
362 Wrap: &ast.Term{
363 Foundry: "opennlp",
364 Layer: "",
365 Key: "PIDAT",
366 Match: ast.MatchEqual,
367 },
368 },
369 Lower: &ast.Token{
370 Wrap: &ast.Term{
371 Key: "PIDAT",
372 Match: ast.MatchEqual,
373 },
374 },
375 },
376 },
Akron76b87972025-06-02 16:59:59 +0200377 {
Akronbb5065f2025-05-21 12:44:05 +0200378 name: "Invalid mapping syntax",
379 input: "[PAV] -> [ADV]",
380 wantErr: true,
381 },
382 {
383 name: "Missing closing bracket",
384 input: "[PAV <> [ADV]",
385 wantErr: true,
386 },
387 }
388
389 parser, err := NewGrammarParser("", "")
390 assert.NoError(t, err)
391
392 for _, tt := range tests {
393 t.Run(tt.name, func(t *testing.T) {
394 result, err := parser.ParseMapping(tt.input)
395 if tt.wantErr {
396 assert.Error(t, err)
397 return
398 }
Akroncc25e932025-06-02 19:39:43 +0200399 assert.NoError(t, err, "Input: %s", tt.input)
Akronbb5065f2025-05-21 12:44:05 +0200400 assert.Equal(t, tt.expected, result)
401 })
402 }
403}