]> git.xonotic.org Git - xonotic/gmqcc.git/blob - lexer.h
Adding ids to operators for SYA later
[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_STRINGCONST, /* not the typename but an actual "string" */
49     TOKEN_CHARCONST,
50     TOKEN_VECTORCONST,
51     TOKEN_INTCONST,
52     TOKEN_FLOATCONST,
53
54     TOKEN_EOF,
55
56     /* We use '< TOKEN_ERROR', so TOKEN_FATAL must come after it and any
57      * other error related tokens as well
58      */
59     TOKEN_ERROR,
60     TOKEN_FATAL /* internal error, eg out of memory */
61 };
62
63 static const char *_tokennames[] = {
64     "TOKEN_START",
65     "TOKEN_IDENT",
66     "TOKEN_TYPENAME",
67     "TOKEN_OPERATOR",
68     "TOKEN_KEYWORD",
69     "TOKEN_STRINGCONST",
70     "TOKEN_CHARCONST",
71     "TOKEN_VECTORCONST",
72     "TOKEN_INTCONST",
73     "TOKEN_FLOATCONST",
74     "TOKEN_EOF",
75     "TOKEN_ERROR",
76     "TOKEN_FATAL",
77 };
78 typedef int
79 _all_tokennames_added_[
80         ((TOKEN_FATAL - TOKEN_START + 1) ==
81          (sizeof(_tokennames)/sizeof(_tokennames[0])))
82         ? 1 : -1];
83
84 typedef struct {
85         FILE   *file;
86         char   *name;
87         size_t  line;
88         size_t  sline; /* line at the start of a token */
89
90         char    peek[256];
91         size_t  peekpos;
92
93         token  *tok;
94
95         struct {
96             bool noops;
97         } flags;
98 } lex_file;
99
100 MEM_VECTOR_PROTO(lex_file, char, token);
101
102 lex_file* lex_open (const char *file);
103 void      lex_close(lex_file   *lex);
104 int       lex_do   (lex_file   *lex);
105
106 /* Parser
107  *
108  */
109
110 enum {
111     ASSOC_LEFT,
112     ASSOC_RIGHT
113 };
114
115 #define OP_SUFFIX 1
116 #define OP_PREFIX 2
117
118 typedef struct {
119     const char   *op;
120     unsigned int id;
121     unsigned int assoc;
122     unsigned int prec;
123     unsigned int flags;
124 } oper_info;
125
126 static const oper_info operators[] = {
127     { "++",    1, ASSOC_LEFT,  16, OP_SUFFIX},
128     { "--",    2, ASSOC_LEFT,  16, OP_SUFFIX},
129
130     { ".",    10, ASSOC_LEFT,  15, 0 },
131
132     { "!",    21, ASSOC_RIGHT, 14, 0 },
133     { "~",    22, ASSOC_RIGHT, 14, 0 },
134     { "+",    23, ASSOC_RIGHT, 14, OP_PREFIX },
135     { "-",    24, ASSOC_RIGHT, 14, OP_PREFIX },
136     { "++",   25, ASSOC_RIGHT, 14, OP_PREFIX },
137     { "--",   26, ASSOC_RIGHT, 14, OP_PREFIX },
138 /*  { "&",    27, ASSOC_RIGHT, 14, OP_PREFIX }, */
139
140     { "*",    30, ASSOC_LEFT,  13, 0 },
141     { "/",    31, ASSOC_LEFT,  13, 0 },
142     { "%",    32, ASSOC_LEFT,  13, 0 },
143
144     { "+",    40, ASSOC_LEFT,  12, 0 },
145     { "-",    41, ASSOC_LEFT,  12, 0 },
146
147     { "<<",   50, ASSOC_LEFT,  11, 0 },
148     { ">>",   51, ASSOC_LEFT,  11, 0 },
149
150     { "<",    60, ASSOC_LEFT,  10, 0 },
151     { ">",    61, ASSOC_LEFT,  10, 0 },
152     { "<=",   62, ASSOC_LEFT,  10, 0 },
153     { ">=",   63, ASSOC_LEFT,  10, 0 },
154
155     { "==",   70, ASSOC_LEFT,  9,  0 },
156     { "!=",   71, ASSOC_LEFT,  9,  0 },
157
158     { "&",    80, ASSOC_LEFT,  8,  0 },
159
160     { "^",    90, ASSOC_LEFT,  7,  0 },
161
162     { "|",   100, ASSOC_LEFT,  6,  0 },
163
164     { "&&",  110, ASSOC_LEFT,  5,  0 },
165
166     { "||",  120, ASSOC_LEFT,  4,  0 },
167
168     { "?",   130, ASSOC_RIGHT, 3,  0 },
169
170     { "=",   140, ASSOC_RIGHT, 2,  0 },
171     { "+=",  141, ASSOC_RIGHT, 2,  0 },
172     { "-=",  142, ASSOC_RIGHT, 2,  0 },
173     { "*=",  143, ASSOC_RIGHT, 2,  0 },
174     { "/=",  144, ASSOC_RIGHT, 2,  0 },
175     { "%=",  145, ASSOC_RIGHT, 2,  0 },
176     { ">>=", 146, ASSOC_RIGHT, 2,  0 },
177     { "<<=", 147, ASSOC_RIGHT, 2,  0 },
178     { "&=",  148, ASSOC_RIGHT, 2,  0 },
179     { "^=",  149, ASSOC_RIGHT, 2,  0 },
180     { "|=",  150, ASSOC_RIGHT, 2,  0 },
181 };
182
183 typedef struct
184 {
185         lex_file *lex;
186         int      error;
187         lex_ctx  ctx;
188
189         token    *tokens;
190         token    *lastok;
191
192         token    *tok; /* current token */
193
194         MEM_VECTOR_MAKE(ast_value*, globals);
195 } parse_file;
196
197 MEM_VECTOR_PROTO(parse_file, ast_value*, globals);
198
199 parse_file* parse_open(const char *file);
200 void        parse_file_close(parse_file*);
201
202 bool        parse(parse_file*);
203
204 bool        parse_iskey(parse_file *self, const char *ident);
205
206 void lexerror(lex_file*, const char *fmt, ...);
207
208 #endif