diff --git a/oberon.c b/oberon.c
index e411c6c2fdaa455bf15fddcd54c7b94a37f3c8c3..4dfc604a5f38159b0d1668b8376b0cc4fa8195e7 100644 (file)
--- a/oberon.c
+++ b/oberon.c
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
+
#include "oberon.h"
+#include "generator.h"
enum {
EOF_ = 0,
COLON,
BEGIN,
ASSIGN,
- INTEGER
-};
-
-enum {
- MODE_VAR,
- MODE_INTEGER,
+ INTEGER,
+ TRUE,
+ FALSE,
+ LPAREN,
+ RPAREN
};
-typedef struct
-{
- int mode;
- int integer;
- oberon_var_t * var;
-} oberon_item_t;
-
// =======================================================================
// UTILS
// =======================================================================
-static void
+void
oberon_error(oberon_context_t * ctx, const char * fmt, ...)
{
va_list ptr;
{
int class;
- if(item -> mode == MODE_INTEGER)
+ switch(item -> mode)
{
- class = OBERON_TYPE_INTEGER;
- }
- else if(item -> mode == MODE_VAR)
- {
- class = item -> var -> type -> class;
- }
- else
- {
- oberon_error(ctx, "oberon_item_to_type_class: wat");
+ case MODE_INTEGER:
+ class = OBERON_TYPE_INTEGER;
+ break;
+ case MODE_BOOLEAN:
+ class = OBERON_TYPE_BOOLEAN;
+ break;
+ case MODE_VAR:
+ class = item -> var -> type -> class;
+ break;
+ default:
+ oberon_error(ctx, "oberon_item_to_type_class: wat");
+ break;
}
return class;
}
+static void
+oberon_autocast_to(oberon_context_t * ctx, oberon_item_t * from, oberon_item_t * to)
+{
+ int from_class = oberon_item_to_type_class(ctx, from);
+ int to_class = oberon_item_to_type_class(ctx, to);
+
+ if(from_class != to_class)
+ {
+ oberon_error(ctx, "oberon_autocast_to: types not matched %i -> %i", from_class, to_class);
+ }
+}
+
// =======================================================================
// TABLE
// =======================================================================
memset(newvar, 0, sizeof *newvar);
newvar -> name = name;
newvar -> type = type;
+ oberon_generator_init_var(ctx, newvar);
x -> next = newvar;
}
-// =======================================================================
-// GENERATOR
-// =======================================================================
-
-static void
-oberon_generate_assign(oberon_context_t * ctx, void * src, void * dst, int size)
-{
- printf("G: %p := %p (%i);\n", dst, src, size);
-}
-
// =======================================================================
// SCANER
// =======================================================================
c = ctx -> code[i];
}
- char * ident = malloc(len + 2);
+ char * ident = malloc(len + 1);
memcpy(ident, &ctx->code[ctx->code_index], len);
- ident[len + 1] = 0;
+ ident[len] = 0;
ctx -> code_index = i;
ctx -> c = ctx -> code[i];
{
ctx -> token = BEGIN;
}
+ else if(strcmp(ident, "TRUE") == 0)
+ {
+ ctx -> token = TRUE;
+ }
+ else if(strcmp(ident, "FALSE") == 0)
+ {
+ ctx -> token = FALSE;
+ }
}
static void
}
}
+static void
+oberon_read_symbol(oberon_context_t * ctx)
+{
+ int c = ctx -> c;
+ switch(c)
+ {
+ case 0:
+ ctx -> token = EOF_;
+ break;
+ case ';':
+ ctx -> token = SEMICOLON;
+ oberon_get_char(ctx);
+ break;
+ case ':':
+ ctx -> token = COLON;
+ oberon_get_char(ctx);
+ if(ctx -> c == '=')
+ {
+ ctx -> token = ASSIGN;
+ oberon_get_char(ctx);
+ }
+ break;
+ case '.':
+ ctx -> token = DOT;
+ oberon_get_char(ctx);
+ break;
+ case '(':
+ ctx -> token = LPAREN;
+ oberon_get_char(ctx);
+ break;
+ case ')':
+ ctx -> token = RPAREN;
+ oberon_get_char(ctx);
+ break;
+ default:
+ oberon_error(ctx, "invalid char");
+ break;
+ }
+}
+
static void
oberon_read_token(oberon_context_t * ctx)
{
}
else
{
- switch(c)
- {
- case 0: ctx -> token = EOF_; break;
- case ';': ctx -> token = SEMICOLON; oberon_get_char(ctx); break;
- case ':':
- /****************************************************/
- ctx -> token = COLON; oberon_get_char(ctx);
- if(ctx -> c == '=')
- {
- ctx -> token = ASSIGN;
- oberon_get_char(ctx);
- }
- break;
- /****************************************************/
- case '.': ctx -> token = DOT; oberon_get_char(ctx); break;
- default: oberon_error(ctx, "invalid char");
- }
+ oberon_read_symbol(ctx);
}
}
+// =======================================================================
+// EXPR
+// =======================================================================
+
+static void oberon_expect_token(oberon_context_t * ctx, int token);
+static oberon_item_t * oberon_expr(oberon_context_t * ctx);
+static void oberon_assert_token(oberon_context_t * ctx, int token);
+static char * oberon_assert_ident(oberon_context_t * ctx);
+
+static oberon_item_t *
+oberon_factor(oberon_context_t * ctx)
+{
+ char * name;
+ oberon_var_t * var;
+
+ oberon_item_t * item = malloc(sizeof *item);
+ memset(item, 0, sizeof *item);
+
+ switch(ctx -> token)
+ {
+ case IDENT:
+ name = oberon_assert_ident(ctx);
+ var = oberon_find_var(ctx, name);
+ if(var == NULL)
+ {
+ oberon_error(ctx, "undefined variable %s", name);
+ }
+ item -> mode = MODE_VAR;
+ item -> var = var;
+ break;
+ case INTEGER:
+ item -> mode = MODE_INTEGER;
+ item -> integer = ctx -> integer;
+ oberon_assert_token(ctx, INTEGER);
+ break;
+ case TRUE:
+ item -> mode = MODE_BOOLEAN;
+ item -> boolean = 1;
+ oberon_assert_token(ctx, TRUE);
+ break;
+ case FALSE:
+ item -> mode = MODE_BOOLEAN;
+ item -> boolean = 0;
+ oberon_assert_token(ctx, FALSE);
+ break;
+ case LPAREN:
+ oberon_assert_token(ctx, LPAREN);
+ item = oberon_expr(ctx);
+ oberon_assert_token(ctx, RPAREN);
+ break;
+ default:
+ oberon_error(ctx, "invalid expression");
+ }
+
+ return item;
+}
+
+static oberon_item_t *
+oberon_expr(oberon_context_t * ctx)
+{
+ return oberon_factor(ctx);
+}
+
// =======================================================================
// PARSER
// =======================================================================
static char *
oberon_assert_ident(oberon_context_t * ctx)
{
- char * ident;
oberon_expect_token(ctx, IDENT);
- ident = ctx -> string;
+ char * ident = ctx -> string;
oberon_read_token(ctx);
return ident;
}
}
}
-static oberon_item_t *
-oberon_expr(oberon_context_t * ctx)
-{
- oberon_item_t * item = malloc(sizeof *item);
- memset(item, 0, sizeof *item);
-
- if(ctx -> token == IDENT)
- {
- char * name = oberon_assert_ident(ctx);
- oberon_var_t * var = oberon_find_var(ctx, name);
- if(var == NULL)
- {
- oberon_error(ctx, "undefined variable");
- }
- item -> mode = MODE_VAR;
- item -> var = var;
- }
- else if(ctx -> token == INTEGER)
- {
- item -> mode = MODE_INTEGER;
- item -> integer = ctx -> integer;
- oberon_assert_token(ctx, INTEGER);
- }
- else
- {
- oberon_error(ctx, "invalid expression");
- }
-
- return item;
-}
-
static void
oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst)
{
@@ -367,16 +430,9 @@ oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst)
oberon_error(ctx, "invalid assignment");
}
- int src_class = oberon_item_to_type_class(ctx, src);
- int dst_class = oberon_item_to_type_class(ctx, dst);
-
- if(src_class != dst_class)
- {
- oberon_error(ctx, "types not matched");
- }
+ oberon_autocast_to(ctx, src, dst);
- // TODO: code generation
- oberon_generate_assign(ctx, 0, 0, 4);
+ oberon_generate_assign(ctx, src, dst);
}
static void
}
static void
-oberon_parse_it(oberon_context_t * ctx)
+oberon_parse_module(oberon_context_t * ctx)
{
char *name1, *name2;
oberon_read_token(ctx);
if(ctx -> token == BEGIN)
{
oberon_assert_token(ctx, BEGIN);
+ oberon_generate_begin_module(ctx);
oberon_statement_seq(ctx);
+ oberon_generate_end_module(ctx);
}
oberon_assert_token(ctx, END);
oberon_type_t * types = malloc(sizeof *types);
memset(types, 0, sizeof *types);
+ oberon_generator_init_context(ctx);
ctx -> types = types;
return ctx;
}
+void
+oberon_destroy_context(oberon_context_t * ctx)
+{
+ oberon_generator_destroy_context(ctx);
+ free(ctx);
+}
+
oberon_module_t *
oberon_compile_module(oberon_context_t * ctx, const char * code)
{
ctx -> mod -> vars = vars;
oberon_init_scaner(ctx, code);
- oberon_parse_it(ctx);
+ oberon_parse_module(ctx);
+
+ oberon_generate_code(ctx);
return mod;
}
oberon_type_t * newtype = malloc(sizeof *newtype);
memcpy(newtype, type, sizeof *newtype);
newtype -> next = NULL;
+ oberon_generator_init_type(ctx, newtype);
x -> next = newtype;
}