#5
by かずま » 7年前
コードをファイルから入力するようにしてみました。
sml0.c
コード:
#include <stdio.h>
#include <stdlib.h> // exit
#include <string.h> // strtok
#define div div_
enum OP { nop, ldi, opr1, opr2, print, read, jump, cjump, store, load, halt };
enum OPR { neg, not, add, sub, mul, div, mod, less, lseq, gteq, gtr, equ, nteq };
typedef struct { int op; int operand; } Code;
Code code[512];
int mem[1024], stack[256], sp, pc;
void error(const char *msg)
{
printf("[pc:%d, sp:%d] %s\n", pc, sp, msg);
exit(1);
}
void push(int x)
{
if (sp >= 256) error("stack overflow");
stack[sp++] = x;
}
int pop(void)
{
if (sp <= 0) error("stack empty");
return stack[--sp];
}
void do_opr1(int x)
{
int a = pop();
switch (x) {
case neg: push(-a); break;
case not: push(!a); break;
}
}
void do_opr2(int x)
{
int b = pop(), a = pop();
switch (x) {
case add: push(a + b); break;
case sub: push(a - b); break;
case mul: push(a * b); break;
case div: if (b == 0) error("zero divide");
push(a / b); break;
case mod: if (b == 0) error("zero divide");
push(a % b); break;
case less: push(a < b); break;
case lseq: push(a <= b); break;
case gteq: push(a >= b); break;
case gtr: push(a > b); break;
case equ: push(a == b); break;
case nteq: push(a != b); break;
}
}
void do_read(void)
{
int x;
printf("? ");
if (scanf("%d", &x) != 1) error("read failed");
push(x);
}
void do_print(void) { printf(" %d\n", pop()); }
void execute(int a)
{
pc = a;
while (1){
int operand = code[pc].operand;
switch (code[pc++].op) {
case nop : break;
case ldi : push(operand); break;
case opr1 : do_opr1(operand); break;
case opr2 : do_opr2(operand); break;
case print : do_print(); break;
case read : do_read(); break;
case jump : pc = operand; break;
case cjump : if (pop() == 0) pc = operand; break;
case store : mem[operand] = pop(); break;
case load : push(mem[operand]); break;
case halt : return;
default: error("illegal op code");
};
}
}
const char *str_op[] = {
"nop", "ldi", "opr1", "opr2", "print", "read", "jump", "cjump",
"store", "load", "halt"
};
const char *str_opr[] = {
"neg", "not", "add", "sub", "mul", "div", "mod",
"less", "lseq", "gteq", "gtr", "equ", "nteq"
};
const int n_op = sizeof(str_op) / sizeof(*str_op);
const int n_opr = sizeof(str_opr) / sizeof(*str_opr);
int compile(const char *fname)
{
FILE *fp = fopen(fname, "r");
if (!fp) return printf("can't open %s\n", fname), -1;
int ret = 0;
char buf[256], *p;
while (fgets(buf, sizeof buf, fp)) {
char *addr = strtok(buf, " ,:");
char *op = strtok(NULL, " ,");
char *opr = strtok(NULL, " ,;\n");
if (!addr || !op || !opr) { ret = 1; break; }
int i, j, k = strtol(addr, &p, 10);
if (p == addr) { ret = 2; break; }
for (i = 0; i < n_op && strcmp(op, str_op[i]); i++) ;
if (i == n_op) { ret = 3; break; }
int str = 0;
j = strtol(opr, &p, 10);
if (p == opr) {
for (j = 0; j < n_opr && strcmp(opr, str_opr[j]); j++) ;
if (j == n_opr) { ret = 4; break; }
str = 1;
}
code[k].op = i, code[k].operand = j;
if (str)
printf("%3d: %-6s %s\n", k, str_op[i], str_opr[j]);
else
printf("%3d: %-6s %d\n", k, str_op[i], j);
}
fclose(fp);
return ret;
}
int main(int argc, char *argv[])
{
if (argc != 2) return printf("usage: %s file\n", argv[0]), 1;
if (compile(argv[1])) return puts("complie error"), 2;
puts("Executing program...");
execute(0);
printf("[pc:%d, sp:%d] Execution terminated\n", pc, sp);
}
sample2.txt
コード:
0: nop, -1
1, read, -1
2, store 0
3: load 0,
4: ldi, 2 ;
5: opr2, mod ; mem[0] % 2
6: store, 1
7: load, 0
8: ldi, 2
9: opr2, div
10: store, 0
11: load, 1
12: print, -1
13: load, 0
14: cjump, 16
15: jump, 3
16: halt, -1
実行例
コード:
C:\tmp\SML0>sml0 sample2.txt
0: nop -1
1: read -1
2: store 0
3: load 0
4: ldi 2
5: opr2 mod
6: store 1
7: load 0
8: ldi 2
9: opr2 div
10: store 0
11: load 1
12: print -1
13: load 0
14: cjump 16
15: jump 3
16: halt -1
Executing program...
? 12345
1
0
0
1
1
1
0
0
0
0
0
0
1
1
[pc:17, sp:0] Execution terminated
C:\tmp\SML0>
コードをファイルから入力するようにしてみました。
sml0.c
[code=c]
#include <stdio.h>
#include <stdlib.h> // exit
#include <string.h> // strtok
#define div div_
enum OP { nop, ldi, opr1, opr2, print, read, jump, cjump, store, load, halt };
enum OPR { neg, not, add, sub, mul, div, mod, less, lseq, gteq, gtr, equ, nteq };
typedef struct { int op; int operand; } Code;
Code code[512];
int mem[1024], stack[256], sp, pc;
void error(const char *msg)
{
printf("[pc:%d, sp:%d] %s\n", pc, sp, msg);
exit(1);
}
void push(int x)
{
if (sp >= 256) error("stack overflow");
stack[sp++] = x;
}
int pop(void)
{
if (sp <= 0) error("stack empty");
return stack[--sp];
}
void do_opr1(int x)
{
int a = pop();
switch (x) {
case neg: push(-a); break;
case not: push(!a); break;
}
}
void do_opr2(int x)
{
int b = pop(), a = pop();
switch (x) {
case add: push(a + b); break;
case sub: push(a - b); break;
case mul: push(a * b); break;
case div: if (b == 0) error("zero divide");
push(a / b); break;
case mod: if (b == 0) error("zero divide");
push(a % b); break;
case less: push(a < b); break;
case lseq: push(a <= b); break;
case gteq: push(a >= b); break;
case gtr: push(a > b); break;
case equ: push(a == b); break;
case nteq: push(a != b); break;
}
}
void do_read(void)
{
int x;
printf("? ");
if (scanf("%d", &x) != 1) error("read failed");
push(x);
}
void do_print(void) { printf(" %d\n", pop()); }
void execute(int a)
{
pc = a;
while (1){
int operand = code[pc].operand;
switch (code[pc++].op) {
case nop : break;
case ldi : push(operand); break;
case opr1 : do_opr1(operand); break;
case opr2 : do_opr2(operand); break;
case print : do_print(); break;
case read : do_read(); break;
case jump : pc = operand; break;
case cjump : if (pop() == 0) pc = operand; break;
case store : mem[operand] = pop(); break;
case load : push(mem[operand]); break;
case halt : return;
default: error("illegal op code");
};
}
}
const char *str_op[] = {
"nop", "ldi", "opr1", "opr2", "print", "read", "jump", "cjump",
"store", "load", "halt"
};
const char *str_opr[] = {
"neg", "not", "add", "sub", "mul", "div", "mod",
"less", "lseq", "gteq", "gtr", "equ", "nteq"
};
const int n_op = sizeof(str_op) / sizeof(*str_op);
const int n_opr = sizeof(str_opr) / sizeof(*str_opr);
int compile(const char *fname)
{
FILE *fp = fopen(fname, "r");
if (!fp) return printf("can't open %s\n", fname), -1;
int ret = 0;
char buf[256], *p;
while (fgets(buf, sizeof buf, fp)) {
char *addr = strtok(buf, " ,:");
char *op = strtok(NULL, " ,");
char *opr = strtok(NULL, " ,;\n");
if (!addr || !op || !opr) { ret = 1; break; }
int i, j, k = strtol(addr, &p, 10);
if (p == addr) { ret = 2; break; }
for (i = 0; i < n_op && strcmp(op, str_op[i]); i++) ;
if (i == n_op) { ret = 3; break; }
int str = 0;
j = strtol(opr, &p, 10);
if (p == opr) {
for (j = 0; j < n_opr && strcmp(opr, str_opr[j]); j++) ;
if (j == n_opr) { ret = 4; break; }
str = 1;
}
code[k].op = i, code[k].operand = j;
if (str)
printf("%3d: %-6s %s\n", k, str_op[i], str_opr[j]);
else
printf("%3d: %-6s %d\n", k, str_op[i], j);
}
fclose(fp);
return ret;
}
int main(int argc, char *argv[])
{
if (argc != 2) return printf("usage: %s file\n", argv[0]), 1;
if (compile(argv[1])) return puts("complie error"), 2;
puts("Executing program...");
execute(0);
printf("[pc:%d, sp:%d] Execution terminated\n", pc, sp);
}
[/code]
sample2.txt
[code=text]
0: nop, -1
1, read, -1
2, store 0
3: load 0,
4: ldi, 2 ;
5: opr2, mod ; mem[0] % 2
6: store, 1
7: load, 0
8: ldi, 2
9: opr2, div
10: store, 0
11: load, 1
12: print, -1
13: load, 0
14: cjump, 16
15: jump, 3
16: halt, -1
[/code]
実行例
[code=text]
C:\tmp\SML0>sml0 sample2.txt
0: nop -1
1: read -1
2: store 0
3: load 0
4: ldi 2
5: opr2 mod
6: store 1
7: load 0
8: ldi 2
9: opr2 div
10: store 0
11: load 1
12: print -1
13: load 0
14: cjump 16
15: jump 3
16: halt -1
Executing program...
? 12345
1
0
0
1
1
1
0
0
0
0
0
0
1
1
[pc:17, sp:0] Execution terminated
C:\tmp\SML0>
[/code]