#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
+#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <setjmp.h>
-void fatal(char* estr);
-void* emalloc(size_t size);
-
-/* Token Types
- *****************************************************************************/
typedef enum {
NONE = 0,
IDENT = 256,
} value;
} Tok;
-/* Lexer and Parser Types
- *****************************************************************************/
typedef struct LexFile {
struct LexFile* next;
char* path;
puts("");
}
+// src/stdlib.c
+void fatal(char* estr);
+void* emalloc(size_t size);
+
+// src/lex.c
void lexfile(Parser* ctx, char* path);
void lex(Parser* ctx);
void lexprintpos(Parser* p, FILE* file, Tok* tok);
+
+// src/parse.c
+Tok* peek(Parser* p);
+void error(Parser* p, const char* fmt, ...);
+bool matches(Parser* p, TokType type);
+bool matches_oneof(Parser* p, TokType types[]);
+bool accept(Parser* p, TokType type);
+void expect(Parser* p, TokType type);
+Tok* expect_val(Parser* p, TokType type);
+char* expect_text(Parser* p, TokType type);
+int consume(Parser* p);
+
+// src/sym.c
+Symbol* symbol_new(Parser* p, char* name, int class, bool export);
+Symbol* symbol_get(Parser* p, int class, char* name);
+
+// src/type_checks.c
+void check_int(Parser* p, Item* item);
+void check_ints(Parser* p, Item* a, Item* b);
+void check_real(Parser* p, Item* item);
+void check_reals(Parser* p, Item* a, Item* b);
+void check_num(Parser* p, Item* a);
+void check_nums(Parser* p, Item* a, Item* b);
+void check_bool(Parser* p, Item* item);
+void check_bools(Parser* p, Item* a, Item* b);
+void check_types(Parser* p, Item* a, Item* b);
+
+// src/grammar.c
void compile(char* fname);
-/* Code Generation
- *****************************************************************************/
+// src/const_ops.c
int items_const(Item* a, Item* b);
void const_binop(int op, Item* a, Item* b);
void const_unop(Parser* p, int op, Item* a);
+/* Backend Code Generation
+ *****************************************************************************/
extern Type BoolType, IntType, RealType, StringType;
void codegen_setint(Item* item, Type* type, long long val);
#ifdef TRACE
static int Indent = 0;
#define RULE(name) \
- void name##_actual(Parser* p, Item* item); \
- void name(Parser* p, Item* item) { \
+ static void name##_actual(Parser* p, Item* item); \
+ static void name(Parser* p, Item* item) { \
printf("%*c-> %s\n", ++Indent * 2, ' ', __func__); \
name##_actual(p, item); \
Indent--; } \
- void name##_actual(Parser* p, Item* item)
+ static void name##_actual(Parser* p, Item* item)
#else
#define RULE(name) \
- void name(Parser* p, Item* item)
+ static void name(Parser* p, Item* item)
#endif
-/* Default Symbols
+/* Default Symbol List
*****************************************************************************/
static Symbol BoolSym = {
.class = SYM_TYPE,
.type = &RealType
};
-/* Parsing Routines
- *****************************************************************************/
-static Tok* peek(Parser* p)
-{
- if (NONE == p->tok.type)
- lex(p);
- return &(p->tok);
-}
-
-static void error(Parser* parser, const char* fmt, ...)
-{
- Tok* tok = peek(parser);
- va_list args;
- va_start(args, fmt);
- lexprintpos(parser, stderr, tok);
- fprintf(stderr, " error: ");
- vfprintf(stderr, fmt, args);
- fprintf(stderr, "\n");
- va_end(args);
- exit(1);
-}
-
-static bool matches(Parser* p, TokType type)
-{
- return (peek(p)->type == type);
-}
-
-static bool matches_oneof(Parser* p, TokType types[])
-{
- for (int i = 0; types[i] != NONE; i++)
- {
- if (matches(p, types[i]))
- {
- return true;
- }
- }
- return false;
-}
-
-static bool accept(Parser* p, TokType type)
-{
- if (matches(p, type)) {
- p->tok.type = NONE;
- return true;
- }
- return false;
-}
-
-static void expect(Parser* p, TokType type)
-{
- if (!accept(p, type))
- error(p, "Unexpected token");
-}
-
-static Tok* expect_val(Parser* p, TokType type)
-{
- static Tok token = {0};
- /* perform the match */
- if (matches(p, type)) {
- token = *(peek(p));
- p->tok.type = NONE;
- } else {
- error(p, "Unexpected token");
- }
- return &token;
-}
-
-static char* expect_text(Parser* p, TokType type)
-{
- return strdup(expect_val(p, type)->text);
-}
-
-static int consume(Parser* p)
-{
- int type = peek(p)->type;
- if (!accept(p, type))
- {
- error(p, "Unexpected token");
- }
- return type;
-}
-
-/* Symbol Table
- *****************************************************************************/
-static Symbol* symbol_new(Parser* p, char* name, int class, bool export)
-{
- Symbol* sym = calloc(1, sizeof(Symbol));
- sym->name = name;
- sym->class = class;
- sym->export = export;
- sym->next = p->scope;
- p->scope = sym;
- return sym;
-}
-
-static Symbol* symbol_get(Parser* p, int class, char* name)
-{
- Symbol* sym = p->scope;
- for (; sym; sym = sym->next)
- {
- if (!strcmp(sym->name, name))
- {
- if (class >= 0 && (int)sym->class != class)
- {
- switch(class)
- {
- case SYM_CONST: error(p, "'%s' is not a constant", name); break;
- case SYM_VAR: error(p, "'%s' is not a variable", name); break;
- case SYM_TYPE: error(p, "'%s' is not a type", name); break;
- default: assert(!"unknown identifier type"); break;
- }
- }
- return sym;
- }
- }
- error(p, "unknown identifier '%s'", name);
- return NULL;
-}
-
/* Item Handling
*****************************************************************************/
static void init_item(Item* item, Symbol* sym)
item->type = sym->type;
}
-/* Type Checking
- *****************************************************************************/
-static void check_int(Parser* p, Item* item)
-{
- if (item->type->form != FORM_INT)
- {
- error(p, "not an int");
- }
-}
-
-static void check_ints(Parser* p, Item* a, Item* b)
-{
- check_int(p, a);
- check_int(p, b);
-}
-
-static void check_real(Parser* p, Item* item)
-{
- if (item->type->form != FORM_REAL)
- {
- error(p, "not a real");
- }
-}
-
-static void check_reals(Parser* p, Item* a, Item* b)
-{
- check_real(p, a);
- check_real(p, b);
-}
-
-static void check_num(Parser* p, Item* a)
-{
- if (a->type->form == FORM_REAL)
- {
- check_real(p, a);
- }
- else
- {
- check_int(p, a);
- }
-}
-
-static void check_nums(Parser* p, Item* a, Item* b)
-{
- if (a->type->form == FORM_REAL)
- {
- check_reals(p, a, b);
- }
- else
- {
- check_ints(p, a, b);
- }
-}
-
-static void check_bool(Parser* p, Item* item)
-{
- if (item->type->form != FORM_BOOL)
- {
- error(p, "not an bool");
- }
-}
-
-static void check_bools(Parser* p, Item* a, Item* b)
-{
- check_bool(p, a);
- check_bool(p, b);
-}
-
-static void check_types(Parser* p, Item* a, Item* b)
-{
- if (a->type->form == FORM_REAL)
- {
- check_reals(p, a, b);
- }
- else if (a->type->form == FORM_INT)
- {
- check_ints(p, a, b);
- }
- else if (a->type->form == FORM_BOOL)
- {
- check_bools(p, a, b);
- }
- else
- {
- error(p, "type mismatch");
- }
-}
-
/* Grammar Definition
*****************************************************************************/
-
static void expression(Parser* p, Item* item);
//RULE(expr_list)
expect(p, END);
}
codegen_endproc(p);
-
-// char* ename = expect_text(p, IDENT);
-// if (strcmp(sname, ename))
-// {
-// error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
-// }
-// expect(p, ';');
}
static inline char* file_load(char* path)
--- /dev/null
+#include "cerise.h"
+
+Tok* peek(Parser* p)
+{
+ if (NONE == p->tok.type)
+ lex(p);
+ return &(p->tok);
+}
+
+void error(Parser* p, const char* fmt, ...)
+{
+ Tok* tok = peek(p);
+ va_list args;
+ va_start(args, fmt);
+ lexprintpos(p, stderr, tok);
+ fprintf(stderr, " error: ");
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ exit(1);
+}
+
+bool matches(Parser* p, TokType type)
+{
+ return (peek(p)->type == type);
+}
+
+bool matches_oneof(Parser* p, TokType types[])
+{
+ for (int i = 0; types[i] != NONE; i++)
+ {
+ if (matches(p, types[i]))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool accept(Parser* p, TokType type)
+{
+ if (matches(p, type)) {
+ p->tok.type = NONE;
+ return true;
+ }
+ return false;
+}
+
+void expect(Parser* p, TokType type)
+{
+ if (!accept(p, type))
+ error(p, "Unexpected token");
+}
+
+Tok* expect_val(Parser* p, TokType type)
+{
+ static Tok token = {0};
+ /* perform the match */
+ if (matches(p, type)) {
+ token = *(peek(p));
+ p->tok.type = NONE;
+ } else {
+ error(p, "Unexpected token");
+ }
+ return &token;
+}
+
+char* expect_text(Parser* p, TokType type)
+{
+ return strdup(expect_val(p, type)->text);
+}
+
+int consume(Parser* p)
+{
+ int type = peek(p)->type;
+ if (!accept(p, type))
+ {
+ error(p, "Unexpected token");
+ }
+ return type;
+}
#include "cerise.h"
-void fatal(char* estr) {
+void fatal(char* estr)
+{
perror(estr);
exit(1);
}
-void* emalloc(size_t size) {
+void* emalloc(size_t size)
+{
void* ptr = malloc(size);
if (!ptr) fatal("malloc()");
return ptr;
--- /dev/null
+#include "cerise.h"
+
+Symbol* symbol_new(Parser* p, char* name, int class, bool export)
+{
+ Symbol* sym = calloc(1, sizeof(Symbol));
+ sym->name = name;
+ sym->class = class;
+ sym->export = export;
+ sym->next = p->scope;
+ p->scope = sym;
+ return sym;
+}
+
+Symbol* symbol_get(Parser* p, int class, char* name)
+{
+ Symbol* sym = p->scope;
+ for (; sym; sym = sym->next)
+ {
+ if (!strcmp(sym->name, name))
+ {
+ if (class >= 0 && (int)sym->class != class)
+ {
+ switch(class)
+ {
+ case SYM_CONST: error(p, "'%s' is not a constant", name); break;
+ case SYM_VAR: error(p, "'%s' is not a variable", name); break;
+ case SYM_TYPE: error(p, "'%s' is not a type", name); break;
+ default: assert(!"unknown identifier type"); break;
+ }
+ }
+ return sym;
+ }
+ }
+ error(p, "unknown identifier '%s'", name);
+ return NULL;
+}
--- /dev/null
+#include "cerise.h"
+
+void check_int(Parser* p, Item* item)
+{
+ if (item->type->form != FORM_INT)
+ {
+ error(p, "not an int");
+ }
+}
+
+void check_ints(Parser* p, Item* a, Item* b)
+{
+ check_int(p, a);
+ check_int(p, b);
+}
+
+void check_real(Parser* p, Item* item)
+{
+ if (item->type->form != FORM_REAL)
+ {
+ error(p, "not a real");
+ }
+}
+
+void check_reals(Parser* p, Item* a, Item* b)
+{
+ check_real(p, a);
+ check_real(p, b);
+}
+
+void check_num(Parser* p, Item* a)
+{
+ if (a->type->form == FORM_REAL)
+ {
+ check_real(p, a);
+ }
+ else
+ {
+ check_int(p, a);
+ }
+}
+
+void check_nums(Parser* p, Item* a, Item* b)
+{
+ if (a->type->form == FORM_REAL)
+ {
+ check_reals(p, a, b);
+ }
+ else
+ {
+ check_ints(p, a, b);
+ }
+}
+
+void check_bool(Parser* p, Item* item)
+{
+ if (item->type->form != FORM_BOOL)
+ {
+ error(p, "not an bool");
+ }
+}
+
+void check_bools(Parser* p, Item* a, Item* b)
+{
+ check_bool(p, a);
+ check_bool(p, b);
+}
+
+void check_types(Parser* p, Item* a, Item* b)
+{
+ if (a->type->form == FORM_REAL)
+ {
+ check_reals(p, a, b);
+ }
+ else if (a->type->form == FORM_INT)
+ {
+ check_ints(p, a, b);
+ }
+ else if (a->type->form == FORM_BOOL)
+ {
+ check_bools(p, a, b);
+ }
+ else
+ {
+ error(p, "type mismatch");
+ }
+}