~kikoodx/bf.vala

8f6df796238f0c783fdf3ce913c51df4ad65c714 — kdx 3 months ago
initial commit
6 files changed, 113 insertions(+), 0 deletions(-)

A bf.vala
A build.sh
A check.vala
A execute.vala
A lex.vala
A token.vala
A  => bf.vala +11 -0
@@ 1,11 @@
int main(string[] args) {
	Token[] tokens = {};
	foreach(var arg in args[1:args.length])
		tokens = lex(tokens, arg);
	if (!check(tokens)) {
		stdout.printf("input program is invalid\n");
		return 1;
	}
	execute(tokens);
	return 0;
}

A  => build.sh +2 -0
@@ 1,2 @@
#!/bin/sh
valac bf.vala *.vala

A  => check.vala +18 -0
@@ 1,18 @@
bool check(Token[] tokens) {
	int opened = 0;
	foreach (var tok in tokens) {
		switch (tok) {
		case LOOP_OPEN:
			opened++;
			break;
		case LOOP_CLOSE:
			opened--;
			if (opened < 0)
				return false;
			break;
		default:
			break;
		}
	}
	return (opened == 0);
}

A  => execute.vala +47 -0
@@ 1,47 @@
const ssize_t MEMORY_SIZE = 30000;

void execute(Token[] tokens) {
	var memory = new uchar[MEMORY_SIZE];
	for (var i = 0; i < MEMORY_SIZE; i++)
		memory[i] = 0;
	ssize_t ptr = 0;

	for (var i = 0; i < tokens.length; i++) {
		switch (tokens[i]) {
		case LEFT:
			ptr--;
			if (ptr < 0)
				ptr = MEMORY_SIZE - 1;
			break;
		case RIGHT:
			ptr++;
			if (ptr == MEMORY_SIZE)
				ptr = 0;
			break;
		case PLUS:
			memory[ptr]++;
			break;
		case MINUS:
			memory[ptr]--;
			break;
		case WRITE:
			stdout.putc((char)memory[ptr]);
			break;
		case READ:
			memory[ptr] = (uchar)stdin.getc();
			break;
		case LOOP_OPEN:
			if (memory[ptr] == 0)
				while (tokens[i] != LOOP_CLOSE)
					i++;
			break;
		case LOOP_CLOSE:
			while (tokens[i] != LOOP_OPEN)
				i--;
			i--;
			break;
		default:
			break;
		}
	}
}

A  => lex.vala +10 -0
@@ 1,10 @@
Token[] lex(owned Token[] tokens, string src) {
	for (var i = 0; i < src.length; i++) {
		var tok = token_from_char(src[i]);
		if (tok != Token.SKIP) {
			tokens.resize(tokens.length + 1);
			tokens[tokens.length - 1] = tok;
		}
	}
	return tokens;
}

A  => token.vala +25 -0
@@ 1,25 @@
enum Token {
	LEFT,
	RIGHT,
	PLUS,
	MINUS,
	WRITE,
	READ,
	LOOP_OPEN,
	LOOP_CLOSE,
	SKIP;
}

Token token_from_char(char c) {
	switch (c) {
	case '<': return LEFT;
	case '>': return RIGHT;
	case '+': return PLUS;
	case '-': return MINUS;
	case '.': return WRITE;
	case ',': return READ;
	case '[': return LOOP_OPEN;
	case ']': return LOOP_CLOSE;
	default:  return SKIP;
	}
}