aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-03-05 18:31:55 +0800
committerMistivia <i@mistivia.com>2025-03-05 18:31:55 +0800
commit1ce0d45242097a07b7a4ee539a074ec812851a58 (patch)
tree5825213b60c3da442780e2a3fa1bbc0750ab25f1
parent2c228ecb7d373fd3a7150768302ce0ade6714246 (diff)
finish parser
-rw-r--r--src/as_op.c28
-rw-r--r--src/as_op.h14
-rw-r--r--src/as_parser.c52
-rw-r--r--src/as_parser.h24
-rw-r--r--src/as_tokenizer.c6
-rw-r--r--src/as_tokenizer.h7
6 files changed, 100 insertions, 31 deletions
diff --git a/src/as_op.c b/src/as_op.c
new file mode 100644
index 0000000..847214d
--- /dev/null
+++ b/src/as_op.c
@@ -0,0 +1,28 @@
+#include "as_op.h"
+
+#include <string.h>
+
+struct opTableEntry{
+ Op op;
+ const char* name;
+};
+typedef struct opTableEntry OpTableEntry;
+
+OpTableEntry opTable[] = {
+ {ADD, "add"},
+ {SUB, "sub"},
+ {MUL, "mul"},
+ {DIV, "div"},
+ {MOD, "mod"},
+ {EQ, "eq"},
+ {OPEND, NULL}
+};
+
+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;
+ }
+ }
+ return OPEND;
+}
diff --git a/src/as_op.h b/src/as_op.h
new file mode 100644
index 0000000..ec88670
--- /dev/null
+++ b/src/as_op.h
@@ -0,0 +1,14 @@
+#ifndef FVM_AS_OP_H_
+#define FVM_AS_OP_H_
+
+enum op {
+ ADD, SUB, MUL, DIV, MOD, EQ,
+ // place holder for the end of the table
+ OPEND
+};
+typedef enum op Op;
+
+Op str2op(const char *str);
+
+#endif
+
diff --git a/src/as_parser.c b/src/as_parser.c
index d80cdd9..b419be5 100644
--- a/src/as_parser.c
+++ b/src/as_parser.c
@@ -7,9 +7,9 @@
//
// <prog> ::= <stmts>
// <stmts> ::= <stmt> <newline> | <stmt> <stmts>
-// <stmt> ::= <tag> <instr> | <instr> | <tag>
-// <instr> ::= <op> | <op> <arg> | <op> <label>
-// <tag> ::= <label> :
+// <stmt> ::= <label> <instr> | <instr> | <label>
+// <instr> ::= <op> | <op> <arg> | <op> <tag>
+// <label> ::= <tag> :
// <op> ::= add | sub | mul | div | mod | eq
@@ -38,9 +38,25 @@ Stmts* parseStmts(TokenStream *ts) {
return ss;
}
+Label* parseLabel(TokenStream *ts) {
+ Token *t = nextToken(ts);
+ if (t->type != TAG) {
+ fprintf(stderr, "%d:%d Expect LABEL.\n", t->line, t->col);
+ exit(-1);
+ }
+ Label *l = malloc(sizeof(Label));
+ l->name = t->sval;
+ t = nextToken(ts);
+ if (t->type != COLON) {
+ fprintf(stderr, "%d:%d Expect COLON.\n", t->line, t->col);
+ exit(-1);
+ }
+ return l;
+}
+
Stmt* parseStmt(TokenStream *ts) {
Token *t = peekToken(ts);
- if (t->type == LABEL) {
+ if (t->type == TAG) {
Label *l = parseLabel(ts);
t = peekToken(ts);
if (t->type == COLON) {
@@ -49,23 +65,40 @@ Stmt* parseStmt(TokenStream *ts) {
} else {
Instr *i = parseInstr(ts);
Stmt *s = malloc(sizeof(Stmt));
- s->tag = l;
+ s->label = l;
s->instr = i;
return s;
}
} else {
Instr *i = parseInstr(ts);
Stmt *s = malloc(sizeof(Stmt));
- s->tag = NULL;
+ s->label = NULL;
s->instr = i;
return s;
}
}
+// parse op
+Op parseOp(TokenStream *ts) {
+ Token *t = nextToken(ts);
+ Op op;
+ if (t->type == OP) {
+ op = str2op(t->sval);
+ if (op == OPEND) {
+ fprintf(stderr, "%d:%d Invalid OP.\n", t->line, t->col);
+ exit(-1);
+ }
+ } else {
+ fprintf(stderr, "%d:%d Expect OP.\n", t->line, t->col);
+ exit(-1);
+ }
+ return op;
+}
+
Instr* parseInstr(TokenStream *ts) {
Token *t = nextToken(ts);
Instr *i = malloc(sizeof(Instr));
- i->labelName = NULL;
+ i->tagName = NULL;
if (t->type == OP) {
i->op = parseOp(ts);
t = peekToken(ts);
@@ -73,11 +106,10 @@ Instr* parseInstr(TokenStream *ts) {
Arg *a = malloc(sizeof(Arg));
a->ival = t->ival;
a->fval = t->fval;
- a->sval = t->sval;
i->arg = a;
nextToken(ts);
- } else if (t->type == LABEL) {
- i->labelName = t->sval;
+ } else if (t->type == TAG) {
+ i->tagName = t->sval;
nextToken(ts);
}
}
diff --git a/src/as_parser.h b/src/as_parser.h
index 268f45a..3306909 100644
--- a/src/as_parser.h
+++ b/src/as_parser.h
@@ -1,31 +1,20 @@
+#ifndef FVM_AS_PARSER_H_
+#define FVM_AS_PARSER_H_
+
#include "as_tokenizer.h"
-// BNF
-// ===
-//
-// <prog> ::= <stmts>
-// <stmts> ::= <stmt> <newline> | <stmt> <stmts>
-// <stmt> ::= <tag> <instr> | <instr> | <tag>
-// <instr> ::= <op> | <op> <arg> | <op> <label>
-// <tag> ::= <label> :
-// <op> ::= add | sub | mul | div | mod | eq
-
-enum op {
- ADD, SUB, MUL, DIV, MOD, EQ
-};
-typedef enum op Op;
+#include "as_op.h"
struct arg {
int64_t ival;
double fval;
- const char *sval;
};
typedef struct arg Arg;
struct instr {
Op op;
Arg* arg;
- const char* labelName;
+ const char* tagName;
};
typedef struct instr Instr;
@@ -35,7 +24,7 @@ struct label {
typedef struct label Label;
struct stmt {
- Label* tag;
+ Label* label;
Instr* instr;
};
typedef struct stmt Stmt;
@@ -57,3 +46,4 @@ Instr* parseInstr(TokenStream *ts);
Label* parseLabel(TokenStream *ts);
Op parseOp(TokenStream *ts);
+#endif
diff --git a/src/as_tokenizer.c b/src/as_tokenizer.c
index 7cf244a..23c0ce1 100644
--- a/src/as_tokenizer.c
+++ b/src/as_tokenizer.c
@@ -132,7 +132,7 @@ Token nextTokenImpl(InputStream *s) {
if (isOp(sval)) {
return (Token){.type = OP, .sval = sval, .line = line, .col = col};
}
- return (Token){.type = LABEL, .sval = sval, .line = line, .col = col};
+ return (Token){.type = TAG, .sval = sval, .line = line, .col = col};
}
fprintf(stderr, "error: invalid character %c at line %d, col %d\n", c, s->line, s->col);
}
@@ -164,11 +164,11 @@ void printToken(Token *t) {
switch (t->type) {
case OP:
printf("OP: %s, line: %d, col: %d\n", t->sval, t->line, t->col);
- 狗太厉害了 break;
+ break;
case ARG:
printf("ARG: %ld, line: %d, col: %d\n", t->ival, t->line, t->col);
break;
- case LABEL:
+ case TAG:
printf("LABEL: %s, line: %d, col: %d\n", t->sval, t->line, t->col);
break;
case COLON:
diff --git a/src/as_tokenizer.h b/src/as_tokenizer.h
index fef8625..377aca0 100644
--- a/src/as_tokenizer.h
+++ b/src/as_tokenizer.h
@@ -1,8 +1,11 @@
+#ifndef FMV_AS_TOKENIZER_H_
+#define FMV_AS_TOKENIZER_H_
+
#include <stdint.h>
#include <stdio.h>
typedef enum {
- OP, ARG, LABEL, COLON, NEWLINE, ENDOFFILE
+ OP, ARG, TAG, COLON, NEWLINE, ENDOFFILE
} TokenType;
typedef struct {
@@ -34,3 +37,5 @@ Token *nextToken(TokenStream *ts);
Token *peekToken(TokenStream *ts);
void printToken(Token *t);
TokenStream* makeTokenStream(FILE* fp);
+
+#endif // FMV_AS_TOKENIZER_H_