aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/as_main.c7
-rw-r--r--src/as_op.c7
-rw-r--r--src/as_op.h3
-rw-r--r--src/as_parser.c103
-rw-r--r--src/as_parser.h39
-rw-r--r--src/as_tokenizer.c49
-rw-r--r--src/as_tokenizer.h39
-rw-r--r--src/utils.c37
-rw-r--r--src/utils.h14
9 files changed, 185 insertions, 113 deletions
diff --git a/src/as_main.c b/src/as_main.c
index eb5de20..2809c59 100644
--- a/src/as_main.c
+++ b/src/as_main.c
@@ -1,15 +1,18 @@
#include <stdio.h>
#include "as_tokenizer.h"
+#include "utils.h"
int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "Usage: fvm-as <inputfile>\n");
return 1;
}
-
+ Allocator alct = newAllocator();
FILE *fp = fopen(argv[1], "r");
- TokenStream* ts = makeTokenStream(fp);
+ TokenStream ts = makeTokenStream(alct, fp);
+
+ deleteAllocator(alct);
return 0;
}
diff --git a/src/as_op.c b/src/as_op.c
index 847214d..88884b8 100644
--- a/src/as_op.c
+++ b/src/as_op.c
@@ -3,12 +3,11 @@
#include <string.h>
struct opTableEntry{
- Op op;
+ enum op op;
const char* name;
};
-typedef struct opTableEntry OpTableEntry;
-OpTableEntry opTable[] = {
+struct opTableEntry opTable[] = {
{ADD, "add"},
{SUB, "sub"},
{MUL, "mul"},
@@ -18,7 +17,7 @@ OpTableEntry opTable[] = {
{OPEND, NULL}
};
-Op str2op(const char* str) {
+enum op str2op(const char* str) {
for (int i = 0; opTable[i].name != NULL; i++) {
if (strcmp(opTable[i].name, str) == 0) {
return opTable[i].op;
diff --git a/src/as_op.h b/src/as_op.h
index ec88670..dcd77e0 100644
--- a/src/as_op.h
+++ b/src/as_op.h
@@ -6,9 +6,8 @@ enum op {
// place holder for the end of the table
OPEND
};
-typedef enum op Op;
-Op str2op(const char *str);
+enum op str2op(const char *str);
#endif
diff --git a/src/as_parser.c b/src/as_parser.c
index b419be5..f848730 100644
--- a/src/as_parser.c
+++ b/src/as_parser.c
@@ -1,36 +1,46 @@
#include "as_parser.h"
+#include "as_tokenizer.h"
+#include "utils.h"
+#include <stdio.h>
#include <stdlib.h>
// BNF
// ===
//
// <prog> ::= <stmts>
-// <stmts> ::= <stmt> <newline> | <stmt> <stmts>
+// <stmts> ::= <stmt> newline | <stmt> newline <stmts>
// <stmt> ::= <label> <instr> | <instr> | <label>
-// <instr> ::= <op> | <op> <arg> | <op> <tag>
-// <label> ::= <tag> :
-// <op> ::= add | sub | mul | div | mod | eq
+// <instr> ::= <op> | <op> arg | <op> tag
+// <label> ::= tag ":"
+// <op> ::= "add" | "sub" | "mul" | "div" | "mod" | "eq"
-Prog* parseProg(TokenStream *ts) {
- Prog *p = malloc(sizeof(Prog));
- p->stmts = parseStmts(ts);
+Prog parseProg(Allocator alct, TokenStream ts) {
+ Prog p = allocate(alct, sizeof(struct prog));
+ p->stmts = parseStmts(alct, ts);
return p;
}
-Stmts* parseStmts(TokenStream *ts) {
- Stmts *ss = malloc(sizeof(Stmts));
- ss->stmts = malloc(sizeof(Stmt*));
+Stmts parseStmts(Allocator alct, TokenStream ts) {
+ Stmts ss = allocate(alct, sizeof(struct stmts));
+ ss->stmts = allocate(alct, sizeof(Stmt));
ss->stmts[0] = NULL;
int capacity = 0;
int len = 0;
- while (peekToken(ts)->type != ENDOFFILE) {
- Stmt *s = parseStmt(ts);
+ while (peekToken(alct, ts)->type != ENDOFFILE) {
+ Stmt s = parseStmt(alct, ts);
+ if (s == NULL) continue;
if (len == capacity) {
capacity = capacity * 2 + 1;
ss->stmts = realloc(ss->stmts, sizeof(Stmt*) * capacity);
}
+ // expect newline
+ if (peekToken(alct, ts)->type == NEWLINE) {
+ nextToken(alct, ts);
+ } else {
+ fprintf(stderr, "%d:%d Expect NEWLINE.\n", peekToken(alct, ts)->line, peekToken(alct, ts)->col);
+ }
ss->stmts[len] = s;
len++;
}
@@ -38,15 +48,15 @@ Stmts* parseStmts(TokenStream *ts) {
return ss;
}
-Label* parseLabel(TokenStream *ts) {
- Token *t = nextToken(ts);
+Label parseLabel(Allocator alct, TokenStream ts) {
+ Token t = nextToken(alct, ts);
if (t->type != TAG) {
fprintf(stderr, "%d:%d Expect LABEL.\n", t->line, t->col);
exit(-1);
}
- Label *l = malloc(sizeof(Label));
+ Label l = allocate(alct, sizeof(Label));
l->name = t->sval;
- t = nextToken(ts);
+ t = nextToken(alct, ts);
if (t->type != COLON) {
fprintf(stderr, "%d:%d Expect COLON.\n", t->line, t->col);
exit(-1);
@@ -54,34 +64,33 @@ Label* parseLabel(TokenStream *ts) {
return l;
}
-Stmt* parseStmt(TokenStream *ts) {
- Token *t = peekToken(ts);
+Stmt parseStmt(Allocator alct, TokenStream ts) {
+ Token t = peekToken(alct, ts);
+ Stmt stmt = allocate(alct, sizeof(struct stmt));
+ stmt->label = NULL;
+ stmt->instr = NULL;
if (t->type == TAG) {
- Label *l = parseLabel(ts);
- t = peekToken(ts);
- if (t->type == COLON) {
- nextToken(ts);
- return (Stmt*)l;
- } else {
- Instr *i = parseInstr(ts);
- Stmt *s = malloc(sizeof(Stmt));
- s->label = l;
- s->instr = i;
- return s;
+ stmt->label = parseLabel(alct, ts);
+ if (peekToken(alct, ts)->type == NEWLINE) {
+ return stmt;
}
- } else {
- Instr *i = parseInstr(ts);
- Stmt *s = malloc(sizeof(Stmt));
- s->label = NULL;
- s->instr = i;
- return s;
}
+ if (t->type == OP) {
+ stmt->instr = parseInstr(alct, ts);
+ if (peekToken(alct, ts)->type == NEWLINE) {
+ return stmt;
+ }
+ }
+ if (t->type == NEWLINE) {
+ return NULL;
+ }
+ fprintf(stderr, "%d:%d Expect lable + instruction, lable, or instruction.", t->line, t->col);
+ exit(-1);
}
-// parse op
-Op parseOp(TokenStream *ts) {
- Token *t = nextToken(ts);
- Op op;
+enum op parseOp(Allocator alct, TokenStream ts) {
+ Token t = nextToken(alct, ts);
+ enum op op;
if (t->type == OP) {
op = str2op(t->sval);
if (op == OPEND) {
@@ -95,22 +104,22 @@ Op parseOp(TokenStream *ts) {
return op;
}
-Instr* parseInstr(TokenStream *ts) {
- Token *t = nextToken(ts);
- Instr *i = malloc(sizeof(Instr));
+Instr parseInstr(Allocator alct, TokenStream ts) {
+ Token t = nextToken(alct, ts);
+ Instr i = allocate(alct, sizeof(struct instr));
i->tagName = NULL;
if (t->type == OP) {
- i->op = parseOp(ts);
- t = peekToken(ts);
+ i->op = parseOp(alct, ts);
+ t = peekToken(alct, ts);
if (t->type == ARG) {
- Arg *a = malloc(sizeof(Arg));
+ Arg a = allocate(alct, sizeof(struct arg));
a->ival = t->ival;
a->fval = t->fval;
i->arg = a;
- nextToken(ts);
+ nextToken(alct, ts);
} else if (t->type == TAG) {
i->tagName = t->sval;
- nextToken(ts);
+ nextToken(alct, ts);
}
}
return i;
diff --git a/src/as_parser.h b/src/as_parser.h
index 3306909..a3db024 100644
--- a/src/as_parser.h
+++ b/src/as_parser.h
@@ -2,6 +2,7 @@
#define FVM_AS_PARSER_H_
#include "as_tokenizer.h"
+#include "utils.h"
#include "as_op.h"
@@ -9,41 +10,41 @@ struct arg {
int64_t ival;
double fval;
};
-typedef struct arg Arg;
+typedef struct arg * Arg;
struct instr {
- Op op;
- Arg* arg;
+ enum op op;
+ Arg arg;
const char* tagName;
};
-typedef struct instr Instr;
+typedef struct instr *Instr;
struct label {
const char* name;
};
-typedef struct label Label;
+typedef struct label *Label;
struct stmt {
- Label* label;
- Instr* instr;
+ Label label;
+ Instr instr;
};
-typedef struct stmt Stmt;
+typedef struct stmt *Stmt;
struct stmts {
- Stmt** stmts;
+ Stmt* stmts;
};
-typedef struct stmts Stmts;
+typedef struct stmts *Stmts;
struct prog {
- Stmts *stmts;
+ Stmts stmts;
};
-typedef struct prog Prog;
-
-Prog* parseProg(TokenStream *ts);
-Stmt* parseStmt(TokenStream *ts);
-Stmts* parseStmts(TokenStream *ts);
-Instr* parseInstr(TokenStream *ts);
-Label* parseLabel(TokenStream *ts);
-Op parseOp(TokenStream *ts);
+typedef struct prog *Prog;
+
+Prog parseProg(Allocator alct, TokenStream ts);
+Stmt parseStmt(Allocator alct, TokenStream ts);
+Stmts parseStmts(Allocator alct, TokenStream ts);
+Instr parseInstr(Allocator alct, TokenStream ts);
+Label parseLabel(Allocator alct, TokenStream ts);
+enum op parseOp(Allocator alct, TokenStream ts);
#endif
diff --git a/src/as_tokenizer.c b/src/as_tokenizer.c
index 23c0ce1..4cb695e 100644
--- a/src/as_tokenizer.c
+++ b/src/as_tokenizer.c
@@ -3,8 +3,9 @@
#include <string.h>
#include "as_tokenizer.h"
+#include "utils.h"
-int InputStream_nextChar(InputStream *s) {
+int InputStream_nextChar(InputStream s) {
if (s->cursor == -1) {
return EOF;
}
@@ -28,7 +29,7 @@ int InputStream_nextChar(InputStream *s) {
return c;
}
-int InputStream_peekChar(InputStream *s) {
+int InputStream_peekChar(InputStream s) {
if (s->cursor == -1) {
return EOF;
}
@@ -79,7 +80,8 @@ int isPartOfIndentifier(int c) {
return 0;
}
-Token nextTokenImpl(InputStream *s) {
+Token nextTokenImpl(Allocator alct, InputStream s) {
+ Token t = allocate(alct, sizeof(struct token));
int c;
while (1) {
c = InputStream_peekChar(s);
@@ -88,12 +90,13 @@ Token nextTokenImpl(InputStream *s) {
}
if (c == '\n') {
InputStream_nextChar(s);
- Token t = (Token){.type = NEWLINE, .line = s->line, .col = s->col};
+ *t = (struct token){.type = NEWLINE, .line = s->line, .col = s->col};
return t;
}
if (c == ':') {
InputStream_nextChar(s);
- return (Token){.type = COLON, .line = s->line, .col = s->col};
+ *t = (struct token){.type = COLON, .line = s->line, .col = s->col};
+ return t;
}
if (c == ' ' || c == '\t') {
InputStream_nextChar(s);
@@ -109,12 +112,13 @@ Token nextTokenImpl(InputStream *s) {
break;
}
}
- return (Token){.type = ARG, .ival = ival, .line = s->line, .col = s->col};
+ *t = (struct token){.type = ARG, .ival = ival, .line = s->line, .col = s->col};
+ return t;
}
if (isStartOfIndentifier(c)) {
size_t line = s->line;
size_t col = s->col;
- char *sval = malloc(256);
+ char *sval = allocate(alct, 256);
size_t i = 0;
while(1) {
if (i >= 255) {
@@ -130,37 +134,38 @@ Token nextTokenImpl(InputStream *s) {
}
sval[i] = '\0';
if (isOp(sval)) {
- return (Token){.type = OP, .sval = sval, .line = line, .col = col};
+ *t = (struct token){.type = OP, .sval = sval, .line = line, .col = col};
+ return t;
}
- return (Token){.type = TAG, .sval = sval, .line = line, .col = col};
+ *t = (struct token){.type = TAG, .sval = sval, .line = line, .col = col};
+ return t;
}
fprintf(stderr, "error: invalid character %c at line %d, col %d\n", c, s->line, s->col);
}
// end of file
- return (Token){.type = ENDOFFILE};
+ *t = (struct token){.type = ENDOFFILE};
+ return t;
}
-Token *nextToken(TokenStream *ts) {
+Token nextToken(Allocator alct, TokenStream ts) {
if (ts->buf != NULL) {
- Token *t = ts->buf;
+ Token t = ts->buf;
ts->buf = NULL;
return t;
}
- Token *t = malloc(sizeof(Token));
- *t = nextTokenImpl(ts->s);
+ Token t = nextTokenImpl(alct, ts->s);
return t;
}
-Token *peekToken(TokenStream *ts) {
+Token peekToken(Allocator alct, TokenStream ts) {
if (ts->buf != NULL) {
return ts->buf;
}
- ts->buf = malloc(sizeof(Token));
- *(ts->buf) = nextTokenImpl(ts->s);
+ ts->buf = nextTokenImpl(alct, ts->s);
return ts->buf;
}
-void printToken(Token *t) {
+void printToken(Token t) {
switch (t->type) {
case OP:
printf("OP: %s, line: %d, col: %d\n", t->sval, t->line, t->col);
@@ -183,15 +188,15 @@ void printToken(Token *t) {
}
}
-TokenStream* makeTokenStream(FILE* fp) {
- InputStream *s = malloc(sizeof(InputStream));
+TokenStream makeTokenStream(Allocator alct, FILE* fp) {
+ InputStream s = allocate(alct, sizeof(struct inputStream));
s->fp = fp;
- s->buf = malloc(INPUT_STREAM_BUF_SIZE);
+ s->buf = allocate(alct, INPUT_STREAM_BUF_SIZE);
s->buf_pos = 0;
s->cursor = 0;
s->line = 1;
s->col = 1;
- TokenStream *ts = malloc(sizeof(TokenStream));
+ TokenStream ts = allocate(alct, sizeof(struct tokenStream));
ts->s = s;
ts->buf = NULL;
return ts;
diff --git a/src/as_tokenizer.h b/src/as_tokenizer.h
index 377aca0..e9025ba 100644
--- a/src/as_tokenizer.h
+++ b/src/as_tokenizer.h
@@ -4,38 +4,43 @@
#include <stdint.h>
#include <stdio.h>
-typedef enum {
+#include "utils.h"
+
+enum tokenType {
OP, ARG, TAG, COLON, NEWLINE, ENDOFFILE
-} TokenType;
+};
-typedef struct {
- TokenType type;
+struct token {
+ enum tokenType type;
int line;
int col;
char *sval;
int64_t ival;
double fval;
-} Token;
+};
+typedef struct token *Token;
#define INPUT_STREAM_BUF_SIZE 1024
-typedef struct {
+struct inputStream {
FILE *fp;
char *buf;
int buf_pos;
int cursor;
int line;
int col;
-} InputStream;
-
-typedef struct {
- Token* buf;
- InputStream *s;
-} TokenStream;
-
-Token *nextToken(TokenStream *ts);
-Token *peekToken(TokenStream *ts);
-void printToken(Token *t);
-TokenStream* makeTokenStream(FILE* fp);
+};
+typedef struct inputStream *InputStream;
+
+struct tokenStream {
+ Token buf;
+ InputStream s;
+};
+typedef struct tokenStream *TokenStream;
+
+Token nextToken(Allocator alct, TokenStream ts);
+Token peekToken(Allocator alct, TokenStream ts);
+void printToken(Token t);
+TokenStream makeTokenStream(Allocator alct, FILE* fp);
#endif // FMV_AS_TOKENIZER_H_
diff --git a/src/utils.c b/src/utils.c
new file mode 100644
index 0000000..354159b
--- /dev/null
+++ b/src/utils.c
@@ -0,0 +1,37 @@
+#include "utils.h"
+
+struct allocator {
+ void** bufs;
+ size_t cap;
+ size_t len;
+};
+
+Allocator newAllocator() {
+ Allocator alct = malloc(sizeof(struct allocator));
+ alct->bufs = malloc(sizeof(void*) * 16);
+ alct->cap = 16;
+ alct->len = 0;
+ alct->bufs[0] = NULL;
+ return alct;
+}
+
+void deleteAllocator(Allocator alct) {
+ for (size_t i = 0; i < alct->len; i++) {
+ free(alct->bufs[i]);
+ }
+ free(alct);
+}
+
+void * allocate(Allocator alct, size_t size) {
+ if (alct->len >= alct->cap) {
+ alct->cap = alct->cap * 2; // Doubling the capacity
+ alct->bufs = realloc(alct->bufs, sizeof(void*) * alct->cap);
+ }
+
+ void* ptr = malloc(size); // Allocate requested size
+ alct->bufs[alct->len] = ptr; // Store pointer in array
+ alct->len++;
+ return ptr;
+}
+
+
diff --git a/src/utils.h b/src/utils.h
new file mode 100644
index 0000000..af5e820
--- /dev/null
+++ b/src/utils.h
@@ -0,0 +1,14 @@
+#ifndef FVM_UTILS_H_
+#define FVM_UTILS_H_
+
+#include <stdlib.h>
+
+struct allocator;
+typedef struct allocator *Allocator;
+
+Allocator newAllocator();
+void deleteAllocator(Allocator allocator);
+
+void* allocate(Allocator allocator, size_t size);
+
+#endif // FVM_UTILS_H_