-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_token.c
More file actions
145 lines (127 loc) · 4.42 KB
/
Copy pathtest_token.c
File metadata and controls
145 lines (127 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tex/tex_internal.h"
#include "tex/tex_pool.h"
#include "tex/tex_token.h"
static int tests_run = 0, tests_failed = 0;
static void assert_true(int cond, const char* msg)
{
++tests_run;
if (!cond)
{
++tests_failed;
fprintf(stderr, "FAIL: %s\n", msg);
}
}
// Collect all tokens from streaming tokenizer
static int collect_tokens(const char* buf, TeX_Token** out, UnifiedPool* pool)
{
TeX_Stream s;
tex_stream_init(&s, buf, -1);
// First pass: count tokens
int count = 0;
TeX_Token tok;
while (tex_stream_next(&s, &tok, NULL, NULL))
{
++count;
}
++count; // for EOF
// Allocate array
TeX_Token* arr = (TeX_Token*)calloc((size_t)count, sizeof(TeX_Token));
if (!arr)
return -1;
// Second pass: fill tokens
tex_stream_init(&s, buf, -1);
int i = 0;
while (tex_stream_next(&s, &arr[i], pool, NULL))
{
++i;
}
arr[i] = (TeX_Token){ .type = T_EOF, .start = s.cursor, .len = 0, .aux = 0 };
*out = arr;
return count;
}
static int str_eq_token(const TeX_Token* t, const char* s)
{
return (int)strlen(s) == t->len && strncmp(t->start, s, (size_t)t->len) == 0;
}
int main(void)
{
UnifiedPool pool;
pool_init(&pool, 4096);
// 1) "$x$" -> T_MATH_INLINE("x")
{
TeX_Token* toks = NULL;
int n = collect_tokens("$x$", &toks, &pool);
assert(toks && "collect_tokens should return valid token array");
assert_true(n >= 2, "math inline token count >= 2 (incl EOF)");
assert_true(toks[0].type == T_MATH_INLINE, "inline math token type");
assert_true(str_eq_token(&toks[0], "x"), "inline math payload 'x'");
assert_true(toks[n - 1].type == T_EOF, "EOF terminator present");
free(toks);
}
// 2) "$$x^2$$ text" -> T_MATH_DISPLAY("x^2"), T_SPACE, T_TEXT("text")
{
TeX_Token* toks = NULL;
int n = collect_tokens("$$x^2$$ text", &toks, &pool);
assert(toks && "collect_tokens should return valid token array");
assert_true(n >= 4, "display math token count >= 4");
assert_true(toks[0].type == T_MATH_DISPLAY, "display math token type");
assert_true(str_eq_token(&toks[0], "x^2"), "display math payload 'x^2'");
assert_true(toks[1].type == T_SPACE, "space after display math");
assert_true(toks[2].type == T_TEXT && str_eq_token(&toks[2], "text"), "following text token");
free(toks);
}
// 3) "a b\nc" -> T_TEXT("a"), T_SPACE, T_TEXT("b"), T_NEWLINE, T_TEXT("c")
{
TeX_Token* toks = NULL;
int n = collect_tokens("a b\nc", &toks, &pool);
assert(toks && "collect_tokens should return valid token array");
assert_true(n >= 6, "text+space+newline token count >=6");
assert_true(toks[0].type == T_TEXT && str_eq_token(&toks[0], "a"), "first word 'a'");
assert_true(toks[1].type == T_SPACE, "space token");
assert_true(toks[2].type == T_TEXT && str_eq_token(&toks[2], "b"), "second word 'b'");
assert_true(toks[3].type == T_NEWLINE, "newline token");
assert_true(toks[4].type == T_TEXT && str_eq_token(&toks[4], "c"), "third word 'c'");
free(toks);
}
// 4) "$unclosed" -> T_TEXT("$unclosed")
{
TeX_Token* toks = NULL;
int n = collect_tokens("$unclosed", &toks, &pool);
assert(toks && "collect_tokens should return valid token array");
assert_true(n >= 2, "unclosed math fallback count >=2");
assert_true(toks[0].type == T_TEXT && str_eq_token(&toks[0], "$unclosed"), "fallback as single text token");
free(toks);
}
// 5) Math content passes through verbatim (math parser handles escapes)
// Input: "$\$\{\}$" -> payload is raw "\$\{\}" (not unescaped)
{
TeX_Token* toks = NULL;
int n = collect_tokens("$\\$\\{\\}$", &toks, &pool);
assert(toks && "collect_tokens should return valid token array");
assert_true(n >= 2, "math verbatim token count >=2");
assert_true(toks[0].type == T_MATH_INLINE, "inline math token for escapes");
assert_true(str_eq_token(&toks[0], "\\$\\{\\}"), "payload verbatim (math parser handles escapes)");
free(toks);
}
// 6) Escapes in text: "price\$100" -> T_TEXT("price$100")
{
TeX_Token* toks = NULL;
int n = collect_tokens("price\\$100", &toks, &pool);
assert(toks && "collect_tokens should return valid token array");
assert_true(n >= 2, "text escape token count >=2");
assert_true(toks[0].type == T_TEXT && str_eq_token(&toks[0], "price$100"), "text escape $ handled");
free(toks);
}
pool_free(&pool);
if (tests_failed == 0)
{
printf("test_token: PASS (%d tests)\n", tests_run);
return 0;
}
printf("test_token: FAIL (%d/%d failed)\n", tests_failed, tests_run);
return 1;
}