blob: d9e553480ffda1f74d9f6096b582c8d5f71aa002 [file] [log] [blame]
Akron22322ec2025-05-21 11:17:30 +02001package parser
2
3import (
4 "testing"
5
Akronc79d87e2025-05-26 15:03:27 +02006 "github.com/KorAP/KoralPipe-TermMapper2/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 },
70 }
71
72 for _, tt := range tests {
73 t.Run(tt.name, func(t *testing.T) {
74 parser, err := NewGrammarParser(tt.defaultFoundry, tt.defaultLayer)
75 require.NoError(t, err)
76
Akronbb5065f2025-05-21 12:44:05 +020077 grammar, err := parser.tokenParser.ParseString("", tt.input)
Akron22322ec2025-05-21 11:17:30 +020078 if tt.expectError {
79 assert.Error(t, err)
80 return
81 }
82 require.NoError(t, err)
Akronbb5065f2025-05-21 12:44:05 +020083 require.NotNil(t, grammar.Token, "Expected token expression")
Akron22322ec2025-05-21 11:17:30 +020084 assert.Equal(t, tt.expected, grammar.Token.Expr.First.Simple)
85 })
86 }
87}
88
89func TestGrammarParser(t *testing.T) {
90 tests := []struct {
91 name string
92 input string
93 defaultFoundry string
94 defaultLayer string
95 expected ast.Node
96 expectError bool
97 }{
98 {
99 name: "Simple term with foundry and layer",
100 input: "[opennlp/p=PIDAT]",
101 defaultFoundry: "opennlp",
102 defaultLayer: "p",
103 expected: &ast.Token{
104 Wrap: &ast.Term{
105 Foundry: "opennlp",
106 Key: "PIDAT",
107 Layer: "p",
108 Match: ast.MatchEqual,
109 },
110 },
111 },
112 {
113 name: "Term group with and relation",
114 input: "[opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]",
115 defaultFoundry: "opennlp",
116 defaultLayer: "p",
117 expected: &ast.Token{
118 Wrap: &ast.TermGroup{
119 Operands: []ast.Node{
120 &ast.Term{
121 Foundry: "opennlp",
122 Key: "PIDAT",
123 Layer: "p",
124 Match: ast.MatchEqual,
125 },
126 &ast.Term{
127 Foundry: "opennlp",
128 Key: "AdjType",
129 Layer: "p",
130 Match: ast.MatchEqual,
131 Value: "Pdt",
132 },
133 },
134 Relation: ast.AndRelation,
135 },
136 },
137 },
138 {
139 name: "Term group with or relation",
140 input: "[opennlp/p=PronType:Ind | opennlp/p=PronType:Neg]",
141 defaultFoundry: "opennlp",
142 defaultLayer: "p",
143 expected: &ast.Token{
144 Wrap: &ast.TermGroup{
145 Operands: []ast.Node{
146 &ast.Term{
147 Foundry: "opennlp",
148 Key: "PronType",
149 Layer: "p",
150 Match: ast.MatchEqual,
151 Value: "Ind",
152 },
153 &ast.Term{
154 Foundry: "opennlp",
155 Key: "PronType",
156 Layer: "p",
157 Match: ast.MatchEqual,
158 Value: "Neg",
159 },
160 },
161 Relation: ast.OrRelation,
162 },
163 },
164 },
165 {
166 name: "Complex term group",
167 input: "[opennlp/p=PIDAT & (opennlp/p=PronType:Ind | opennlp/p=PronType:Neg)]",
168 defaultFoundry: "opennlp",
169 defaultLayer: "p",
170 expected: &ast.Token{
171 Wrap: &ast.TermGroup{
172 Operands: []ast.Node{
173 &ast.Term{
174 Foundry: "opennlp",
175 Key: "PIDAT",
176 Layer: "p",
177 Match: ast.MatchEqual,
178 },
179 &ast.TermGroup{
180 Operands: []ast.Node{
181 &ast.Term{
182 Foundry: "opennlp",
183 Key: "PronType",
184 Layer: "p",
185 Match: ast.MatchEqual,
186 Value: "Ind",
187 },
188 &ast.Term{
189 Foundry: "opennlp",
190 Key: "PronType",
191 Layer: "p",
192 Match: ast.MatchEqual,
193 Value: "Neg",
194 },
195 },
196 Relation: ast.OrRelation,
197 },
198 },
199 Relation: ast.AndRelation,
200 },
201 },
202 },
203 }
204
205 for _, tt := range tests {
206 t.Run(tt.name, func(t *testing.T) {
207 parser, err := NewGrammarParser(tt.defaultFoundry, tt.defaultLayer)
208 require.NoError(t, err)
209
210 result, err := parser.Parse(tt.input)
211 if tt.expectError {
212 assert.Error(t, err)
213 return
214 }
215 require.NoError(t, err)
216 assert.Equal(t, tt.expected, result)
217 })
218 }
219}
Akronbb5065f2025-05-21 12:44:05 +0200220
221func TestMappingRules(t *testing.T) {
222 tests := []struct {
223 name string
224 input string
225 expected *MappingResult
226 wantErr bool
227 }{
228 {
229 name: "Simple PIDAT mapping",
230 input: "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]",
231 expected: &MappingResult{
232 Upper: &ast.Token{
233 Wrap: &ast.Term{
234 Key: "PIDAT",
235 Match: ast.MatchEqual,
236 },
237 },
238 Lower: &ast.Token{
239 Wrap: &ast.TermGroup{
240 Relation: ast.AndRelation,
241 Operands: []ast.Node{
242 &ast.Term{
243 Foundry: "opennlp",
244 Layer: "p",
245 Key: "PIDAT",
246 Match: ast.MatchEqual,
247 },
248 &ast.Term{
249 Foundry: "opennlp",
250 Layer: "p",
251 Key: "AdjType",
252 Value: "Pdt",
253 Match: ast.MatchEqual,
254 },
255 },
256 },
257 },
258 },
259 },
260 {
261 name: "PAV mapping",
262 input: "[PAV] <> [ADV & PronType:Dem]",
263 expected: &MappingResult{
264 Upper: &ast.Token{
265 Wrap: &ast.Term{
266 Key: "PAV",
267 Match: ast.MatchEqual,
268 },
269 },
270 Lower: &ast.Token{
271 Wrap: &ast.TermGroup{
272 Relation: ast.AndRelation,
273 Operands: []ast.Node{
274 &ast.Term{
275 Key: "ADV",
276 Match: ast.MatchEqual,
277 },
278 &ast.Term{
279 Key: "PronType",
280 Value: "Dem",
281 Match: ast.MatchEqual,
282 },
283 },
284 },
285 },
286 },
287 },
288 {
289 name: "Invalid mapping syntax",
290 input: "[PAV] -> [ADV]",
291 wantErr: true,
292 },
293 {
294 name: "Missing closing bracket",
295 input: "[PAV <> [ADV]",
296 wantErr: true,
297 },
298 }
299
300 parser, err := NewGrammarParser("", "")
301 assert.NoError(t, err)
302
303 for _, tt := range tests {
304 t.Run(tt.name, func(t *testing.T) {
305 result, err := parser.ParseMapping(tt.input)
306 if tt.wantErr {
307 assert.Error(t, err)
308 return
309 }
310 assert.NoError(t, err)
311 assert.Equal(t, tt.expected, result)
312 })
313 }
314}