diff options
| author | Mistivia <i@mistivia.com> | 2025-03-16 20:01:42 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2025-03-16 20:01:42 +0800 |
| commit | b83187f66175d93a0dba45f6d110ed94badac7c5 (patch) | |
| tree | 22710b7a5278ac8a254ead30109f1dd9084d1022 /src | |
| parent | 1ce0d45242097a07b7a4ee539a074ec812851a58 (diff) | |
refactor using allocator pattern
Diffstat (limited to 'src')
| -rw-r--r-- | src/as_main.c | 7 | ||||
| -rw-r--r-- | src/as_op.c | 7 | ||||
| -rw-r--r-- | src/as_op.h | 3 | ||||
| -rw-r--r-- | src/as_parser.c | 103 | ||||
| -rw-r--r-- | src/as_parser.h | 39 | ||||
| -rw-r--r-- | src/as_tokenizer.c | 49 | ||||
| -rw-r--r-- | src/as_tokenizer.h | 39 | ||||
| -rw-r--r-- | src/utils.c | 37 | ||||
| -rw-r--r-- | src/utils.h | 14 |
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_ |
