DEADSOFTWARE

Добавлены типы INTEGER и BOOLEAN
[dsw-obn.git] / oberon.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <ctype.h>
5 #include <string.h>
7 #include "oberon.h"
8 #include "generator.h"
10 enum {
11 EOF_ = 0,
12 IDENT,
13 MODULE,
14 SEMICOLON,
15 END,
16 DOT,
17 VAR,
18 COLON,
19 BEGIN,
20 ASSIGN,
21 INTEGER,
22 TRUE,
23 FALSE,
24 LPAREN,
25 RPAREN
26 };
28 // =======================================================================
29 // UTILS
30 // =======================================================================
32 void
33 oberon_error(oberon_context_t * ctx, const char * fmt, ...)
34 {
35 va_list ptr;
36 va_start(ptr, fmt);
37 fprintf(stderr, "error: ");
38 vfprintf(stderr, fmt, ptr);
39 fprintf(stderr, "\n");
40 fprintf(stderr, " code_index = %i\n", ctx -> code_index);
41 fprintf(stderr, " c = %c\n", ctx -> c);
42 fprintf(stderr, " token = %i\n", ctx -> token);
43 va_end(ptr);
44 exit(1);
45 }
47 static int
48 oberon_item_to_type_class(oberon_context_t * ctx, oberon_item_t * item)
49 {
50 int class;
52 switch(item -> mode)
53 {
54 case MODE_INTEGER:
55 class = OBERON_TYPE_INTEGER;
56 break;
57 case MODE_BOOLEAN:
58 class = OBERON_TYPE_BOOLEAN;
59 break;
60 case MODE_VAR:
61 class = item -> var -> type -> class;
62 break;
63 default:
64 oberon_error(ctx, "oberon_item_to_type_class: wat");
65 break;
66 }
68 return class;
69 }
71 static void
72 oberon_autocast_to(oberon_context_t * ctx, oberon_item_t * from, oberon_item_t * to)
73 {
74 int from_class = oberon_item_to_type_class(ctx, from);
75 int to_class = oberon_item_to_type_class(ctx, to);
77 if(from_class != to_class)
78 {
79 oberon_error(ctx, "oberon_autocast_to: types not matched %i -> %i", from_class, to_class);
80 }
81 }
83 // =======================================================================
84 // TABLE
85 // =======================================================================
87 static oberon_type_t *
88 oberon_find_type(oberon_context_t * ctx, char * name)
89 {
90 oberon_type_t * x = ctx -> types;
91 while(x -> next && strcmp(x -> next -> name, name) != 0)
92 {
93 x = x -> next;
94 }
96 return x -> next;
97 }
99 static oberon_var_t *
100 oberon_find_var(oberon_context_t * ctx, char * name)
102 oberon_var_t * x = ctx -> mod -> vars;
103 while(x -> next && strcmp(x -> next -> name, name) != 0)
105 x = x -> next;
108 return x -> next;
111 static void
112 oberon_define_var(oberon_context_t * ctx, char * name, oberon_type_t * type)
114 oberon_var_t * x = ctx -> mod -> vars;
115 while(x -> next && strcmp(x -> next -> name, name) != 0)
117 x = x -> next;
120 if(x -> next)
122 oberon_error(ctx, "already defined");
125 oberon_var_t * newvar = malloc(sizeof *newvar);
126 memset(newvar, 0, sizeof *newvar);
127 newvar -> name = name;
128 newvar -> type = type;
129 oberon_generator_init_var(ctx, newvar);
131 x -> next = newvar;
134 // =======================================================================
135 // SCANER
136 // =======================================================================
138 static void
139 oberon_get_char(oberon_context_t * ctx)
141 ctx -> code_index += 1;
142 ctx -> c = ctx -> code[ctx -> code_index];
145 static void
146 oberon_init_scaner(oberon_context_t * ctx, const char * code)
148 ctx -> code = code;
149 ctx -> code_index = 0;
150 ctx -> c = ctx -> code[ctx -> code_index];
153 static void
154 oberon_read_ident(oberon_context_t * ctx)
156 int len = 0;
157 int i = ctx -> code_index;
159 int c = ctx -> code[i];
160 while(isalnum(c))
162 i += 1;
163 len += 1;
164 c = ctx -> code[i];
167 char * ident = malloc(len + 1);
168 memcpy(ident, &ctx->code[ctx->code_index], len);
169 ident[len] = 0;
171 ctx -> code_index = i;
172 ctx -> c = ctx -> code[i];
173 ctx -> string = ident;
174 ctx -> token = IDENT;
176 if(strcmp(ident, "MODULE") == 0)
178 ctx -> token = MODULE;
180 else if(strcmp(ident, "END") == 0)
182 ctx -> token = END;
184 else if(strcmp(ident, "VAR") == 0)
186 ctx -> token = VAR;
188 else if(strcmp(ident, "BEGIN") == 0)
190 ctx -> token = BEGIN;
192 else if(strcmp(ident, "TRUE") == 0)
194 ctx -> token = TRUE;
196 else if(strcmp(ident, "FALSE") == 0)
198 ctx -> token = FALSE;
202 static void
203 oberon_read_integer(oberon_context_t * ctx)
205 int len = 0;
206 int i = ctx -> code_index;
208 int c = ctx -> code[i];
209 while(isdigit(c))
211 i += 1;
212 len += 1;
213 c = ctx -> code[i];
216 char * ident = malloc(len + 2);
217 memcpy(ident, &ctx->code[ctx->code_index], len);
218 ident[len + 1] = 0;
220 ctx -> code_index = i;
221 ctx -> c = ctx -> code[i];
222 ctx -> string = ident;
223 ctx -> integer = atoi(ident);
224 ctx -> token = INTEGER;
227 static void
228 oberon_skip_space(oberon_context_t * ctx)
230 while(isspace(ctx -> c))
232 oberon_get_char(ctx);
236 static void
237 oberon_read_symbol(oberon_context_t * ctx)
239 int c = ctx -> c;
240 switch(c)
242 case 0:
243 ctx -> token = EOF_;
244 break;
245 case ';':
246 ctx -> token = SEMICOLON;
247 oberon_get_char(ctx);
248 break;
249 case ':':
250 ctx -> token = COLON;
251 oberon_get_char(ctx);
252 if(ctx -> c == '=')
254 ctx -> token = ASSIGN;
255 oberon_get_char(ctx);
257 break;
258 case '.':
259 ctx -> token = DOT;
260 oberon_get_char(ctx);
261 break;
262 case '(':
263 ctx -> token = LPAREN;
264 oberon_get_char(ctx);
265 break;
266 case ')':
267 ctx -> token = RPAREN;
268 oberon_get_char(ctx);
269 break;
270 default:
271 oberon_error(ctx, "invalid char");
272 break;
276 static void
277 oberon_read_token(oberon_context_t * ctx)
279 oberon_skip_space(ctx);
281 int c = ctx -> c;
282 if(isalpha(c))
284 oberon_read_ident(ctx);
286 else if(isdigit(c))
288 oberon_read_integer(ctx);
290 else
292 oberon_read_symbol(ctx);
296 // =======================================================================
297 // EXPR
298 // =======================================================================
300 static void oberon_expect_token(oberon_context_t * ctx, int token);
301 static oberon_item_t * oberon_expr(oberon_context_t * ctx);
302 static void oberon_assert_token(oberon_context_t * ctx, int token);
303 static char * oberon_assert_ident(oberon_context_t * ctx);
305 static oberon_item_t *
306 oberon_factor(oberon_context_t * ctx)
308 char * name;
309 oberon_var_t * var;
311 oberon_item_t * item = malloc(sizeof *item);
312 memset(item, 0, sizeof *item);
314 switch(ctx -> token)
316 case IDENT:
317 name = oberon_assert_ident(ctx);
318 var = oberon_find_var(ctx, name);
319 if(var == NULL)
321 oberon_error(ctx, "undefined variable %s", name);
323 item -> mode = MODE_VAR;
324 item -> var = var;
325 break;
326 case INTEGER:
327 item -> mode = MODE_INTEGER;
328 item -> integer = ctx -> integer;
329 oberon_assert_token(ctx, INTEGER);
330 break;
331 case TRUE:
332 item -> mode = MODE_BOOLEAN;
333 item -> boolean = 1;
334 oberon_assert_token(ctx, TRUE);
335 break;
336 case FALSE:
337 item -> mode = MODE_BOOLEAN;
338 item -> boolean = 0;
339 oberon_assert_token(ctx, FALSE);
340 break;
341 case LPAREN:
342 oberon_assert_token(ctx, LPAREN);
343 item = oberon_expr(ctx);
344 oberon_assert_token(ctx, RPAREN);
345 break;
346 default:
347 oberon_error(ctx, "invalid expression");
350 return item;
353 static oberon_item_t *
354 oberon_expr(oberon_context_t * ctx)
356 return oberon_factor(ctx);
359 // =======================================================================
360 // PARSER
361 // =======================================================================
363 static void
364 oberon_expect_token(oberon_context_t * ctx, int token)
366 if(ctx -> token != token)
368 oberon_error(ctx, "unexpected token %i (%i)", ctx -> token, token);
372 static void
373 oberon_assert_token(oberon_context_t * ctx, int token)
375 oberon_expect_token(ctx, token);
376 oberon_read_token(ctx);
379 static char *
380 oberon_assert_ident(oberon_context_t * ctx)
382 oberon_expect_token(ctx, IDENT);
383 char * ident = ctx -> string;
384 oberon_read_token(ctx);
385 return ident;
388 static oberon_type_t *
389 oberon_type(oberon_context_t * ctx)
391 char * name = oberon_assert_ident(ctx);
392 oberon_type_t * type = oberon_find_type(ctx, name);
394 if(type == NULL)
396 oberon_error(ctx, "undefined type");
399 return type;
402 static void
403 oberon_var_decl(oberon_context_t * ctx)
405 char * name = oberon_assert_ident(ctx);
406 oberon_assert_token(ctx, COLON);
407 oberon_type_t * type = oberon_type(ctx);
408 oberon_define_var(ctx, name, type);
411 static void
412 oberon_decl_seq(oberon_context_t * ctx)
414 if(ctx -> token == VAR)
416 oberon_assert_token(ctx, VAR);
417 while(ctx -> token == IDENT)
419 oberon_var_decl(ctx);
420 oberon_assert_token(ctx, SEMICOLON);
425 static void
426 oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst)
428 if(dst -> mode == MODE_INTEGER)
430 oberon_error(ctx, "invalid assignment");
433 oberon_autocast_to(ctx, src, dst);
435 oberon_generate_assign(ctx, src, dst);
438 static void
439 oberon_statement(oberon_context_t * ctx)
441 oberon_item_t * item1;
442 oberon_item_t * item2;
444 if(ctx -> token == IDENT)
446 item1 = oberon_expr(ctx);
447 oberon_assert_token(ctx, ASSIGN);
448 item2 = oberon_expr(ctx);
449 oberon_assign(ctx, item2, item1);
453 static void
454 oberon_statement_seq(oberon_context_t * ctx)
456 oberon_statement(ctx);
457 while(ctx -> token == SEMICOLON)
459 oberon_assert_token(ctx, SEMICOLON);
460 oberon_statement(ctx);
464 static void
465 oberon_parse_module(oberon_context_t * ctx)
467 char *name1, *name2;
468 oberon_read_token(ctx);
470 oberon_assert_token(ctx, MODULE);
471 name1 = oberon_assert_ident(ctx);
472 oberon_assert_token(ctx, SEMICOLON);
473 ctx -> mod -> name = name1;
475 oberon_decl_seq(ctx);
477 if(ctx -> token == BEGIN)
479 oberon_assert_token(ctx, BEGIN);
480 oberon_generate_begin_module(ctx);
481 oberon_statement_seq(ctx);
482 oberon_generate_end_module(ctx);
485 oberon_assert_token(ctx, END);
486 name2 = oberon_assert_ident(ctx);
487 oberon_assert_token(ctx, DOT);
489 if(strcmp(name1, name2) != 0)
491 oberon_error(ctx, "module name not matched");
495 // =======================================================================
496 // LIBRARY
497 // =======================================================================
499 oberon_context_t *
500 oberon_create_context()
502 oberon_context_t * ctx = malloc(sizeof *ctx);
503 memset(ctx, 0, sizeof *ctx);
505 oberon_type_t * types = malloc(sizeof *types);
506 memset(types, 0, sizeof *types);
508 oberon_generator_init_context(ctx);
509 ctx -> types = types;
510 return ctx;
513 void
514 oberon_destroy_context(oberon_context_t * ctx)
516 oberon_generator_destroy_context(ctx);
517 free(ctx);
520 oberon_module_t *
521 oberon_compile_module(oberon_context_t * ctx, const char * code)
523 oberon_module_t * mod = malloc(sizeof *mod);
524 memset(mod, 0, sizeof *mod);
525 oberon_var_t * vars = malloc(sizeof *vars);
526 memset(vars, 0, sizeof *vars);
527 ctx -> mod = mod;
528 ctx -> mod -> vars = vars;
530 oberon_init_scaner(ctx, code);
531 oberon_parse_module(ctx);
533 oberon_generate_code(ctx);
534 return mod;
537 void
538 oberon_register_global_type(oberon_context_t * ctx, oberon_type_t * type)
540 oberon_type_t * x = ctx -> types;
541 while(x -> next && strcmp(x -> next -> name, type -> name) != 0)
543 x = x -> next;
546 if(x -> next)
548 oberon_error(ctx, "already defined");
551 // TODO: copy type name (not a pointer)
552 oberon_type_t * newtype = malloc(sizeof *newtype);
553 memcpy(newtype, type, sizeof *newtype);
554 newtype -> next = NULL;
555 oberon_generator_init_type(ctx, newtype);
557 x -> next = newtype;