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