6
#include "llama-grammar.h"
10
static const char * type_str(llama_gretype type) {
12
case LLAMA_GRETYPE_CHAR: return "LLAMA_GRETYPE_CHAR";
13
case LLAMA_GRETYPE_CHAR_NOT: return "LLAMA_GRETYPE_CHAR_NOT";
14
case LLAMA_GRETYPE_CHAR_ALT: return "LLAMA_GRETYPE_CHAR_ALT";
15
case LLAMA_GRETYPE_CHAR_RNG_UPPER: return "LLAMA_GRETYPE_CHAR_RNG_UPPER";
16
case LLAMA_GRETYPE_RULE_REF: return "LLAMA_GRETYPE_RULE_REF";
17
case LLAMA_GRETYPE_ALT: return "LLAMA_GRETYPE_ALT";
18
case LLAMA_GRETYPE_END: return "LLAMA_GRETYPE_END";
23
static void verify_parsing(const char *grammar_bytes, const std::vector<std::pair<std::string, uint32_t>> expected, const std::vector<llama_grammar_element> &expected_rules) {
25
llama_grammar_parser parsed_grammar;
26
parsed_grammar.parse(grammar_bytes);
28
std::map<uint32_t, std::string> symbol_names;
29
for (auto it = parsed_grammar.symbol_ids.begin(); it != parsed_grammar.symbol_ids.end(); ++it) {
30
symbol_names[it->second] = it->first;
33
auto print_all = [&]() {
34
fprintf(stderr, " verify_parsing(R\"\"\"(%s)\"\"\", {\n", grammar_bytes);
35
for (auto it = parsed_grammar.symbol_ids.begin(); it != parsed_grammar.symbol_ids.end(); ++it) {
36
fprintf(stderr, " {\"%s\", %u},\n", it->first.c_str(), it->second);
38
fprintf(stderr, " }, {\n");
39
for (size_t i_rule = 0; i_rule < parsed_grammar.rules.size(); i_rule++) {
40
fprintf(stderr, " // %s (index %zu)\n", symbol_names[i_rule].c_str(), i_rule);
41
auto & rule = parsed_grammar.rules[i_rule];
42
for (uint32_t i = 0; i < rule.size(); i++) {
44
fprintf(stderr, " {%s, ", type_str(rule[i].type));
45
if (rule[i].type == LLAMA_GRETYPE_CHAR || rule[i].type == LLAMA_GRETYPE_CHAR_ALT ||
46
rule[i].type == LLAMA_GRETYPE_CHAR_NOT || rule[i].type == LLAMA_GRETYPE_CHAR_RNG_UPPER) {
47
char c = rule[i].value;
49
fprintf(stderr, "'\\n'");
50
} else if (c == '\t') {
51
fprintf(stderr, "'\\t'");
52
} else if (c == '\r') {
53
fprintf(stderr, "'\\r'");
54
} else if (c == '\0') {
55
fprintf(stderr, "'\\0'");
57
fprintf(stderr, "'%c'", c);
59
} else if (rule[i].type == LLAMA_GRETYPE_RULE_REF) {
60
fprintf(stderr, "/* %s */ %u", symbol_names[rule[i].value].c_str(), rule[i].value);
62
fprintf(stderr, "%u", rule[i].value);
64
fprintf(stderr, "},\n");
67
fprintf(stderr, " });\n");
70
if (getenv("TEST_GRAMMAR_PARSER_PRINT_ALL")) {
72
fprintf(stderr, "\n");
76
fprintf(stderr, "Testing grammar:%s\n", grammar_bytes);
78
if (parsed_grammar.symbol_ids.size() != expected.size()) {
79
fprintf(stderr, "Code to update expectation (set TEST_GRAMMAR_PARSER_PRINT_ALL=1 to print all):\n");
81
assert(parsed_grammar.symbol_ids.size() == expected.size());
84
for (auto it = parsed_grammar.symbol_ids.begin(); it != parsed_grammar.symbol_ids.end(); ++it)
86
std::string key = it->first;
87
uint32_t value = it->second;
88
std::pair<std::string, uint32_t> expected_pair = expected[index];
90
// pretty print error message before asserting
91
if (expected_pair.first != key || expected_pair.second != value)
93
fprintf(stderr, "index: %u\n", index);
94
fprintf(stderr, "expected_pair: %s, %u\n", expected_pair.first.c_str(), expected_pair.second);
95
fprintf(stderr, "actual_pair: %s, %u\n", key.c_str(), value);
96
fprintf(stderr, "expected_pair != actual_pair\n");
97
fprintf(stderr, "Code to update expectation (set TEST_GRAMMAR_PARSER_PRINT_ALL=1 to print all):\n");
101
assert(expected_pair.first == key && expected_pair.second == value);
107
for (auto rule : parsed_grammar.rules)
109
// compare rule to expected rule
110
for (uint32_t i = 0; i < rule.size(); i++)
112
llama_grammar_element element = rule[i];
113
llama_grammar_element expected_element = expected_rules[index];
115
// pretty print error message before asserting
116
if (expected_element.type != element.type || expected_element.value != element.value)
118
fprintf(stderr, "index: %u\n", index);
119
fprintf(stderr, "expected_element: %s, %u\n", type_str(expected_element.type), expected_element.value);
120
fprintf(stderr, "actual_element: %s, %u\n", type_str(element.type), element.value);
121
fprintf(stderr, "expected_element != actual_element\n");
122
fprintf(stderr, "all elements:\n");
123
fprintf(stderr, "Code to update expectation (set TEST_GRAMMAR_PARSER_PRINT_ALL=1 to print all):\n");
127
assert(expected_element.type == element.type && expected_element.value == element.value);
133
static void verify_failure(const char * grammar_bytes) {
134
fprintf(stderr, "Testing expected failure:%s\n", grammar_bytes);
135
llama_grammar_parser result;
136
result.parse(grammar_bytes);
137
assert(result.rules.empty() && "should have failed");
156
{LLAMA_GRETYPE_CHAR, 'a'},
157
{LLAMA_GRETYPE_END, 0},
161
root ::= "a" | [bdx-z] | [^1-3]
166
{LLAMA_GRETYPE_CHAR, 'a'},
167
{LLAMA_GRETYPE_ALT, 0},
168
{LLAMA_GRETYPE_CHAR, 'b'},
169
{LLAMA_GRETYPE_CHAR_ALT, 'd'},
170
{LLAMA_GRETYPE_CHAR_ALT, 'x'},
171
{LLAMA_GRETYPE_CHAR_RNG_UPPER, 'z'},
172
{LLAMA_GRETYPE_ALT, 0},
173
{LLAMA_GRETYPE_CHAR_NOT, '1'},
174
{LLAMA_GRETYPE_CHAR_RNG_UPPER, '3'},
175
{LLAMA_GRETYPE_END, 0},
187
{LLAMA_GRETYPE_RULE_REF, /* a */ 1},
188
{LLAMA_GRETYPE_RULE_REF, /* root_2 */ 2},
189
{LLAMA_GRETYPE_END, 0},
191
{LLAMA_GRETYPE_CHAR, 'a'},
192
{LLAMA_GRETYPE_END, 0},
194
{LLAMA_GRETYPE_RULE_REF, /* a */ 1},
195
{LLAMA_GRETYPE_RULE_REF, /* root_2 */ 2},
196
{LLAMA_GRETYPE_ALT, 0},
197
{LLAMA_GRETYPE_END, 0},
207
{LLAMA_GRETYPE_CHAR, 'a'},
208
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
209
{LLAMA_GRETYPE_END, 0},
211
{LLAMA_GRETYPE_CHAR, 'a'},
212
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
213
{LLAMA_GRETYPE_ALT, 0},
214
{LLAMA_GRETYPE_END, 0},
226
{LLAMA_GRETYPE_RULE_REF, /* root_2 */ 2},
227
{LLAMA_GRETYPE_END, 0},
229
{LLAMA_GRETYPE_CHAR, 'a'},
230
{LLAMA_GRETYPE_END, 0},
232
{LLAMA_GRETYPE_RULE_REF, /* a */ 1},
233
{LLAMA_GRETYPE_ALT, 0},
234
{LLAMA_GRETYPE_END, 0},
244
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
245
{LLAMA_GRETYPE_END, 0},
247
{LLAMA_GRETYPE_CHAR, 'a'},
248
{LLAMA_GRETYPE_ALT, 0},
249
{LLAMA_GRETYPE_END, 0},
261
{LLAMA_GRETYPE_RULE_REF, /* root_2 */ 2},
262
{LLAMA_GRETYPE_END, 0},
264
{LLAMA_GRETYPE_CHAR, 'a'},
265
{LLAMA_GRETYPE_END, 0},
267
{LLAMA_GRETYPE_RULE_REF, /* a */ 1},
268
{LLAMA_GRETYPE_RULE_REF, /* root_2 */ 2},
269
{LLAMA_GRETYPE_ALT, 0},
270
{LLAMA_GRETYPE_END, 0},
280
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
281
{LLAMA_GRETYPE_END, 0},
283
{LLAMA_GRETYPE_CHAR, 'a'},
284
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
285
{LLAMA_GRETYPE_ALT, 0},
286
{LLAMA_GRETYPE_END, 0},
295
{LLAMA_GRETYPE_CHAR, 'a'},
296
{LLAMA_GRETYPE_CHAR, 'a'},
297
{LLAMA_GRETYPE_END, 0},
307
{LLAMA_GRETYPE_CHAR, 'a'},
308
{LLAMA_GRETYPE_CHAR, 'a'},
309
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
310
{LLAMA_GRETYPE_END, 0},
312
{LLAMA_GRETYPE_CHAR, 'a'},
313
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
314
{LLAMA_GRETYPE_ALT, 0},
315
{LLAMA_GRETYPE_END, 0},
324
{LLAMA_GRETYPE_CHAR, 'a'},
325
{LLAMA_GRETYPE_CHAR, 'a'},
326
{LLAMA_GRETYPE_CHAR, 'a'},
327
{LLAMA_GRETYPE_CHAR, 'a'},
328
{LLAMA_GRETYPE_END, 0},
339
{LLAMA_GRETYPE_CHAR, 'a'},
340
{LLAMA_GRETYPE_CHAR, 'a'},
341
{LLAMA_GRETYPE_RULE_REF, /* root_2 */ 2},
342
{LLAMA_GRETYPE_END, 0},
344
{LLAMA_GRETYPE_CHAR, 'a'},
345
{LLAMA_GRETYPE_ALT, 0},
346
{LLAMA_GRETYPE_END, 0},
348
{LLAMA_GRETYPE_CHAR, 'a'},
349
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
350
{LLAMA_GRETYPE_ALT, 0},
351
{LLAMA_GRETYPE_END, 0},
355
root ::= (expr "=" term "\n")+
356
expr ::= term ([-+*/] term)*
369
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
370
{LLAMA_GRETYPE_RULE_REF, /* root_4 */ 4},
371
{LLAMA_GRETYPE_END, 0},
373
{LLAMA_GRETYPE_RULE_REF, /* expr */ 2},
374
{LLAMA_GRETYPE_CHAR, '='},
375
{LLAMA_GRETYPE_RULE_REF, /* term */ 3},
376
{LLAMA_GRETYPE_CHAR, '\n'},
377
{LLAMA_GRETYPE_END, 0},
379
{LLAMA_GRETYPE_RULE_REF, /* term */ 3},
380
{LLAMA_GRETYPE_RULE_REF, /* expr_6 */ 6},
381
{LLAMA_GRETYPE_END, 0},
383
{LLAMA_GRETYPE_CHAR, '0'},
384
{LLAMA_GRETYPE_CHAR_RNG_UPPER, '9'},
385
{LLAMA_GRETYPE_RULE_REF, /* term_7 */ 7},
386
{LLAMA_GRETYPE_END, 0},
388
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
389
{LLAMA_GRETYPE_RULE_REF, /* root_4 */ 4},
390
{LLAMA_GRETYPE_ALT, 0},
391
{LLAMA_GRETYPE_END, 0},
393
{LLAMA_GRETYPE_CHAR, '-'},
394
{LLAMA_GRETYPE_CHAR_ALT, '+'},
395
{LLAMA_GRETYPE_CHAR_ALT, '*'},
396
{LLAMA_GRETYPE_CHAR_ALT, '/'},
397
{LLAMA_GRETYPE_RULE_REF, /* term */ 3},
398
{LLAMA_GRETYPE_END, 0},
400
{LLAMA_GRETYPE_RULE_REF, /* expr_5 */ 5},
401
{LLAMA_GRETYPE_RULE_REF, /* expr_6 */ 6},
402
{LLAMA_GRETYPE_ALT, 0},
403
{LLAMA_GRETYPE_END, 0},
405
{LLAMA_GRETYPE_CHAR, '0'},
406
{LLAMA_GRETYPE_CHAR_RNG_UPPER, '9'},
407
{LLAMA_GRETYPE_RULE_REF, /* term_7 */ 7},
408
{LLAMA_GRETYPE_ALT, 0},
409
{LLAMA_GRETYPE_END, 0},
413
root ::= (expr "=" ws term "\n")+
414
expr ::= term ([-+*/] term)*
415
term ::= ident | num | "(" ws expr ")" ws
416
ident ::= [a-z] [a-z0-9_]* ws
435
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
436
{LLAMA_GRETYPE_RULE_REF, /* root_5 */ 5},
437
{LLAMA_GRETYPE_END, 0},
439
{LLAMA_GRETYPE_RULE_REF, /* expr */ 2},
440
{LLAMA_GRETYPE_CHAR, '='},
441
{LLAMA_GRETYPE_RULE_REF, /* ws */ 3},
442
{LLAMA_GRETYPE_RULE_REF, /* term */ 4},
443
{LLAMA_GRETYPE_CHAR, '\n'},
444
{LLAMA_GRETYPE_END, 0},
446
{LLAMA_GRETYPE_RULE_REF, /* term */ 4},
447
{LLAMA_GRETYPE_RULE_REF, /* expr_7 */ 7},
448
{LLAMA_GRETYPE_END, 0},
450
{LLAMA_GRETYPE_RULE_REF, /* ws_12 */ 12},
451
{LLAMA_GRETYPE_END, 0},
453
{LLAMA_GRETYPE_RULE_REF, /* ident */ 8},
454
{LLAMA_GRETYPE_ALT, 0},
455
{LLAMA_GRETYPE_RULE_REF, /* num */ 9},
456
{LLAMA_GRETYPE_ALT, 0},
457
{LLAMA_GRETYPE_CHAR, '('},
458
{LLAMA_GRETYPE_RULE_REF, /* ws */ 3},
459
{LLAMA_GRETYPE_RULE_REF, /* expr */ 2},
460
{LLAMA_GRETYPE_CHAR, ')'},
461
{LLAMA_GRETYPE_RULE_REF, /* ws */ 3},
462
{LLAMA_GRETYPE_END, 0},
464
{LLAMA_GRETYPE_RULE_REF, /* root_1 */ 1},
465
{LLAMA_GRETYPE_RULE_REF, /* root_5 */ 5},
466
{LLAMA_GRETYPE_ALT, 0},
467
{LLAMA_GRETYPE_END, 0},
469
{LLAMA_GRETYPE_CHAR, '-'},
470
{LLAMA_GRETYPE_CHAR_ALT, '+'},
471
{LLAMA_GRETYPE_CHAR_ALT, '*'},
472
{LLAMA_GRETYPE_CHAR_ALT, '/'},
473
{LLAMA_GRETYPE_RULE_REF, /* term */ 4},
474
{LLAMA_GRETYPE_END, 0},
476
{LLAMA_GRETYPE_RULE_REF, /* expr_6 */ 6},
477
{LLAMA_GRETYPE_RULE_REF, /* expr_7 */ 7},
478
{LLAMA_GRETYPE_ALT, 0},
479
{LLAMA_GRETYPE_END, 0},
481
{LLAMA_GRETYPE_CHAR, 'a'},
482
{LLAMA_GRETYPE_CHAR_RNG_UPPER, 'z'},
483
{LLAMA_GRETYPE_RULE_REF, /* ident_10 */ 10},
484
{LLAMA_GRETYPE_RULE_REF, /* ws */ 3},
485
{LLAMA_GRETYPE_END, 0},
487
{LLAMA_GRETYPE_CHAR, '0'},
488
{LLAMA_GRETYPE_CHAR_RNG_UPPER, '9'},
489
{LLAMA_GRETYPE_RULE_REF, /* num_11 */ 11},
490
{LLAMA_GRETYPE_RULE_REF, /* ws */ 3},
491
{LLAMA_GRETYPE_END, 0},
492
// ident_10 (index 10)
493
{LLAMA_GRETYPE_CHAR, 'a'},
494
{LLAMA_GRETYPE_CHAR_RNG_UPPER, 'z'},
495
{LLAMA_GRETYPE_CHAR_ALT, '0'},
496
{LLAMA_GRETYPE_CHAR_RNG_UPPER, '9'},
497
{LLAMA_GRETYPE_CHAR_ALT, '_'},
498
{LLAMA_GRETYPE_RULE_REF, /* ident_10 */ 10},
499
{LLAMA_GRETYPE_ALT, 0},
500
{LLAMA_GRETYPE_END, 0},
502
{LLAMA_GRETYPE_CHAR, '0'},
503
{LLAMA_GRETYPE_CHAR_RNG_UPPER, '9'},
504
{LLAMA_GRETYPE_RULE_REF, /* num_11 */ 11},
505
{LLAMA_GRETYPE_ALT, 0},
506
{LLAMA_GRETYPE_END, 0},
508
{LLAMA_GRETYPE_CHAR, ' '},
509
{LLAMA_GRETYPE_CHAR_ALT, '\t'},
510
{LLAMA_GRETYPE_CHAR_ALT, '\n'},
511
{LLAMA_GRETYPE_RULE_REF, /* ws_12 */ 12},
512
{LLAMA_GRETYPE_ALT, 0},
513
{LLAMA_GRETYPE_END, 0},