]> git.xonotic.org Git - xonotic/gmqcc.git/blob - lexer.h
the -std=qcc set of operators, still have to verify if it's the original
[xonotic/gmqcc.git] / lexer.h
1 #ifndef GMQCC_LEXER_HDR_
2 #define GMQCC_LEXER_HDR_
3
4 typedef struct token_s token;
5
6 #include "ast.h"
7
8 struct token_s {
9         int ttype;
10
11         MEM_VECTOR_MAKE(char, value);
12
13         union {
14                 vector v;
15                 int    i;
16                 double f;
17                 int    t; /* type */
18         } constval;
19
20         struct token_s *next;
21         struct token_s *prev;
22
23         lex_ctx ctx;
24 };
25
26 token* token_new();
27 void   token_delete(token*);
28 token* token_copy(const token *cp);
29 void   token_delete_all(token *t);
30 token* token_copy_all(const token *cp);
31
32 /* Lexer
33  *
34  */
35 enum {
36     /* Other tokens which we can return: */
37     TOKEN_NONE = 0,
38     TOKEN_START = 128,
39
40     TOKEN_IDENT,
41
42     TOKEN_TYPENAME,
43
44     TOKEN_OPERATOR,
45
46     TOKEN_KEYWORD, /* loop */
47
48     TOKEN_DOTS, /* 3 dots, ... */
49
50     TOKEN_STRINGCONST, /* not the typename but an actual "string" */
51     TOKEN_CHARCONST,
52     TOKEN_VECTORCONST,
53     TOKEN_INTCONST,
54     TOKEN_FLOATCONST,
55
56     TOKEN_EOF,
57
58     /* We use '< TOKEN_ERROR', so TOKEN_FATAL must come after it and any
59      * other error related tokens as well
60      */
61     TOKEN_ERROR,
62     TOKEN_FATAL /* internal error, eg out of memory */
63 };
64
65 static const char *_tokennames[] = {
66     "TOKEN_START",
67     "TOKEN_IDENT",
68     "TOKEN_TYPENAME",
69     "TOKEN_OPERATOR",
70     "TOKEN_KEYWORD",
71     "TOKEN_DOTS",
72     "TOKEN_STRINGCONST",
73     "TOKEN_CHARCONST",
74     "TOKEN_VECTORCONST",
75     "TOKEN_INTCONST",
76     "TOKEN_FLOATCONST",
77     "TOKEN_EOF",
78     "TOKEN_ERROR",
79     "TOKEN_FATAL",
80 };
81 typedef int
82 _all_tokennames_added_[
83         ((TOKEN_FATAL - TOKEN_START + 1) ==
84          (sizeof(_tokennames)/sizeof(_tokennames[0])))
85         ? 1 : -1];
86
87 typedef struct {
88     char *name;
89     int   value;
90 } frame_macro;
91
92 typedef struct {
93         FILE   *file;
94         char   *name;
95         size_t  line;
96         size_t  sline; /* line at the start of a token */
97
98         char    peek[256];
99         size_t  peekpos;
100
101         bool    eof;
102
103         token  *tok;
104
105         struct {
106             bool noops;
107         } flags;
108
109     int framevalue;
110         MEM_VECTOR_MAKE(frame_macro, frames);
111         char *modelname;
112 } lex_file;
113
114 MEM_VECTOR_PROTO(lex_file, char, token);
115
116 lex_file* lex_open (const char *file);
117 void      lex_close(lex_file   *lex);
118 int       lex_do   (lex_file   *lex);
119 void      lex_cleanup(void);
120
121 /* Parser
122  *
123  */
124
125 enum {
126     ASSOC_LEFT,
127     ASSOC_RIGHT
128 };
129
130 #define OP_SUFFIX 1
131 #define OP_PREFIX 2
132
133 typedef struct {
134     const char   *op;
135     unsigned int operands;
136     unsigned int id;
137     unsigned int assoc;
138     unsigned int prec;
139     unsigned int flags;
140 } oper_info;
141
142 #define opid1(a) (a)
143 #define opid2(a,b) ((a<<8)|b)
144 #define opid3(a,b,c) ((a<<16)|(b<<8)|c)
145
146 static const oper_info c_operators[] = {
147     { "(",   0, opid1('('),         ASSOC_LEFT,  99, OP_PREFIX}, /* paren expression - non function call */
148
149     { "++",  1, opid3('S','+','+'), ASSOC_LEFT,  16, OP_SUFFIX},
150     { "--",  1, opid3('S','-','-'), ASSOC_LEFT,  16, OP_SUFFIX},
151
152     { ".",   2, opid1('.'),         ASSOC_LEFT,  15, 0 },
153     { "(",   0, opid1('('),         ASSOC_LEFT,  15, 0 }, /* function call */
154
155     { "!",   1, opid2('!', 'P'),    ASSOC_RIGHT, 14, OP_PREFIX },
156     { "~",   1, opid2('~', 'P'),    ASSOC_RIGHT, 14, OP_PREFIX },
157     { "+",   1, opid2('+','P'),     ASSOC_RIGHT, 14, OP_PREFIX },
158     { "-",   1, opid2('-','P'),     ASSOC_RIGHT, 14, OP_PREFIX },
159     { "++",  1, opid3('+','+','P'), ASSOC_RIGHT, 14, OP_PREFIX },
160     { "--",  1, opid3('-','-','P'), ASSOC_RIGHT, 14, OP_PREFIX },
161 /*  { "&",   1, opid2('&','P'),     ASSOC_RIGHT, 14, OP_PREFIX }, */
162
163     { "*",   2, opid1('*'),         ASSOC_LEFT,  13, 0 },
164     { "/",   2, opid1('/'),         ASSOC_LEFT,  13, 0 },
165     { "%",   2, opid1('%'),         ASSOC_LEFT,  13, 0 },
166
167     { "+",   2, opid1('+'),         ASSOC_LEFT,  12, 0 },
168     { "-",   2, opid1('-'),         ASSOC_LEFT,  12, 0 },
169
170     { "<<",  2, opid2('<','<'),     ASSOC_LEFT,  11, 0 },
171     { ">>",  2, opid2('>','>'),     ASSOC_LEFT,  11, 0 },
172
173     { "<",   2, opid1('<'),         ASSOC_LEFT,  10, 0 },
174     { ">",   2, opid1('>'),         ASSOC_LEFT,  10, 0 },
175     { "<=",  2, opid2('<','='),     ASSOC_LEFT,  10, 0 },
176     { ">=",  2, opid2('>','='),     ASSOC_LEFT,  10, 0 },
177
178     { "==",  2, opid2('=','='),     ASSOC_LEFT,  9,  0 },
179     { "!=",  2, opid2('!','='),     ASSOC_LEFT,  9,  0 },
180
181     { "&",   2, opid1('&'),         ASSOC_LEFT,  8,  0 },
182
183     { "^",   2, opid1('^'),         ASSOC_LEFT,  7,  0 },
184
185     { "|",   2, opid1('|'),         ASSOC_LEFT,  6,  0 },
186
187     { "&&",  2, opid2('&','&'),     ASSOC_LEFT,  5,  0 },
188
189     { "||",  2, opid2('|','|'),     ASSOC_LEFT,  4,  0 },
190
191     { "?",   3, opid2('?',':'),     ASSOC_RIGHT, 3,  0 },
192
193     { "=",   2, opid1('='),         ASSOC_RIGHT, 2,  0 },
194     { "+=",  2, opid2('+','='),     ASSOC_RIGHT, 2,  0 },
195     { "-=",  2, opid2('-','='),     ASSOC_RIGHT, 2,  0 },
196     { "*=",  2, opid2('*','='),     ASSOC_RIGHT, 2,  0 },
197     { "/=",  2, opid2('/','='),     ASSOC_RIGHT, 2,  0 },
198     { "%=",  2, opid2('%','='),     ASSOC_RIGHT, 2,  0 },
199     { ">>=", 2, opid3('>','>','='), ASSOC_RIGHT, 2,  0 },
200     { "<<=", 2, opid3('<','<','='), ASSOC_RIGHT, 2,  0 },
201     { "&=",  2, opid2('&','='),     ASSOC_RIGHT, 2,  0 },
202     { "^=",  2, opid2('^','='),     ASSOC_RIGHT, 2,  0 },
203     { "|=",  2, opid2('|','='),     ASSOC_RIGHT, 2,  0 },
204
205     { ",",   2, opid1(','),         ASSOC_LEFT,  1,  0 }
206 };
207 static const size_t c_operator_count = (sizeof(c_operators) / sizeof(c_operators[0]));
208
209 static const oper_info qcc_operators[] = {
210     { "(",   0, opid1('('),         ASSOC_LEFT,  99, OP_PREFIX}, /* paren expression - non function call */
211
212     { ".",   2, opid1('.'),         ASSOC_LEFT,  15, 0 },
213     { "(",   0, opid1('('),         ASSOC_LEFT,  15, 0 }, /* function call */
214
215     { "!",   1, opid2('!', 'P'),    ASSOC_RIGHT, 14, OP_PREFIX },
216     { "+",   1, opid2('+','P'),     ASSOC_RIGHT, 14, OP_PREFIX },
217     { "-",   1, opid2('-','P'),     ASSOC_RIGHT, 14, OP_PREFIX },
218
219     { "*",   2, opid1('*'),         ASSOC_LEFT,  13, 0 },
220     { "/",   2, opid1('/'),         ASSOC_LEFT,  13, 0 },
221     { "&",   2, opid1('&'),         ASSOC_LEFT,  13, 0 },
222     { "|",   2, opid1('|'),         ASSOC_LEFT,  13, 0 },
223
224     { "+",   2, opid1('+'),         ASSOC_LEFT,  12, 0 },
225     { "-",   2, opid1('-'),         ASSOC_LEFT,  12, 0 },
226
227     { "<",   2, opid1('<'),         ASSOC_LEFT,  10, 0 },
228     { ">",   2, opid1('>'),         ASSOC_LEFT,  10, 0 },
229     { "<=",  2, opid2('<','='),     ASSOC_LEFT,  10, 0 },
230     { ">=",  2, opid2('>','='),     ASSOC_LEFT,  10, 0 },
231     { "==",  2, opid2('=','='),     ASSOC_LEFT,  10,  0 },
232     { "!=",  2, opid2('!','='),     ASSOC_LEFT,  10,  0 },
233
234     { "=",   2, opid1('='),         ASSOC_RIGHT, 8,  0 },
235     { "+=",  2, opid2('+','='),     ASSOC_RIGHT, 8,  0 },
236     { "-=",  2, opid2('-','='),     ASSOC_RIGHT, 8,  0 },
237     { "*=",  2, opid2('*','='),     ASSOC_RIGHT, 8,  0 },
238     { "/=",  2, opid2('/','='),     ASSOC_RIGHT, 8,  0 },
239     { "%=",  2, opid2('%','='),     ASSOC_RIGHT, 8,  0 },
240     { "&=",  2, opid2('&','='),     ASSOC_RIGHT, 8,  0 },
241     { "|=",  2, opid2('|','='),     ASSOC_RIGHT, 8,  0 },
242
243     { "&&",  2, opid2('&','&'),     ASSOC_LEFT,  5,  0 },
244     { "||",  2, opid2('|','|'),     ASSOC_LEFT,  5,  0 },
245
246     { ",",   2, opid1(','),         ASSOC_LEFT,  1,  0 }
247 };
248 static const size_t qcc_operator_count = (sizeof(qcc_operators) / sizeof(qcc_operators[0]));
249
250 extern const oper_info *operators;
251 extern size_t           operator_count;
252
253 typedef struct
254 {
255         lex_file *lex;
256         int      error;
257         lex_ctx  ctx;
258
259         token    *tokens;
260         token    *lastok;
261
262         token    *tok; /* current token */
263
264         MEM_VECTOR_MAKE(ast_value*, globals);
265 } parse_file;
266
267 MEM_VECTOR_PROTO(parse_file, ast_value*, globals);
268
269 parse_file* parse_open(const char *file);
270 void        parse_file_close(parse_file*);
271
272 bool        parse(parse_file*);
273
274 bool        parse_iskey(parse_file *self, const char *ident);
275
276 void lexerror(lex_file*, const char *fmt, ...);
277
278 #endif