~snowball-yiddish-dev/snowball-yiddish/trunk

« back to all changes in this revision

Viewing changes to snowball/compiler/tokeniser.c

  • Committer: richard
  • Date: 2003-03-30 12:08:09 UTC
  • Revision ID: svn-v4:633ccae0-01f4-0310-8c99-d3591da6f01f:trunk:216
This module will contain only the code and build system, and documentation
for building and running the stemming library.
All sample data will be in a separate module, and the website will be in
its own module too.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include <stdio.h>   /* stderr etc */
 
3
#include <stdlib.h>  /* malloc free */
 
4
#include <string.h>  /* strlen */
 
5
#include <ctype.h>   /* isalpha etc */
 
6
#include "header.h"
 
7
 
 
8
struct system_word
 
9
{   int s_size;   /* size of system word */
 
10
    byte * s;     /* pointer to the system word */
 
11
    int code;     /* it's internal code */
 
12
};
 
13
 
 
14
 
 
15
/* ASCII collating assumed in syswords.c */
 
16
 
 
17
#include "syswords"
 
18
 
 
19
static int smaller(int a, int b) { return a < b ? a : b; }
 
20
 
 
21
extern symbol * get_input(symbol * p)
 
22
{
 
23
    char * s = b_to_s(p);
 
24
    {   FILE * input = fopen(s, "r");
 
25
        free(s);
 
26
        if (input == 0) return 0;
 
27
        {   symbol * u = create_b(STARTSIZE);
 
28
            int size = 0;
 
29
            repeat
 
30
            {   int ch = getc(input);
 
31
                if (ch == EOF) break;
 
32
                if (size >= CAPACITY(u)) u = increase_capacity(u, size/2);
 
33
                u[size++] = ch;
 
34
            }
 
35
            fclose(input);
 
36
            SIZE(u) = size; return u;
 
37
        }
 
38
    }
 
39
}
 
40
 
 
41
static void error(struct tokeniser * t, char * s1, int n, symbol * p, char * s2)
 
42
{
 
43
    if (t->error_count == 20) { fprintf(stderr, "... etc\n"); exit(1); }
 
44
    fprintf(stderr, "Line %d", t->line_number);
 
45
    if (t->get_depth > 0) fprintf(stderr, " (of included file)");
 
46
    fprintf(stderr, ": ");
 
47
    unless (s1 == 0) fprintf(stderr, "%s", s1);
 
48
    unless (p == 0)
 
49
    {   int i;
 
50
        for (i = 0; i < n; i++) fprintf(stderr, "%c", p[i]);
 
51
    }
 
52
    unless (s2 == 0) fprintf(stderr, "%s", s2);
 
53
    fprintf(stderr, "\n");
 
54
    t->error_count++;
 
55
}
 
56
 
 
57
static void error1(struct tokeniser * t, char * s)
 
58
   { error(t, s, 0,0, 0); }
 
59
 
 
60
static void error2(struct tokeniser * t, char * s)
 
61
   { error(t, "unexpected end of text after ", 0,0, s); }
 
62
 
 
63
static int compare_words(int m, symbol * p, int n, byte * q)
 
64
{   unless (m == n) return m - n;
 
65
    {   int i; for (i = 0; i < n; i++)
 
66
        {   int diff = p[i] - q[i];
 
67
            unless (diff == 0) return diff;
 
68
        }
 
69
    }
 
70
    return 0;
 
71
}
 
72
 
 
73
static int find_word(int n, symbol * p)
 
74
{   int i = 0; int j = vocab->code;
 
75
    repeat
 
76
    {   int k = i + (j - i)/2;
 
77
        struct system_word * w = vocab + k;
 
78
        int diff = compare_words(n, p, w->s_size, w->s);
 
79
        if (diff == 0) return w->code;
 
80
        if (diff < 0) j = k; else i = k;
 
81
        if (j - i == 1) break;
 
82
    }
 
83
    return -1;
 
84
}
 
85
 
 
86
static int get_number(int n, symbol * p)
 
87
{   int x = 0;
 
88
    int i; for (i = 0; i < n; i++) x = 10*x + p[i] - '0';
 
89
    return x;
 
90
}
 
91
 
 
92
static int eq_s(struct tokeniser * t, char * s)
 
93
{   int l = strlen(s);
 
94
    if (SIZE(t->p) - t->c < l) return false;
 
95
    {   int i;
 
96
        for (i = 0; i < l; i++) if (t->p[t->c + i] != s[i]) return false;
 
97
    }
 
98
    t->c += l; return true;
 
99
}
 
100
 
 
101
static int white_space(struct tokeniser * t, int ch)
 
102
{   switch (ch)
 
103
    {   case '\n': t->line_number++;
 
104
        case '\r':
 
105
        case '\t':
 
106
        case ' ': return true;
 
107
    }
 
108
    return false;
 
109
}
 
110
 
 
111
static symbol * find_in_m(struct tokeniser * t, int n, symbol * p)
 
112
{   struct m_pair * q = t->m_pairs;
 
113
    repeat
 
114
    {   if (q == 0) return 0;
 
115
        {   symbol * name = q->name;
 
116
            if (n == SIZE(name) && memcmp(name, p, n * sizeof(symbol)) == 0) return q->value;
 
117
        }
 
118
        q = q->next;
 
119
    }
 
120
}
 
121
 
 
122
static int read_literal_string(struct tokeniser * t, int c)
 
123
{   symbol * p = t->p;
 
124
    int ch;
 
125
    SIZE(t->b) = 0;
 
126
    repeat
 
127
    {   if (c >= SIZE(p)) { error2(t, "'"); return c; }
 
128
        ch = p[c];
 
129
        if (ch == '\n') { error1(t, "string not terminated"); return c; }
 
130
        c++;
 
131
        if (ch == t->m_start)
 
132
        {   int c0 = c;
 
133
            int newlines = false; /* no newlines as yet */
 
134
            int black_found = false; /* no printing chars as yet */
 
135
            repeat
 
136
            {   if (c >= SIZE(p)) { error2(t, "'"); return c; }
 
137
                ch = p[c]; c++;
 
138
                if (ch == t->m_end) break;
 
139
                unless (white_space(t, ch)) black_found = true;
 
140
                if (ch == '\n') newlines = true;
 
141
                {   if (newlines && black_found)
 
142
                    {   error1(t, "string not terminated");
 
143
                        return c;
 
144
                    }
 
145
                }
 
146
            }
 
147
            unless (newlines)
 
148
            {
 
149
                int n = c - c0 - 1;    /* macro size */
 
150
                int firstch = p[c0];
 
151
                symbol * q = find_in_m(t, n, p + c0);
 
152
                if (q == 0)
 
153
                {   if (n == 1 && (firstch == '\'' || firstch == t->m_start))
 
154
                        t->b = add_to_b(t->b, 1, p + c0);
 
155
                    else
 
156
                        error(t, "string macro '", n, p + c0, "' undeclared");
 
157
                }
 
158
                else
 
159
                    t->b = add_to_b(t->b, SIZE(q), q);
 
160
            }
 
161
        }  else
 
162
        {   if (ch == '\'') return c;
 
163
            t->b = add_to_b(t->b, 1, p + c - 1);
 
164
        }
 
165
    }
 
166
}
 
167
 
 
168
static int next_token(struct tokeniser * t)
 
169
{   symbol * p = t->p;
 
170
    int c = t->c;
 
171
    int ch;
 
172
    int code = -1;
 
173
    repeat
 
174
    {   if (c >= SIZE(p)) { t->c = c; return -1; }
 
175
        ch = p[c];
 
176
        if (white_space(t, ch)) { c++; continue; }
 
177
        if (isalpha(ch))
 
178
        {   int c0 = c;
 
179
            while (c < SIZE(p) && (isalnum(p[c]) || p[c] == '_')) c++;
 
180
            code = find_word(c - c0, p + c0);
 
181
            if (code < 0)
 
182
            {   t->b = move_to_b(t->b, c - c0, p + c0);
 
183
                code = c_name;
 
184
            }
 
185
        } else
 
186
        if (isdigit(ch))
 
187
        {   int c0 = c;
 
188
            while (c < SIZE(p) && isdigit(p[c])) c++;
 
189
            t->number = get_number(c - c0, p + c0);
 
190
            code = c_number;
 
191
        } else
 
192
        if (ch == '\'')
 
193
        {   c = read_literal_string(t, c + 1);
 
194
            code = c_literalstring;
 
195
        } else
 
196
        {   int lim = smaller(2, SIZE(p) - c);
 
197
            int i; for (i = lim; i > 0; i--)
 
198
            {   code = find_word(i, p + c);
 
199
                if (code >= 0) { c += i; break; }
 
200
            }
 
201
        }
 
202
        if (code >= 0)
 
203
        {   t->c = c;
 
204
            return code;
 
205
        }
 
206
        error(t, "'", 1, p + c, "' unknown");
 
207
        c++;
 
208
        continue;
 
209
    }
 
210
}
 
211
 
 
212
static int next_char(struct tokeniser * t)
 
213
{   if (t->c >= SIZE(t->p)) return -1;
 
214
    return t->p[t->c++];
 
215
}
 
216
 
 
217
static int next_real_char(struct tokeniser * t)
 
218
{   repeat
 
219
    {   int ch = next_char(t);
 
220
        if (white_space(t, ch)) continue;
 
221
        return ch;
 
222
    }
 
223
}
 
224
 
 
225
static void read_chars(struct tokeniser * t)
 
226
{   int ch = next_real_char(t);
 
227
    if (ch < 0)
 
228
        { error2(t, "stringdef"); return; }
 
229
    {   int c0 = t->c-1;
 
230
        repeat
 
231
        {   ch = next_char(t);
 
232
            if (white_space(t, ch) || ch < 0) break;
 
233
        }
 
234
        t->b2 = move_to_b(t->b2, t->c - c0 - 1, t->p + c0);
 
235
    }
 
236
}
 
237
 
 
238
static int decimal_to_num(ch)
 
239
{   if ('0' <= ch && ch <= '9') return ch - '0';
 
240
    return -1;
 
241
}
 
242
 
 
243
static int hex_to_num(ch)
 
244
{   if ('0' <= ch && ch <= '9') return ch - '0';
 
245
    if ('a' <= ch && ch <= 'f') return ch - 'a' + 10;
 
246
    return -1;
 
247
}
 
248
 
 
249
static void convert_numeric_string(struct tokeniser * t, symbol * p, int base)
 
250
{
 
251
    int c = 0; int d = 0;
 
252
    repeat
 
253
    {   while (c < SIZE(p) && p[c] == ' ') c++;
 
254
        if (c == SIZE(p)) break;
 
255
        {   int number = 0;
 
256
            repeat
 
257
            {   int ch = p[c];
 
258
                if (c == SIZE(p) || ch == ' ') break;
 
259
                if (base == 10)
 
260
                {   ch = decimal_to_num(ch);
 
261
                    if (ch < 0)
 
262
                    {   error1(t, "decimal string contains non-digits");
 
263
                        return;
 
264
                    }
 
265
                } else
 
266
                {   ch = hex_to_num(tolower(ch));
 
267
                    if (ch < 0)
 
268
                    {   error1(t, "hex string contains non-hex characters");
 
269
                        return;
 
270
                    }
 
271
                }
 
272
                number = base * number + ch;
 
273
                c++;
 
274
            }
 
275
            if (t->widechars) unless (0 <= number && number <= 0xffff)
 
276
            {   error1(t, "character values exceed 64K");
 
277
                return;
 
278
            }
 
279
            unless (t->widechars) unless (0 <= number && number <= 0xff)
 
280
            {   error1(t, "character values exceed 256");
 
281
                return;
 
282
            }
 
283
            p[d++] = number;
 
284
        }
 
285
    }
 
286
    SIZE(p) = d;
 
287
}
 
288
 
 
289
extern int read_token(struct tokeniser * t)
 
290
{   symbol * p = t->p;
 
291
    int held = t->token_held;
 
292
    t->token_held = false;
 
293
    if (held) return t->token;
 
294
    repeat
 
295
    {   int code = next_token(t);
 
296
        switch (code)
 
297
        {   case c_comment1: /*  slash-slash comment */
 
298
               while (t->c < SIZE(p) && p[t->c] != '\n') t->c++;
 
299
               continue;
 
300
            case c_comment2: /* slash-star comment */
 
301
               repeat
 
302
               {   if (t->c >= SIZE(p))
 
303
                   {   error1(t, "/* comment not terminated");
 
304
                       t->token = -1;
 
305
                       return -1;
 
306
                   }
 
307
                   if (p[t->c] == '\n') t->line_number++;
 
308
                   if (eq_s(t, "*/")) break;
 
309
                   t->c++;
 
310
               }
 
311
               continue;
 
312
            case c_stringescapes:
 
313
               {   int ch1 = next_real_char(t);
 
314
                   int ch2 = next_real_char(t);
 
315
                   if (ch2 < 0)
 
316
                       { error2(t, "stringescapes"); continue; }
 
317
                   if (ch1 == '\'')
 
318
                       { error1(t, "first stringescape cannot be '"); continue; }
 
319
                   t->m_start = ch1;
 
320
                   t->m_end = ch2;
 
321
               }
 
322
               continue;
 
323
            case c_stringdef:
 
324
               {   int base = 0;
 
325
                   read_chars(t);
 
326
                   code = read_token(t);
 
327
                   if (code == c_hex) { base = 16; code = read_token(t); } else
 
328
                   if (code == c_decimal) { base = 10; code = read_token(t); }
 
329
                   unless (code == c_literalstring)
 
330
                       { error1(t, "string omitted after stringdef"); continue; }
 
331
                   if (base > 0) convert_numeric_string(t, t->b, base);
 
332
                   {   NEW(m_pair, q);
 
333
                       q->next = t->m_pairs;
 
334
                       q->name = copy_b(t->b2);
 
335
                       q->value = copy_b(t->b);
 
336
                       t->m_pairs = q;
 
337
                   }
 
338
               }
 
339
               continue;
 
340
            case c_get:
 
341
               {   code = read_token(t);
 
342
                   unless (code == c_literalstring)
 
343
                       { error1(t, "string omitted after get"); continue; }
 
344
                   t->get_depth++;
 
345
                   if (t->get_depth > 10)
 
346
                   {   fprintf(stderr, "get directives go 10 deep. Looping?\n");
 
347
                       exit(1);
 
348
                   }
 
349
                   {   NEW(input, q);
 
350
                       symbol * u = get_input(t->b);
 
351
                       if (u == 0)
 
352
                       {   struct include * r = t->includes;
 
353
                           until (r == 0)
 
354
                           {   symbol * b = copy_b(r->b);
 
355
                               b = add_to_b(b, SIZE(t->b), t->b);
 
356
                               u = get_input(b);
 
357
                               lose_b(b);
 
358
                               unless (u == 0) break;
 
359
                               r = r->next;
 
360
                           }
 
361
                       }
 
362
                       if (u == 0)
 
363
                       {   error(t, "Can't get '", SIZE(t->b), t->b, "'");
 
364
                           exit(1);
 
365
                       }
 
366
                       memmove(q, t, sizeof(struct input));
 
367
                       t->next = q;
 
368
                       t->p = u;
 
369
                       t->c = 0;
 
370
                       t->line_number = 1;
 
371
                   }
 
372
                   p = t->p;
 
373
                   continue;
 
374
               }
 
375
            case -1:
 
376
               unless (t->next == 0)
 
377
               {   lose_b(p);
 
378
                   {   struct input * q = t->next;
 
379
                       memmove(t, q, sizeof(struct input)); p = t->p;
 
380
                       FREE(q);
 
381
                   }
 
382
                   t->get_depth--;
 
383
                   continue;
 
384
               }
 
385
               /* drop through */
 
386
            default:
 
387
                t->previous_token = t->token;
 
388
                t->token = code;
 
389
                return code;
 
390
        }
 
391
    }
 
392
}
 
393
 
 
394
extern byte * name_of_token(int code)
 
395
{   int i;
 
396
    for (i = 1; i < vocab->code; i++)
 
397
        if ((vocab + i)->code == code) return (vocab + i)->s;
 
398
    switch (code)
 
399
    {
 
400
        case c_mathassign:   return (byte *) "=";
 
401
        case c_name:         return (byte *) "name";
 
402
        case c_number:       return (byte *) "number";
 
403
        case c_literalstring:return (byte *) "literal";
 
404
        case c_neg:          return (byte *) "neg";
 
405
        case c_grouping:     return (byte *) "grouping";
 
406
        case c_call:         return (byte *) "call";
 
407
        case c_booltest:     return (byte *) "Boolean test";
 
408
        case -2:             return (byte *) "start of text";
 
409
        case -1:             return (byte *) "end of text";
 
410
        default:             return (byte *) "?";
 
411
    }
 
412
}
 
413
 
 
414
extern struct tokeniser * create_tokeniser(symbol * p)
 
415
{   NEW(tokeniser, t);
 
416
    t->next = 0;
 
417
    t->p = p;
 
418
    t->c = 0;
 
419
    t->line_number = 1;
 
420
    t->b = create_b(0);
 
421
    t->b2 = create_b(0);
 
422
    t->m_start = -1;
 
423
    t->m_pairs = 0;
 
424
    t->get_depth = 0;
 
425
    t->error_count = 0;
 
426
    t->token_held = false;
 
427
    t->token = -2;
 
428
    t->previous_token = -2;
 
429
    return t;
 
430
}
 
431
 
 
432
extern void close_tokeniser(struct tokeniser * t)
 
433
{   lose_b(t->b);
 
434
    lose_b(t->b2);
 
435
    {   struct m_pair * q = t->m_pairs;
 
436
        until (q == 0)
 
437
        {   struct m_pair * q_next = q->next;
 
438
            lose_b(q->name);
 
439
            lose_b(q->value);
 
440
            FREE(q);
 
441
            q = q_next;
 
442
        }
 
443
    }
 
444
    {   struct input * q = t->next;
 
445
        until (q == 0)
 
446
        {   struct input * q_next = q->next;
 
447
            FREE(q);
 
448
            q = q_next;
 
449
        }
 
450
    }
 
451
    FREE(t);
 
452
}
 
453