mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-30 19:08:12 +03:00
ainedit: support parsing .jaf functions
This commit is contained in:
@@ -326,6 +326,7 @@ int ain_get_struct_no(struct ain *ain, char *name);
|
||||
int ain_add_struct(struct ain *ain, char *name);
|
||||
struct ain_variable *ain_add_global(struct ain *ain, char *name);
|
||||
void ain_add_initval(struct ain *ain, struct ain_initval *init);
|
||||
int ain_add_function(struct ain *ain, struct ain_function *fun);
|
||||
|
||||
void ain_free(struct ain *ain);
|
||||
void ain_free_functions(struct ain *ain);
|
||||
|
||||
@@ -223,6 +223,13 @@ void ain_add_initval(struct ain *ain, struct ain_initval *init)
|
||||
ain->global_initvals[ain->nr_initvals++] = *init;
|
||||
}
|
||||
|
||||
int ain_add_function(struct ain *ain, struct ain_function *fun)
|
||||
{
|
||||
ain->functions = xrealloc_array(ain->functions, ain->nr_functions, ain->nr_functions+1, sizeof (struct ain_function));
|
||||
ain->functions[ain->nr_functions++] = *fun;
|
||||
return ain->nr_functions - 1;
|
||||
}
|
||||
|
||||
static const char *errtab[AIN_MAX_ERROR] = {
|
||||
[AIN_SUCCESS] = "Success",
|
||||
[AIN_FILE_ERROR] = "Error opening AIN file",
|
||||
|
||||
+105
-20
@@ -14,8 +14,8 @@
|
||||
* along with this program; if not, see <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AINEDIT_JAF_AST_H
|
||||
#define AINEDIT_JAF_AST_H
|
||||
#ifndef AINEDIT_JAF_H
|
||||
#define AINEDIT_JAF_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -120,7 +120,7 @@ struct jaf_type_specifier {
|
||||
enum jaf_type type;
|
||||
unsigned qualifiers;
|
||||
struct string *name;
|
||||
struct jaf_declaration_list *def;
|
||||
struct jaf_block *def;
|
||||
int struct_no;
|
||||
};
|
||||
|
||||
@@ -136,24 +136,89 @@ struct jaf_declarator_list {
|
||||
struct jaf_declarator **decls;
|
||||
};
|
||||
|
||||
struct jaf_function {
|
||||
// TODO
|
||||
struct jaf_function_declarator {
|
||||
struct string *name;
|
||||
struct jaf_block *params;
|
||||
};
|
||||
|
||||
enum block_item_kind {
|
||||
JAF_DECLARATION,
|
||||
JAF_FUNCTION,
|
||||
JAF_STMT_LABELED,
|
||||
JAF_STMT_COMPOUND,
|
||||
JAF_STMT_EXPRESSION,
|
||||
JAF_STMT_IF,
|
||||
JAF_STMT_SWITCH,
|
||||
JAF_STMT_WHILE,
|
||||
JAF_STMT_DO_WHILE,
|
||||
JAF_STMT_FOR,
|
||||
JAF_STMT_GOTO,
|
||||
JAF_STMT_CONTINUE,
|
||||
JAF_STMT_BREAK,
|
||||
JAF_STMT_RETURN,
|
||||
JAF_STMT_CASE,
|
||||
JAF_STMT_DEFAULT
|
||||
};
|
||||
|
||||
struct jaf_declaration {
|
||||
bool function;
|
||||
struct string *name;
|
||||
struct jaf_type_specifier *type;
|
||||
size_t array_rank;
|
||||
size_t *array_dims;
|
||||
struct jaf_expression *init;
|
||||
struct jaf_function *fun;
|
||||
int var_no;
|
||||
union {
|
||||
struct {
|
||||
struct jaf_expression *init;
|
||||
int var_no;
|
||||
};
|
||||
struct {
|
||||
struct jaf_block *params;
|
||||
struct jaf_block *body;
|
||||
int func_no;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct jaf_declaration_list {
|
||||
size_t nr_decls;
|
||||
struct jaf_declaration **decls;
|
||||
// declaration or statement
|
||||
struct jaf_block_item {
|
||||
enum block_item_kind kind;
|
||||
union {
|
||||
struct jaf_declaration decl;
|
||||
struct {
|
||||
struct string *name;
|
||||
struct jaf_block_item *stmt;
|
||||
} label;
|
||||
struct {
|
||||
struct jaf_expression *expr;
|
||||
struct jaf_block_item *stmt;
|
||||
} swi_case;
|
||||
struct jaf_block *block;
|
||||
struct jaf_expression *expr;
|
||||
struct {
|
||||
struct jaf_expression *test;
|
||||
struct jaf_block_item *consequent;
|
||||
struct jaf_block_item *alternative;
|
||||
} cond;
|
||||
struct {
|
||||
struct jaf_expression *expr;
|
||||
struct jaf_block *body;
|
||||
} swi;
|
||||
struct {
|
||||
struct jaf_expression *test;
|
||||
struct jaf_block_item *body;
|
||||
} while_loop;
|
||||
struct {
|
||||
struct jaf_block *init;
|
||||
struct jaf_expression *test;
|
||||
struct jaf_expression *after;
|
||||
struct jaf_block_item *body;
|
||||
} for_loop;
|
||||
struct string *target; // goto
|
||||
};
|
||||
};
|
||||
|
||||
struct jaf_block {
|
||||
size_t nr_items;
|
||||
struct jaf_block_item **items;
|
||||
};
|
||||
|
||||
struct jaf_expression *jaf_integer(struct string *text);
|
||||
@@ -166,29 +231,49 @@ struct jaf_expression *jaf_ternary_expr(struct jaf_expression *test, struct jaf_
|
||||
struct jaf_expression *jaf_seq_expr(struct jaf_expression *head, struct jaf_expression *tail);
|
||||
|
||||
struct jaf_type_specifier *jaf_type(enum jaf_type type);
|
||||
struct jaf_type_specifier *jaf_struct(struct string *name, struct jaf_declaration_list *fields);
|
||||
struct jaf_type_specifier *jaf_struct(struct string *name, struct jaf_block *fields);
|
||||
struct jaf_type_specifier *jaf_typedef(struct string *name);
|
||||
|
||||
struct jaf_declarator *jaf_declarator(struct string *name);
|
||||
struct jaf_declarator_list *jaf_declarators(struct jaf_declarator_list *head, struct jaf_declarator *tail);
|
||||
|
||||
struct jaf_declaration_list *jaf_declaration(struct jaf_type_specifier *type, struct jaf_declarator_list *declarators);
|
||||
struct jaf_declaration_list *jaf_type_declaration(struct jaf_type_specifier *type);
|
||||
struct jaf_declaration_list *jaf_declarations(struct jaf_declaration_list *head, struct jaf_declaration_list *tail);
|
||||
struct jaf_block *jaf_parameter(struct jaf_type_specifier *type, struct jaf_declarator *declarator);
|
||||
struct jaf_function_declarator *jaf_function_declarator(struct string *name, struct jaf_block *params);
|
||||
struct jaf_block *jaf_function(struct jaf_type_specifier *type, struct jaf_function_declarator *decl, struct jaf_block *body);
|
||||
|
||||
struct jaf_block *jaf_declaration(struct jaf_type_specifier *type, struct jaf_declarator_list *declarators);
|
||||
struct jaf_block *jaf_type_declaration(struct jaf_type_specifier *type);
|
||||
struct jaf_block *jaf_merge_blocks(struct jaf_block *head, struct jaf_block *tail);
|
||||
|
||||
struct jaf_block *jaf_block(struct jaf_block_item *item);
|
||||
struct jaf_block_item *jaf_compound_statement(struct jaf_block *block);
|
||||
struct jaf_block_item *jaf_label_statement(struct string *label, struct jaf_block_item *stmt);
|
||||
struct jaf_block_item *jaf_case_statement(struct jaf_expression *expr, struct jaf_block_item *stmt);
|
||||
struct jaf_block_item *jaf_expression_statement(struct jaf_expression *expr);
|
||||
struct jaf_block_item *jaf_if_statement(struct jaf_expression *test, struct jaf_block_item *cons, struct jaf_block_item *alt);
|
||||
struct jaf_block_item *jaf_switch_statement(struct jaf_expression *expr, struct jaf_block *body);
|
||||
struct jaf_block_item *jaf_while_loop(struct jaf_expression *test, struct jaf_block_item *body);
|
||||
struct jaf_block_item *jaf_do_while_loop(struct jaf_expression *test, struct jaf_block_item *body);
|
||||
struct jaf_block_item *jaf_for_loop(struct jaf_block *init, struct jaf_block_item *test, struct jaf_expression *after, struct jaf_block_item *body);
|
||||
struct jaf_block_item *jaf_goto(struct string *target);
|
||||
struct jaf_block_item *jaf_continue(void);
|
||||
struct jaf_block_item *jaf_break(void);
|
||||
struct jaf_block_item *jaf_return(struct jaf_expression *expr);
|
||||
|
||||
void jaf_free_expr(struct jaf_expression *expr);
|
||||
void jaf_free_block(struct jaf_block *block);
|
||||
|
||||
// jaf_compile.c
|
||||
struct ain *jaf_ain_out;
|
||||
struct jaf_declaration_list *jaf_toplevel;
|
||||
struct jaf_block *jaf_toplevel;
|
||||
void jaf_compile(struct ain *out, const char *path);
|
||||
void jaf_define_struct(struct ain *ain, struct jaf_type_specifier *type);
|
||||
|
||||
// jaf_eval.c
|
||||
struct jaf_expression *jaf_simplify(struct jaf_expression *in);
|
||||
struct jaf_expression *jaf_compute_constexpr(struct jaf_expression *in);
|
||||
|
||||
// jaf_types.c
|
||||
void jaf_check_types(struct jaf_expression *expr, struct jaf_type_specifier *type);
|
||||
void jaf_derive_types(struct jaf_expression *expr);
|
||||
void jaf_check_type(struct jaf_expression *expr, struct jaf_type_specifier *type);
|
||||
|
||||
#endif /* AINEDIT_JAF_AST_H */
|
||||
#endif /* AINEDIT_JAF_H */
|
||||
|
||||
+269
-26
@@ -17,6 +17,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include "system4.h"
|
||||
#include "system4/string.h"
|
||||
#include "jaf.h"
|
||||
@@ -104,7 +105,7 @@ struct jaf_type_specifier *jaf_type(enum jaf_type type)
|
||||
return p;
|
||||
}
|
||||
|
||||
struct jaf_type_specifier *jaf_struct(struct string *name, struct jaf_declaration_list *fields)
|
||||
struct jaf_type_specifier *jaf_struct(struct string *name, struct jaf_block *fields)
|
||||
{
|
||||
struct jaf_type_specifier *p = jaf_type(JAF_STRUCT);
|
||||
p->name = name;
|
||||
@@ -137,55 +138,211 @@ struct jaf_declarator_list *jaf_declarators(struct jaf_declarator_list *head, st
|
||||
return head;
|
||||
}
|
||||
|
||||
struct jaf_declaration_list *jaf_declaration(struct jaf_type_specifier *type, struct jaf_declarator_list *declarators)
|
||||
static void init_declaration(struct jaf_type_specifier *type, struct jaf_block_item *dst, struct jaf_declarator *src)
|
||||
{
|
||||
struct jaf_declaration_list *decls = xcalloc(1, sizeof(struct jaf_declaration_list));
|
||||
decls->nr_decls = declarators->nr_decls;
|
||||
decls->decls = xcalloc(declarators->nr_decls, sizeof(struct jaf_declaration*));
|
||||
for (size_t i = 0; i < declarators->nr_decls; i++) {
|
||||
struct jaf_declaration *decl = xcalloc(1, sizeof(struct jaf_declaration));
|
||||
decl->function = false;
|
||||
decl->name = declarators->decls[i]->name;
|
||||
decl->type = type;
|
||||
decl->init = declarators->decls[i]->init;
|
||||
decls->decls[i] = decl;
|
||||
dst->kind = JAF_DECLARATION;
|
||||
dst->decl.name = src->name;
|
||||
dst->decl.type = type;
|
||||
dst->decl.init = src->init;
|
||||
free(src);
|
||||
}
|
||||
|
||||
free(declarators->decls[i]);
|
||||
struct jaf_block *jaf_parameter(struct jaf_type_specifier *type, struct jaf_declarator *declarator)
|
||||
{
|
||||
struct jaf_block *p = xmalloc(sizeof(struct jaf_block));
|
||||
p->nr_items = 1;
|
||||
p->items = xmalloc(sizeof(struct jaf_block_item*));
|
||||
p->items[0] = xcalloc(1, sizeof(struct jaf_block_item));
|
||||
init_declaration(type, p->items[0], declarator);
|
||||
return p;
|
||||
}
|
||||
|
||||
struct jaf_function_declarator *jaf_function_declarator(struct string *name, struct jaf_block *params)
|
||||
{
|
||||
struct jaf_function_declarator *decl = xmalloc(sizeof(struct jaf_function_declarator));
|
||||
decl->name = name;
|
||||
decl->params = params;
|
||||
return decl;
|
||||
}
|
||||
|
||||
struct jaf_block *jaf_function(struct jaf_type_specifier *type, struct jaf_function_declarator *decl, struct jaf_block *body)
|
||||
{
|
||||
struct jaf_block *p = xmalloc(sizeof(struct jaf_block));
|
||||
p->nr_items = 1;
|
||||
p->items = xmalloc(sizeof(struct jaf_block_item*));
|
||||
p->items[0] = xcalloc(1, sizeof(struct jaf_block_item));
|
||||
p->items[0]->kind = JAF_FUNCTION;
|
||||
p->items[0]->decl.type = type;
|
||||
p->items[0]->decl.name = decl->name;
|
||||
p->items[0]->decl.params = decl->params;
|
||||
p->items[0]->decl.body = body;
|
||||
free(decl);
|
||||
return p;
|
||||
}
|
||||
|
||||
struct jaf_block *jaf_declaration(struct jaf_type_specifier *type, struct jaf_declarator_list *declarators)
|
||||
{
|
||||
struct jaf_block *decls = xcalloc(1, sizeof(struct jaf_block));
|
||||
decls->nr_items = declarators->nr_decls;
|
||||
decls->items = xcalloc(declarators->nr_decls, sizeof(struct jaf_block_item*));
|
||||
for (size_t i = 0; i < declarators->nr_decls; i++) {
|
||||
decls->items[i] = xcalloc(1, sizeof(struct jaf_block_item));
|
||||
init_declaration(type, decls->items[i], declarators->decls[i]);
|
||||
}
|
||||
free(declarators->decls);
|
||||
free(declarators);
|
||||
return decls;
|
||||
}
|
||||
|
||||
struct jaf_declaration_list *jaf_type_declaration(struct jaf_type_specifier *type)
|
||||
struct jaf_block *jaf_type_declaration(struct jaf_type_specifier *type)
|
||||
{
|
||||
struct jaf_declaration_list *decls = xcalloc(1, sizeof(struct jaf_declaration_list));
|
||||
decls->nr_decls = 1;
|
||||
decls->decls = xcalloc(1, sizeof(struct jaf_declaration*));
|
||||
decls->decls[0] = xcalloc(1, sizeof(struct jaf_declaration));
|
||||
decls->decls[0]->type = type;
|
||||
struct jaf_block *decls = xcalloc(1, sizeof(struct jaf_block));
|
||||
decls->nr_items = 1;
|
||||
decls->items = xcalloc(1, sizeof(struct jaf_block_item*));
|
||||
decls->items[0] = xcalloc(1, sizeof(struct jaf_block_item));
|
||||
decls->items[0]->kind = JAF_DECLARATION;
|
||||
decls->items[0]->decl.type = type;
|
||||
return decls;
|
||||
}
|
||||
|
||||
|
||||
struct jaf_declaration_list *jaf_declarations(struct jaf_declaration_list *head, struct jaf_declaration_list *tail)
|
||||
struct jaf_block *jaf_merge_blocks(struct jaf_block *head, struct jaf_block *tail)
|
||||
{
|
||||
if (!head)
|
||||
return tail;
|
||||
|
||||
size_t nr_decls = head->nr_decls + tail->nr_decls;
|
||||
head->decls = xrealloc_array(head->decls, head->nr_decls, nr_decls, sizeof(struct jaf_toplevel_decl*));
|
||||
size_t nr_decls = head->nr_items + tail->nr_items;
|
||||
head->items = xrealloc_array(head->items, head->nr_items, nr_decls, sizeof(struct jaf_toplevel_decl*));
|
||||
|
||||
for (size_t i = 0; i < tail->nr_decls; i++) {
|
||||
head->decls[head->nr_decls+i] = tail->decls[i];
|
||||
for (size_t i = 0; i < tail->nr_items; i++) {
|
||||
head->items[head->nr_items+i] = tail->items[i];
|
||||
}
|
||||
head->nr_decls = nr_decls;
|
||||
head->nr_items = nr_decls;
|
||||
|
||||
free(tail->items);
|
||||
free(tail);
|
||||
return head;
|
||||
}
|
||||
|
||||
struct jaf_block *jaf_block(struct jaf_block_item *item)
|
||||
{
|
||||
struct jaf_block *block = xcalloc(1, sizeof(struct jaf_block));
|
||||
if (!item)
|
||||
return block;
|
||||
block->items = xmalloc(sizeof(struct jaf_block_item*));
|
||||
block->items[0] = item;
|
||||
block->nr_items = 1;
|
||||
return block;
|
||||
}
|
||||
|
||||
static struct jaf_block_item *block_item(enum block_item_kind kind)
|
||||
{
|
||||
struct jaf_block_item *item = xcalloc(1, sizeof(struct jaf_block_item));
|
||||
item->kind = kind;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_compound_statement(struct jaf_block *block)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_COMPOUND);
|
||||
item->block = block;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_label_statement(struct string *label, struct jaf_block_item *stmt)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_LABELED);
|
||||
item->label.name = label;
|
||||
item->label.stmt = stmt;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_case_statement(struct jaf_expression *expr, struct jaf_block_item *stmt)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(expr ? JAF_STMT_CASE : JAF_STMT_DEFAULT);
|
||||
item->swi_case.expr = expr;
|
||||
item->swi_case.stmt = stmt;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_expression_statement(struct jaf_expression *expr)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_EXPRESSION);
|
||||
item->expr = expr;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_if_statement(struct jaf_expression *test, struct jaf_block_item *cons, struct jaf_block_item *alt)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_IF);
|
||||
item->cond.test = test;
|
||||
item->cond.consequent = cons;
|
||||
item->cond.alternative = alt;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_switch_statement(struct jaf_expression *expr, struct jaf_block *body)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_SWITCH);
|
||||
item->swi.expr = expr;
|
||||
item->swi.body = body;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_while_loop(struct jaf_expression *test, struct jaf_block_item *body)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_WHILE);
|
||||
item->while_loop.test = test;
|
||||
item->while_loop.body = body;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_do_while_loop(struct jaf_expression *test, struct jaf_block_item *body)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_DO_WHILE);
|
||||
item->while_loop.test = test;
|
||||
item->while_loop.body = body;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_for_loop(struct jaf_block *init, struct jaf_block_item *test, struct jaf_expression *after, struct jaf_block_item *body)
|
||||
{
|
||||
assert(test->kind == JAF_STMT_EXPRESSION);
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_FOR);
|
||||
item->for_loop.init = init;
|
||||
item->for_loop.test = test->expr;
|
||||
item->for_loop.after = after;
|
||||
item->for_loop.body = body;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_goto(struct string *target)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_GOTO);
|
||||
item->target = target;
|
||||
return item;
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_continue(void)
|
||||
{
|
||||
return block_item(JAF_STMT_CONTINUE);
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_break(void)
|
||||
{
|
||||
return block_item(JAF_STMT_BREAK);
|
||||
}
|
||||
|
||||
struct jaf_block_item *jaf_return(struct jaf_expression *expr)
|
||||
{
|
||||
struct jaf_block_item *item = block_item(JAF_STMT_RETURN);
|
||||
item->expr = expr;
|
||||
return item;
|
||||
}
|
||||
|
||||
void jaf_free_expr(struct jaf_expression *expr)
|
||||
{
|
||||
if (!expr)
|
||||
return;
|
||||
if (expr->type == JAF_EXP_UNARY) {
|
||||
jaf_free_expr(expr->expr);
|
||||
} else if (expr->type == JAF_EXP_BINARY) {
|
||||
@@ -198,3 +355,89 @@ void jaf_free_expr(struct jaf_expression *expr)
|
||||
}
|
||||
free(expr);
|
||||
}
|
||||
|
||||
void jaf_free_type_specifier(struct jaf_type_specifier *type)
|
||||
{
|
||||
if (!type)
|
||||
return;
|
||||
if (type->name)
|
||||
free_string(type->name);
|
||||
jaf_free_block(type->def);
|
||||
free(type);
|
||||
}
|
||||
|
||||
void jaf_free_block_item(struct jaf_block_item *item)
|
||||
{
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
switch (item->kind) {
|
||||
case JAF_DECLARATION:
|
||||
if (item->decl.name)
|
||||
free_string(item->decl.name);
|
||||
jaf_free_type_specifier(item->decl.type);
|
||||
jaf_free_expr(item->decl.init);
|
||||
break;
|
||||
case JAF_FUNCTION:
|
||||
if (item->decl.name)
|
||||
free_string(item->decl.name);
|
||||
jaf_free_type_specifier(item->decl.type);
|
||||
jaf_free_block(item->decl.params);
|
||||
jaf_free_block(item->decl.body);
|
||||
break;
|
||||
case JAF_STMT_LABELED:
|
||||
free_string(item->label.name);
|
||||
jaf_free_block_item(item->label.stmt);
|
||||
break;
|
||||
case JAF_STMT_COMPOUND:
|
||||
jaf_free_block(item->block);
|
||||
break;
|
||||
case JAF_STMT_EXPRESSION:
|
||||
jaf_free_expr(item->expr);
|
||||
break;
|
||||
case JAF_STMT_IF:
|
||||
jaf_free_expr(item->cond.test);
|
||||
jaf_free_block_item(item->cond.consequent);
|
||||
jaf_free_block_item(item->cond.alternative);
|
||||
break;
|
||||
case JAF_STMT_SWITCH:
|
||||
ERROR("switch not supported");
|
||||
break;
|
||||
case JAF_STMT_WHILE:
|
||||
case JAF_STMT_DO_WHILE:
|
||||
jaf_free_expr(item->while_loop.test);
|
||||
jaf_free_block_item(item->while_loop.body);
|
||||
break;
|
||||
case JAF_STMT_FOR:
|
||||
jaf_free_block(item->for_loop.init);
|
||||
jaf_free_expr(item->for_loop.test);
|
||||
jaf_free_expr(item->for_loop.after);
|
||||
jaf_free_block_item(item->for_loop.body);
|
||||
break;
|
||||
case JAF_STMT_GOTO:
|
||||
free_string(item->target);
|
||||
case JAF_STMT_CONTINUE:
|
||||
case JAF_STMT_BREAK:
|
||||
break;
|
||||
case JAF_STMT_RETURN:
|
||||
jaf_free_expr(item->expr);
|
||||
break;
|
||||
case JAF_STMT_CASE:
|
||||
case JAF_STMT_DEFAULT:
|
||||
jaf_free_expr(item->swi_case.expr);
|
||||
jaf_free_block_item(item->swi_case.stmt);
|
||||
break;
|
||||
}
|
||||
free(item);
|
||||
}
|
||||
|
||||
void jaf_free_block(struct jaf_block *block)
|
||||
{
|
||||
if (!block)
|
||||
return;
|
||||
for (size_t i = 0; i < block->nr_items; i++) {
|
||||
jaf_free_block_item(block->items[i]);
|
||||
}
|
||||
free(block->items);
|
||||
free(block);
|
||||
}
|
||||
|
||||
+248
-41
@@ -30,7 +30,7 @@ FILE *yyin;
|
||||
int yyparse(void);
|
||||
|
||||
struct ain *jaf_ain_out;
|
||||
struct jaf_declaration_list *jaf_toplevel;
|
||||
struct jaf_block *jaf_toplevel;
|
||||
|
||||
int sym_type(char *name)
|
||||
{
|
||||
@@ -38,12 +38,13 @@ int sym_type(char *name)
|
||||
struct ain_struct *s = ain_get_struct(jaf_ain_out, u);
|
||||
free(u);
|
||||
|
||||
if (s)
|
||||
if (s) {
|
||||
return TYPEDEF_NAME;
|
||||
}
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
static void define_types(struct ain *ain, struct jaf_declaration *decl);
|
||||
static void define_types(struct ain *ain, struct jaf_block_item *decl);
|
||||
|
||||
void jaf_define_struct(struct ain *ain, struct jaf_type_specifier *type)
|
||||
{
|
||||
@@ -58,21 +59,21 @@ void jaf_define_struct(struct ain *ain, struct jaf_type_specifier *type)
|
||||
type->struct_no = ain_add_struct(ain, u);
|
||||
free(u);
|
||||
|
||||
for (size_t i = 0; i < type->def->nr_decls; i++) {
|
||||
define_types(ain, type->def->decls[i]);
|
||||
for (size_t i = 0; i < type->def->nr_items; i++) {
|
||||
define_types(ain, type->def->items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void define_types(struct ain *ain, struct jaf_declaration *decl)
|
||||
static void define_types(struct ain *ain, struct jaf_block_item *decl)
|
||||
{
|
||||
if (!decl)
|
||||
ERROR("DECL IS NULL");
|
||||
if (!decl->type)
|
||||
if (!decl->decl.type)
|
||||
ERROR("TYPE IS NULL");
|
||||
if (decl->type->type != JAF_STRUCT)
|
||||
if (decl->decl.type->type != JAF_STRUCT)
|
||||
return;
|
||||
|
||||
jaf_define_struct(ain, decl->type);
|
||||
jaf_define_struct(ain, decl->decl.type);
|
||||
}
|
||||
|
||||
static enum ain_data_type jaf_to_ain_data_type(enum jaf_type type)
|
||||
@@ -130,16 +131,88 @@ static void jaf_to_initval(struct ain_initval *dst, struct jaf_expression *expr)
|
||||
}
|
||||
}
|
||||
|
||||
static void analyze_expression(possibly_unused struct ain *ain, struct jaf_expression **expr, struct jaf_type_specifier *type)
|
||||
static void analyze_expression(possibly_unused struct ain *ain, struct jaf_expression **expr)
|
||||
{
|
||||
jaf_check_types(*expr, type);
|
||||
if (!*expr)
|
||||
return;
|
||||
jaf_derive_types(*expr);
|
||||
*expr = jaf_simplify(*expr);
|
||||
}
|
||||
|
||||
static void resolve_types(struct ain *ain, struct jaf_declaration *decl)
|
||||
static void analyze_block(struct ain *ain, struct jaf_block *block);
|
||||
|
||||
static void analyze_statement(struct ain *ain, struct jaf_block_item *item)
|
||||
{
|
||||
if (decl->function)
|
||||
if (!item)
|
||||
return;
|
||||
switch (item->kind) {
|
||||
case JAF_DECLARATION:
|
||||
if (!item->decl.init)
|
||||
break;
|
||||
analyze_expression(ain, &item->decl.init);
|
||||
jaf_check_type(item->decl.init, item->decl.type);
|
||||
// add initval to ain object
|
||||
struct ain_initval init = { .global_index = item->decl.var_no };
|
||||
jaf_to_initval(&init, item->decl.init);
|
||||
ain_add_initval(ain, &init);
|
||||
break;
|
||||
case JAF_FUNCTION:
|
||||
analyze_block(ain, item->decl.body);
|
||||
break;
|
||||
case JAF_STMT_LABELED:
|
||||
analyze_statement(ain, item->label.stmt);
|
||||
break;
|
||||
case JAF_STMT_COMPOUND:
|
||||
analyze_block(ain, item->block);
|
||||
break;
|
||||
case JAF_STMT_EXPRESSION:
|
||||
analyze_expression(ain, &item->expr);
|
||||
break;
|
||||
case JAF_STMT_IF:
|
||||
analyze_expression(ain, &item->cond.test);
|
||||
analyze_statement(ain, item->cond.consequent);
|
||||
analyze_statement(ain, item->cond.alternative);
|
||||
break;
|
||||
case JAF_STMT_SWITCH:
|
||||
analyze_expression(ain, &item->swi.expr);
|
||||
analyze_block(ain, item->swi.body);
|
||||
break;
|
||||
case JAF_STMT_WHILE:
|
||||
case JAF_STMT_DO_WHILE:
|
||||
analyze_expression(ain, &item->while_loop.test);
|
||||
analyze_statement(ain, item->while_loop.body);
|
||||
break;
|
||||
case JAF_STMT_FOR:
|
||||
analyze_block(ain, item->for_loop.init);
|
||||
analyze_expression(ain, &item->for_loop.test);
|
||||
analyze_expression(ain, &item->for_loop.after);
|
||||
analyze_statement(ain, item->for_loop.body);
|
||||
break;
|
||||
case JAF_STMT_RETURN:
|
||||
analyze_expression(ain, &item->expr);
|
||||
break;
|
||||
case JAF_STMT_CASE:
|
||||
case JAF_STMT_DEFAULT:
|
||||
analyze_statement(ain, item->swi_case.stmt);
|
||||
break;
|
||||
case JAF_STMT_GOTO:
|
||||
case JAF_STMT_CONTINUE:
|
||||
case JAF_STMT_BREAK:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void analyze_block(struct ain *ain, struct jaf_block *block)
|
||||
{
|
||||
for (size_t i = 0; i < block->nr_items; i++) {
|
||||
analyze_statement(ain, block->items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void resolve_types(struct ain *ain, struct jaf_block *block);
|
||||
|
||||
static void resolve_decl_types(struct ain *ain, struct jaf_declaration *decl)
|
||||
{
|
||||
if (decl->type->type == JAF_TYPEDEF)
|
||||
resolve_typedef(ain, decl->type);
|
||||
if (decl->type->type != JAF_STRUCT || !decl->type->def)
|
||||
@@ -149,20 +222,163 @@ static void resolve_types(struct ain *ain, struct jaf_declaration *decl)
|
||||
assert(decl->type->struct_no < ain->nr_structures);
|
||||
|
||||
// create struct definition in ain object
|
||||
struct jaf_declaration_list *def = decl->type->def;
|
||||
struct ain_variable *members = xcalloc(def->nr_decls, sizeof(struct ain_variable));
|
||||
for (size_t i = 0; i < def->nr_decls; i++) {
|
||||
members[i].name = encode_text_to_input_format(def->decls[i]->name->text);
|
||||
struct jaf_block *def = decl->type->def;
|
||||
struct ain_variable *members = xcalloc(def->nr_items, sizeof(struct ain_variable));
|
||||
for (size_t i = 0; i < def->nr_items; i++) {
|
||||
members[i].name = encode_text_to_input_format(def->items[i]->decl.name->text);
|
||||
if (ain->version >= 12)
|
||||
members[i].name2 = strdup("");
|
||||
jaf_to_ain_type(ain, &members[i].type, def->decls[i]->type);
|
||||
jaf_to_ain_type(ain, &members[i].type, def->items[i]->decl.type);
|
||||
}
|
||||
|
||||
struct ain_struct *s = &ain->structures[decl->type->struct_no];
|
||||
s->nr_members = def->nr_decls;
|
||||
s->nr_members = def->nr_items;
|
||||
s->members = members;
|
||||
}
|
||||
|
||||
static void resolve_statement_types(struct ain *ain, struct jaf_block_item *item)
|
||||
{
|
||||
switch (item->kind) {
|
||||
case JAF_DECLARATION:
|
||||
resolve_decl_types(ain, &item->decl);
|
||||
break;
|
||||
case JAF_FUNCTION:
|
||||
if (item->decl.params)
|
||||
resolve_types(ain, item->decl.params);
|
||||
resolve_types(ain, item->decl.body);
|
||||
break;
|
||||
case JAF_STMT_LABELED:
|
||||
resolve_statement_types(ain, item->label.stmt);
|
||||
break;
|
||||
case JAF_STMT_COMPOUND:
|
||||
resolve_types(ain, item->block);
|
||||
break;
|
||||
case JAF_STMT_IF:
|
||||
resolve_statement_types(ain, item->cond.consequent);
|
||||
resolve_statement_types(ain, item->cond.alternative);
|
||||
break;
|
||||
case JAF_STMT_SWITCH:
|
||||
resolve_types(ain, item->swi.body);
|
||||
break;
|
||||
case JAF_STMT_WHILE:
|
||||
case JAF_STMT_DO_WHILE:
|
||||
resolve_statement_types(ain, item->while_loop.body);
|
||||
break;
|
||||
case JAF_STMT_FOR:
|
||||
resolve_types(ain, item->for_loop.init);
|
||||
resolve_statement_types(ain, item->for_loop.body);
|
||||
break;
|
||||
case JAF_STMT_CASE:
|
||||
case JAF_STMT_DEFAULT:
|
||||
resolve_statement_types(ain, item->swi_case.stmt);
|
||||
break;
|
||||
case JAF_STMT_EXPRESSION:
|
||||
case JAF_STMT_GOTO:
|
||||
case JAF_STMT_CONTINUE:
|
||||
case JAF_STMT_BREAK:
|
||||
case JAF_STMT_RETURN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void resolve_types(struct ain *ain, struct jaf_block *block)
|
||||
{
|
||||
for (size_t i = 0; i < block->nr_items; i++) {
|
||||
resolve_statement_types(ain, block->items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_variable(struct ain *ain, struct ain_variable *var, struct string *name, struct jaf_type_specifier *type)
|
||||
{
|
||||
var->name = encode_text_to_input_format(name->text);
|
||||
if (ain->version >= 12)
|
||||
var->name2 = strdup("");
|
||||
jaf_to_ain_type(ain, &var->type, type);
|
||||
}
|
||||
|
||||
static struct ain_variable *block_get_vars(struct ain *ain, struct jaf_block *block, struct ain_variable *vars, int *nr_vars);
|
||||
|
||||
static struct ain_variable *block_item_get_vars(struct ain *ain, struct jaf_block_item *item, struct ain_variable *vars, int *nr_vars)
|
||||
{
|
||||
switch (item->kind) {
|
||||
case JAF_DECLARATION:
|
||||
if (!item->decl.name)
|
||||
break;
|
||||
vars = xrealloc_array(vars, *nr_vars, *nr_vars + 1, sizeof(struct ain_variable));
|
||||
init_variable(ain, vars + *nr_vars, item->decl.name, item->decl.type);
|
||||
(*nr_vars)++;
|
||||
break;
|
||||
case JAF_STMT_LABELED:
|
||||
vars = block_item_get_vars(ain, item->label.stmt, vars, nr_vars);
|
||||
break;
|
||||
case JAF_STMT_COMPOUND:
|
||||
vars = block_get_vars(ain, item->block, vars, nr_vars);
|
||||
break;
|
||||
case JAF_STMT_IF:
|
||||
vars = block_item_get_vars(ain, item->cond.consequent, vars, nr_vars);
|
||||
vars = block_item_get_vars(ain, item->cond.alternative, vars, nr_vars);
|
||||
break;
|
||||
case JAF_STMT_SWITCH:
|
||||
vars = block_get_vars(ain, item->swi.body, vars, nr_vars);
|
||||
break;
|
||||
case JAF_STMT_WHILE:
|
||||
case JAF_STMT_DO_WHILE:
|
||||
vars = block_item_get_vars(ain, item->while_loop.body, vars, nr_vars);
|
||||
break;
|
||||
case JAF_STMT_FOR:
|
||||
vars = block_get_vars(ain, item->for_loop.init, vars, nr_vars);
|
||||
vars = block_item_get_vars(ain, item->for_loop.body, vars, nr_vars);
|
||||
break;
|
||||
case JAF_STMT_CASE:
|
||||
case JAF_STMT_DEFAULT:
|
||||
vars = block_item_get_vars(ain, item->swi_case.stmt, vars, nr_vars);
|
||||
break;
|
||||
|
||||
case JAF_STMT_EXPRESSION:
|
||||
case JAF_STMT_GOTO:
|
||||
case JAF_STMT_CONTINUE:
|
||||
case JAF_STMT_BREAK:
|
||||
case JAF_STMT_RETURN:
|
||||
break;
|
||||
|
||||
case JAF_FUNCTION:
|
||||
ERROR("Nested functions not supported");
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
static struct ain_variable *block_get_vars(struct ain *ain, struct jaf_block *block, struct ain_variable *vars, int *nr_vars)
|
||||
{
|
||||
for (size_t i = 0; i < block->nr_items; i++) {
|
||||
vars = block_item_get_vars(ain, block->items[i], vars, nr_vars);
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
static void function_init_vars(struct ain *ain, struct ain_function *f, struct jaf_declaration *decl)
|
||||
{
|
||||
f->nr_args = decl->params ? decl->params->nr_items : 0;
|
||||
f->nr_vars = f->nr_args;
|
||||
f->vars = xcalloc(f->nr_args, sizeof(struct ain_variable));
|
||||
for (int i = 0; i < f->nr_args; i++) {
|
||||
assert(decl->params->items[i]->kind == JAF_DECLARATION);
|
||||
assert(decl->params->items[i]->decl.name);
|
||||
struct jaf_declaration *param = &decl->params->items[i]->decl;
|
||||
init_variable(ain, &f->vars[i], param->name, param->type);
|
||||
}
|
||||
f->vars = block_get_vars(ain, decl->body, f->vars, &f->nr_vars);
|
||||
}
|
||||
|
||||
static void add_function(struct ain *ain, struct jaf_declaration *decl)
|
||||
{
|
||||
struct ain_function f = {0};
|
||||
f.name = strdup(decl->name->text);
|
||||
jaf_to_ain_type(ain, &f.return_type, decl->type);
|
||||
function_init_vars(ain, &f, decl);
|
||||
|
||||
decl->func_no = ain_add_function(ain, &f);
|
||||
}
|
||||
|
||||
static void add_global(struct ain *ain, struct jaf_declaration *decl)
|
||||
{
|
||||
char *u = encode_text_to_input_format(decl->name->text);
|
||||
@@ -172,9 +388,9 @@ static void add_global(struct ain *ain, struct jaf_declaration *decl)
|
||||
free(u);
|
||||
}
|
||||
|
||||
static void compile_declaration(possibly_unused struct ain *ain, struct jaf_declaration *decl)
|
||||
static void compile_declaration(possibly_unused struct ain *ain, struct jaf_block_item *decl)
|
||||
{
|
||||
if (decl->function) {
|
||||
if (decl->kind == JAF_FUNCTION) {
|
||||
WARNING("Functions not supported");
|
||||
return;
|
||||
}
|
||||
@@ -199,32 +415,21 @@ void jaf_compile(struct ain *out, const char *path)
|
||||
ERROR("Failed to parse .jaf file");
|
||||
|
||||
// pass 1: typedefs && struct definitions
|
||||
for (size_t i = 0; i < jaf_toplevel->nr_decls; i++) {
|
||||
resolve_types(out, jaf_toplevel->decls[i]);
|
||||
}
|
||||
resolve_types(out, jaf_toplevel);
|
||||
// pass 2: register globals (names, types)
|
||||
for (size_t i = 0; i < jaf_toplevel->nr_decls; i++) {
|
||||
if (jaf_toplevel->decls[i]->name) {
|
||||
if (jaf_toplevel->decls[i]->function)
|
||||
ERROR("Functions not supported");
|
||||
for (size_t i = 0; i < jaf_toplevel->nr_items; i++) {
|
||||
if (jaf_toplevel->items[i]->decl.name) {
|
||||
if (jaf_toplevel->items[i]->kind == JAF_FUNCTION)
|
||||
add_function(out, &jaf_toplevel->items[i]->decl);
|
||||
else
|
||||
add_global(out, jaf_toplevel->decls[i]);
|
||||
add_global(out, &jaf_toplevel->items[i]->decl);
|
||||
}
|
||||
}
|
||||
// pass 3: type analysis & simplification & global initvals (static analysis)
|
||||
for (size_t i = 0; i < jaf_toplevel->nr_decls; i++) {
|
||||
if (jaf_toplevel->decls[i]->init) {
|
||||
analyze_expression(out, &jaf_toplevel->decls[i]->init, jaf_toplevel->decls[i]->type);
|
||||
|
||||
// add initval to ain object
|
||||
struct ain_initval init = { .global_index = jaf_toplevel->decls[i]->var_no };
|
||||
jaf_to_initval(&init, jaf_toplevel->decls[i]->init);
|
||||
ain_add_initval(out, &init);
|
||||
}
|
||||
}
|
||||
analyze_block(out, jaf_toplevel);
|
||||
// pass 4: generate bytecode
|
||||
for (size_t i = 0; i < jaf_toplevel->nr_decls; i++) {
|
||||
compile_declaration(out, jaf_toplevel->decls[i]);
|
||||
for (size_t i = 0; i < jaf_toplevel->nr_items; i++) {
|
||||
compile_declaration(out, jaf_toplevel->items[i]);
|
||||
}
|
||||
|
||||
// XXX: ain_add_initval adds initval to GSET section of the ain file.
|
||||
@@ -233,4 +438,6 @@ void jaf_compile(struct ain *out, const char *path)
|
||||
if (out->nr_initvals && !out->GSET.present) {
|
||||
WARNING("%d global initvals ignored", out->nr_initvals);
|
||||
}
|
||||
|
||||
jaf_free_block(jaf_toplevel);
|
||||
}
|
||||
|
||||
@@ -49,8 +49,6 @@ extern void yyerror(const char *); /* prints grammar violation message */
|
||||
|
||||
extern int sym_type(const char *); /* returns type from symbol table */
|
||||
|
||||
#define sym_type(identifier) IDENTIFIER /* with no symbol table, fake it */
|
||||
|
||||
static void comment(void);
|
||||
static int check_type(void);
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ void yyerror(const char *s);
|
||||
struct jaf_type_specifier *type;
|
||||
struct jaf_declarator *declarator;
|
||||
struct jaf_declarator_list *declarators;
|
||||
struct jaf_declaration_list *declarations;
|
||||
struct jaf_block *block;
|
||||
struct jaf_block_item *statement;
|
||||
struct jaf_function_declarator *fundecl;
|
||||
}
|
||||
|
||||
%token <string> I_CONSTANT F_CONSTANT STRING_LITERAL
|
||||
@@ -62,8 +64,13 @@ void yyerror(const char *s);
|
||||
%type <type> type_specifier struct_specifier declaration_specifiers
|
||||
%type <declarator> init_declarator declarator
|
||||
%type <declarators> init_declarator_list struct_declarator_list
|
||||
%type <declarations> translation_unit external_declaration declaration
|
||||
%type <declarations> struct_declaration struct_declaration_list
|
||||
%type <block> translation_unit external_declaration declaration function_definition
|
||||
%type <block> struct_declaration struct_declaration_list
|
||||
%type <block> parameter_list parameter_declaration
|
||||
%type <block> compound_statement block_item_list block_item
|
||||
%type <statement> statement labeled_statement expression_statement selection_statement
|
||||
%type <statement> iteration_statement jump_statement
|
||||
%type <fundecl> function_declarator
|
||||
|
||||
/*
|
||||
* Shift-reduce conflicts:
|
||||
@@ -276,7 +283,7 @@ type_parameter_list
|
||||
|
||||
struct_declaration_list
|
||||
: struct_declaration { $$ = $1; }
|
||||
| struct_declaration_list struct_declaration { $$ = jaf_declarations($1, $2); }
|
||||
| struct_declaration_list struct_declaration { $$ = jaf_merge_blocks($1, $2); }
|
||||
;
|
||||
|
||||
struct_declaration
|
||||
@@ -315,8 +322,6 @@ declarator
|
||||
: IDENTIFIER { $$ = jaf_declarator($1); }
|
||||
// | '(' declarator ')' // XXX: causes shift-reduce conflict with function-like casts (e.g. "string(identifier)")
|
||||
| array_allocation { ERROR("Arrays not supported"); }
|
||||
| IDENTIFIER '(' parameter_type_list ')' { ERROR("Function declarator not supported"); } // ??? remove?
|
||||
| IDENTIFIER '(' ')' { ERROR("Function declarator not supported"); } // ??? remove?
|
||||
;
|
||||
|
||||
array_allocation
|
||||
@@ -324,21 +329,6 @@ array_allocation
|
||||
| array_allocation '[' constant ']'
|
||||
;
|
||||
|
||||
parameter_type_list
|
||||
: parameter_list ',' ELLIPSIS
|
||||
| parameter_list
|
||||
;
|
||||
|
||||
parameter_list
|
||||
: parameter_declaration
|
||||
| parameter_list ',' parameter_declaration
|
||||
;
|
||||
|
||||
parameter_declaration
|
||||
: declaration_specifiers declarator
|
||||
| declaration_specifiers
|
||||
;
|
||||
|
||||
initializer
|
||||
: '{' initializer_list '}' { $$ = NULL; }
|
||||
| '{' initializer_list ',' '}' { $$ = NULL; }
|
||||
@@ -367,61 +357,61 @@ designator
|
||||
;
|
||||
|
||||
statement
|
||||
: labeled_statement
|
||||
| compound_statement
|
||||
| expression_statement
|
||||
| selection_statement
|
||||
| iteration_statement
|
||||
| jump_statement
|
||||
: labeled_statement { $$ = $1; }
|
||||
| compound_statement { $$ = jaf_compound_statement($1); }
|
||||
| expression_statement { $$ = $1; }
|
||||
| selection_statement { $$ = $1; }
|
||||
| iteration_statement { $$ = $1; }
|
||||
| jump_statement { $$ = $1; }
|
||||
;
|
||||
|
||||
labeled_statement
|
||||
: IDENTIFIER ':' statement
|
||||
| CASE constant_expression ':' statement
|
||||
| DEFAULT ':' statement
|
||||
: IDENTIFIER ':' statement { $$ = jaf_label_statement($1, $3); }
|
||||
| CASE constant_expression ':' statement { $$ = jaf_case_statement($2, $4); }
|
||||
| DEFAULT ':' statement { $$ = jaf_case_statement(NULL, $3); }
|
||||
;
|
||||
|
||||
compound_statement
|
||||
: '{' '}'
|
||||
| '{' block_item_list '}'
|
||||
: '{' '}' { $$ = jaf_block(NULL); }
|
||||
| '{' block_item_list '}' { $$ = $2; }
|
||||
;
|
||||
|
||||
block_item_list
|
||||
: block_item
|
||||
| block_item_list block_item
|
||||
: block_item { $$ = $1; }
|
||||
| block_item_list block_item { $$ = jaf_merge_blocks($1, $2); }
|
||||
;
|
||||
|
||||
block_item
|
||||
: declaration
|
||||
| statement
|
||||
: declaration { $$ = $1; }
|
||||
| statement { $$ = jaf_block($1); }
|
||||
;
|
||||
|
||||
expression_statement
|
||||
: ';'
|
||||
| expression ';'
|
||||
: ';' { $$ = jaf_expression_statement(NULL); }
|
||||
| expression ';' { $$ = jaf_expression_statement($1); }
|
||||
;
|
||||
|
||||
selection_statement
|
||||
: IF '(' expression ')' statement ELSE statement
|
||||
| IF '(' expression ')' statement
|
||||
| SYM_SWITCH '(' expression ')' statement
|
||||
: IF '(' expression ')' statement ELSE statement { $$ = jaf_if_statement($3, $5, $7); }
|
||||
| IF '(' expression ')' statement { $$ = jaf_if_statement($3, $5, NULL); }
|
||||
| SYM_SWITCH '(' expression ')' compound_statement { $$ = jaf_switch_statement($3, $5); }
|
||||
;
|
||||
|
||||
iteration_statement
|
||||
: WHILE '(' expression ')' statement
|
||||
| DO statement WHILE '(' expression ')' ';'
|
||||
| FOR '(' expression_statement expression_statement ')' statement
|
||||
| FOR '(' expression_statement expression_statement expression ')' statement
|
||||
| FOR '(' declaration expression_statement ')' statement
|
||||
| FOR '(' declaration expression_statement expression ')' statement
|
||||
: WHILE '(' expression ')' statement { $$ = jaf_while_loop($3, $5); }
|
||||
| DO statement WHILE '(' expression ')' ';' { $$ = jaf_do_while_loop($5, $2); }
|
||||
| FOR '(' expression_statement expression_statement ')' statement { $$ = jaf_for_loop(jaf_block($3), $4, NULL, $6); }
|
||||
| FOR '(' expression_statement expression_statement expression ')' statement { $$ = jaf_for_loop(jaf_block($3), $4, $5, $7); }
|
||||
| FOR '(' declaration expression_statement ')' statement { $$ = jaf_for_loop($3, $4, NULL, $6); }
|
||||
| FOR '(' declaration expression_statement expression ')' statement { $$ = jaf_for_loop($3, $4, $5, $7); }
|
||||
;
|
||||
|
||||
jump_statement
|
||||
: GOTO IDENTIFIER ';'
|
||||
| CONTINUE ';'
|
||||
| BREAK ';'
|
||||
| SYM_RETURN ';'
|
||||
| SYM_RETURN expression ';'
|
||||
: GOTO IDENTIFIER ';' { $$ = jaf_goto($2); }
|
||||
| CONTINUE ';' { $$ = jaf_continue(); }
|
||||
| BREAK ';' { $$ = jaf_break(); }
|
||||
| SYM_RETURN ';' { $$ = jaf_return(NULL); }
|
||||
| SYM_RETURN expression ';' { $$ = jaf_return($2); }
|
||||
;
|
||||
|
||||
toplevel
|
||||
@@ -429,17 +419,31 @@ toplevel
|
||||
;
|
||||
|
||||
translation_unit
|
||||
: external_declaration { $$ = jaf_declarations(NULL, $1); }
|
||||
| translation_unit external_declaration { $$ = jaf_declarations($1, $2); }
|
||||
: external_declaration { $$ = jaf_merge_blocks(NULL, $1); }
|
||||
| translation_unit external_declaration { $$ = jaf_merge_blocks($1, $2); }
|
||||
;
|
||||
|
||||
external_declaration
|
||||
: function_definition { ERROR("Functions not yet supported"); }
|
||||
: function_definition { $$ = $1; }
|
||||
| declaration { $$ = $1; }
|
||||
;
|
||||
|
||||
function_definition
|
||||
: declaration_specifiers declarator compound_statement
|
||||
: declaration_specifiers function_declarator compound_statement { $$ = jaf_function($1, $2, $3); }
|
||||
;
|
||||
|
||||
function_declarator
|
||||
: IDENTIFIER '(' parameter_list ')' { $$ = jaf_function_declarator($1, $3); }
|
||||
| IDENTIFIER '(' ')' { $$ = jaf_function_declarator($1, NULL); }
|
||||
;
|
||||
|
||||
parameter_list
|
||||
: parameter_declaration { $$ = $1; }
|
||||
| parameter_list ',' parameter_declaration { $$ = jaf_merge_blocks($1, $3); }
|
||||
;
|
||||
|
||||
parameter_declaration
|
||||
: declaration_specifiers declarator { $$ = jaf_parameter($1, $2); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
#define TYPE_CHECK(expr, expected) { if (expr->derived_type != expected) TYPE_ERROR(expr, expected); }
|
||||
#define TYPE_CHECK_NUMERIC(expr) { if (expr->derived_type != JAF_INT && expr->derived_type != JAF_FLOAT) TYPE_ERROR(expr, JAF_INT); }
|
||||
|
||||
static void jaf_derive_types(struct jaf_expression *expr);
|
||||
|
||||
static enum jaf_type jaf_type_check_numeric(struct jaf_expression *expr)
|
||||
{
|
||||
if (expr->derived_type != JAF_INT && expr->derived_type != JAF_FLOAT)
|
||||
@@ -166,15 +164,13 @@ static enum jaf_type _jaf_check_types(struct jaf_expression *expr)
|
||||
ERROR("Unhandled expression type");
|
||||
}
|
||||
|
||||
static void jaf_derive_types(struct jaf_expression *expr)
|
||||
void jaf_derive_types(struct jaf_expression *expr)
|
||||
{
|
||||
expr->derived_type = _jaf_check_types(expr);
|
||||
}
|
||||
|
||||
void jaf_check_types(struct jaf_expression *expr, struct jaf_type_specifier *type)
|
||||
void jaf_check_type(struct jaf_expression *expr, struct jaf_type_specifier *type)
|
||||
{
|
||||
jaf_derive_types(expr);
|
||||
// TODO: struct types, etc.
|
||||
if (expr->derived_type != type->type) {
|
||||
TYPE_ERROR(expr, type->type);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user