|
@@ -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;
|