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

« back to all changes in this revision

Viewing changes to snowball/compiler/tokeniser.c

  • Committer: Jason Spashett
  • Date: 2012-04-14 13:12:57 UTC
  • Revision ID: jason@spashett.com-20120414131257-rv3ugy4u2iyoczdk
Add ISO 639-2, and 639-1 language codes

Show diffs side-by-side

added added

removed removed

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