parser.cpp revision ad6741c6f82febee62bbfc439d03654c2cb3ba3e
1#include "parser.h"
2
3int next_token(struct parse_state *state)
4{
5    char *x = state->ptr;
6    char *s;
7
8    if (state->nexttoken) {
9        int t = state->nexttoken;
10        state->nexttoken = 0;
11        return t;
12    }
13
14    for (;;) {
15        switch (*x) {
16        case 0:
17            state->ptr = x;
18            return T_EOF;
19        case '\n':
20            x++;
21            state->ptr = x;
22            return T_NEWLINE;
23        case ' ':
24        case '\t':
25        case '\r':
26            x++;
27            continue;
28        case '#':
29            while (*x && (*x != '\n')) x++;
30            if (*x == '\n') {
31                state->ptr = x+1;
32                return T_NEWLINE;
33            } else {
34                state->ptr = x;
35                return T_EOF;
36            }
37        default:
38            goto text;
39        }
40    }
41
42textdone:
43    state->ptr = x;
44    *s = 0;
45    return T_TEXT;
46text:
47    state->text = s = x;
48textresume:
49    for (;;) {
50        switch (*x) {
51        case 0:
52            goto textdone;
53        case ' ':
54        case '\t':
55        case '\r':
56            x++;
57            goto textdone;
58        case '\n':
59            state->nexttoken = T_NEWLINE;
60            x++;
61            goto textdone;
62        case '"':
63            x++;
64            for (;;) {
65                switch (*x) {
66                case 0:
67                        /* unterminated quoted thing */
68                    state->ptr = x;
69                    return T_EOF;
70                case '"':
71                    x++;
72                    goto textresume;
73                default:
74                    *s++ = *x++;
75                }
76            }
77            break;
78        case '\\':
79            x++;
80            switch (*x) {
81            case 0:
82                goto textdone;
83            case 'n':
84                *s++ = '\n';
85                break;
86            case 'r':
87                *s++ = '\r';
88                break;
89            case 't':
90                *s++ = '\t';
91                break;
92            case '\\':
93                *s++ = '\\';
94                break;
95            case '\r':
96                    /* \ <cr> <lf> -> line continuation */
97                if (x[1] != '\n') {
98                    x++;
99                    continue;
100                }
101            case '\n':
102                    /* \ <lf> -> line continuation */
103                state->line++;
104                x++;
105                    /* eat any extra whitespace */
106                while((*x == ' ') || (*x == '\t')) x++;
107                continue;
108            default:
109                    /* unknown escape -- just copy */
110                *s++ = *x++;
111            }
112            continue;
113        default:
114            *s++ = *x++;
115        }
116    }
117    return T_EOF;
118}
119