Commit 13f46714 authored by Adam Blank's avatar Adam Blank
Browse files

Initial commit

parents
No related merge requests found
Showing with 1101 additions and 0 deletions
+1101 -0
LET A = -7404239191628693210
LET B = 7748583695542236150
LET C = 5031195319121563358
LET D = 3378037775019915204
LET E = -3754175919243794249
LET F = 6995572237482596448
LET G = -5456344146595105850
LET H = -1982520208976527181
LET I = 5732976392927030386
LET J = -6448752908627215080
LET K = -4374678475208681155
LET L = 6470597970749210573
LET M = 3862287631444697661
LET N = -1288093621442744445
LET O = -8651121217966294221
LET P = -4302574712791609167
LET Q = 1814099260616936054
LET R = 7754838282277457456
LET S = 657307039104540490
LET T = 8220379124348257579
LET U = 8344101991900014326
LET V = 7649186912396317687
LET W = 4447077184117691916
LET X = 8502387255623005578
LET Y = -1078437173401034683
LET Z = 7914221386073648075
PRINT A
PRINT B
PRINT C
PRINT D
PRINT E
PRINT F
PRINT G
PRINT H
PRINT I
PRINT J
PRINT K
PRINT L
PRINT M
PRINT N
PRINT O
PRINT P
PRINT Q
PRINT R
PRINT S
PRINT T
PRINT U
PRINT V
PRINT W
PRINT X
PRINT Y
PRINT Z
#-7404239191628693210
#7748583695542236150
#5031195319121563358
#3378037775019915204
#-3754175919243794249
#6995572237482596448
#-5456344146595105850
#-1982520208976527181
#5732976392927030386
#-6448752908627215080
#-4374678475208681155
#6470597970749210573
#3862287631444697661
#-1288093621442744445
#-8651121217966294221
#-4302574712791609167
#1814099260616936054
#7754838282277457456
#657307039104540490
#8220379124348257579
#8344101991900014326
#7649186912396317687
#4447077184117691916
#8502387255623005578
#-1078437173401034683
#7914221386073648075
#24
#2
#5
#2
#5
LET A = 1 * 2 * 3 * 4
PRINT A
LET A = 2
PRINT A
LET Z = 5
PRINT Z
PRINT A
PRINT Z
#24
#48
#11520
#48
#11520
LET A = 1 * 2 * 3 * 4
PRINT A
LET A = 2 * A
PRINT A
LET Z = A * A * 5
PRINT Z
PRINT A
PRINT Z
This diff is collapsed.
#3
#4
#5
00 GOTO 50
10 LET X = 1
20 LET X = X + 1
30 PRINT X
40 GOTO 100
50 LET X = 3
60 PRINT X
70 LET X = 4
80 PRINT X
90 GOTO 20
100
000 PRINT 0
010 PRINT 1
020 GOTO 170
030 PRINT 5
040 GOTO 060
050 PRINT 9
060 PRINT 6
070 PRINT 7
080 GOTO 220
090 PRINT 10
100 GOTO 010
110 PRINT 11
120 PRINT 3
130 GOTO 190
140 PRINT 12
150 PRINT 13
160 PRINT 14
170 PRINT 2
180 GOTO 120
190 PRINT 4
200 GOTO 030
210 PRINT 15
220 PRINT 8
#0
#1
#2
#3
#4
#5
#6
#7
#8
LET A = -20
LET B = -10
LET C = 0
LET D = 10
LET E = 20
LET F = 30
LET G = 40
LET H = 50
#1
IF D < E THEN PRINT 1
IF D = E THEN PRINT 2
IF D > E THEN PRINT 3
#5
IF H < H THEN PRINT 4
IF H = H THEN PRINT 5
IF H > H THEN PRINT 6
#9
IF G < F THEN PRINT 7
IF G = F THEN PRINT 8
IF G > F THEN PRINT 9
#10
IF A < D THEN PRINT 10
IF A = D THEN PRINT 11
IF A > D THEN PRINT 12
#15
IF F < A THEN PRINT 13
IF F = A THEN PRINT 14
IF F > A THEN PRINT 15
#16
IF A < B THEN PRINT 16
IF A = B THEN PRINT 17
IF A > B THEN PRINT 18
#21
IF B < A THEN PRINT 19
IF B = A THEN PRINT 20
IF B > A THEN PRINT 21
#23
IF B < B THEN PRINT 22
IF B = B THEN PRINT 23
IF B > B THEN PRINT 24
LET C = 1
20 PRINT C
LET C = C + 1
IF C > 20 THEN GOTO 60
GOTO 20
60
#1
#2
#3
#4
#5
#6
#7
#8
#9
#10
#11
#12
#13
#14
#15
#16
#17
#18
#19
#20
# Taken from https://projecteuler.net/problem=30
#443839
000 LET X = 1
010 LET R = 0
020 LET X = X + 1
030 IF X > 1000000 THEN GOTO 140
040 LET Y = X
050 LET S = 0
060 GOTO 080
070 LET Y = Z
080 LET Z = Y / 10
090 LET D = Y - Z * 10
100 LET S = S + D * D * D * D * D
110 IF Z > 0 THEN GOTO 070
120 IF S = X THEN LET R = R + X
130 GOTO 020
140 PRINT R
# Taken from https://projecteuler.net/problem=36
#872187
000 LET X = 0
010 LET R = 0
020 LET X = X + 1
030 IF X = 1000000 THEN GOTO 220
040 LET Y = X
050 LET E = 0
060 GOTO 080
070 LET Y = Z
080 LET Z = Y / 10
090 LET E = E * 10 + Y - Z * 10
100 IF Z > 0 THEN GOTO 070
110 IF E = X THEN GOTO 130
120 GOTO 020
130 LET Y = X
140 LET E = 0
150 GOTO 170
160 LET Y = Z
170 LET Z = Y / 2
180 LET E = E * 2 + Y - Z * 2
190 IF Z > 0 THEN GOTO 160
200 IF E = X THEN LET R = R + X
210 GOTO 020
220 PRINT R
00 LET X = 1
10 IF X / 3 * 3 < X THEN IF X / 5 * 5 < X THEN PRINT 0 - X
20 IF X / 3 * 3 = X THEN IF X / 5 * 5 < X THEN PRINT 3
30 IF X / 3 * 3 < X THEN IF X / 5 * 5 = X THEN PRINT 5
40 IF X / 3 * 3 = X THEN IF X / 5 * 5 = X THEN PRINT 15
50 LET X = X + 1
60 IF X < 100 THEN GOTO 10
#-1
#-2
#3
#-4
#5
#3
#-7
#-8
#3
#5
#-11
#3
#-13
#-14
#15
#-16
#-17
#3
#-19
#5
#3
#-22
#-23
#3
#5
#-26
#3
#-28
#-29
#15
#-31
#-32
#3
#-34
#5
#3
#-37
#-38
#3
#5
#-41
#3
#-43
#-44
#15
#-46
#-47
#3
#-49
#5
#3
#-52
#-53
#3
#5
#-56
#3
#-58
#-59
#15
#-61
#-62
#3
#-64
#5
#3
#-67
#-68
#3
#5
#-71
#3
#-73
#-74
#15
#-76
#-77
#3
#-79
#5
#3
#-82
#-83
#3
#5
#-86
#3
#-88
#-89
#15
#-91
#-92
#3
#-94
#5
#3
#-97
#-98
#3
# Prints all the primes below 1000
00 LET P = 2
10 LET T = 2
20 IF T * T > P THEN GOTO 60
30 IF P / T * T = P THEN GOTO 70
40 LET T = T + 1
50 GOTO 20
60 PRINT P
70 LET P = P + 1
80 IF P < 1000 THEN GOTO 10
#2
#3
#5
#7
#11
#13
#17
#19
#23
#29
#31
#37
#41
#43
#47
#53
#59
#61
#67
#71
#73
#79
#83
#89
#97
#101
#103
#107
#109
#113
#127
#131
#137
#139
#149
#151
#157
#163
#167
#173
#179
#181
#191
#193
#197
#199
#211
#223
#227
#229
#233
#239
#241
#251
#257
#263
#269
#271
#277
#281
#283
#293
#307
#311
#313
#317
#331
#337
#347
#349
#353
#359
#367
#373
#379
#383
#389
#397
#401
#409
#419
#421
#431
#433
#439
#443
#449
#457
#461
#463
#467
#479
#487
#491
#499
#503
#509
#521
#523
#541
#547
#557
#563
#569
#571
#577
#587
#593
#599
#601
#607
#613
#617
#619
#631
#641
#643
#647
#653
#659
#661
#673
#677
#683
#691
#701
#709
#719
#727
#733
#739
#743
#751
#757
#761
#769
#773
#787
#797
#809
#811
#821
#823
#827
#829
#839
#853
#857
#859
#863
#877
#881
#883
#887
#907
#911
#919
#929
#937
#941
#947
#953
#967
#971
#977
#983
#991
#997
# Computes the square root of a number
#1834817011
000 LET A = 3366553463854974121
010 LET C = 1
020 LET B = C
030 LET C = C * 2
040 IF C * C > 0 THEN GOTO 020
050 LET Z = 0
060 LET Y = Z + B
070 IF Y * Y > A THEN GOTO 090
080 LET Z = Y
090 LET B = B / 2
100 IF B > 0 THEN GOTO 060
110 PRINT Z
# Taken from https://projecteuler.net/problem=92
#8581146
000 LET X = 2
010 LET C = 0
020 GOTO 060
030 LET C = C + 1
040 LET X = X + 1
050 IF X = 10000000 THEN GOTO 160
060 LET Z = X
070 LET S = 0
080 LET Y = Z
090 LET Z = Y / 10
100 LET S = S + (Y - Z * 10) * (Y - Z * 10)
110 IF Z > 0 THEN GOTO 080
120 IF S = 89 THEN GOTO 030
130 IF S = 1 THEN GOTO 040
140 LET Z = S
150 GOTO 070
160 PRINT C
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include "ast.h"
node_t *init_num_node(char *num_as_str) {
if (!num_as_str) {
return NULL;
}
num_node_t *node = malloc(sizeof(num_node_t));
assert(node);
node->base.type = NUM;
node->value = strtol(num_as_str, NULL, 0);
free(num_as_str);
return (node_t *) node;
}
node_t *init_binary_node(char op, node_t *left, node_t *right) {
if (!left || !right) {
free_ast(left);
free_ast(right);
return NULL;
}
binary_node_t *node = malloc(sizeof(binary_node_t));
assert(node);
node->base.type = BINARY_OP;
node->op = op;
node->left = left;
node->right = right;
return (node_t *) node;
}
node_t *init_var_node(char name) {
if (name == '\0') {
return NULL;
}
var_node_t *node = malloc(sizeof(var_node_t));
assert(node);
node->base.type = VAR;
node->name = name;
return (node_t *) node;
}
node_t *init_print_node(node_t *expr) {
if (!expr) {
return NULL;
}
print_node_t *node = malloc(sizeof(print_node_t));
assert(node);
node->base.type = PRINT;
node->expr = expr;
return (node_t *) node;
}
node_t *init_let_node(char name, node_t *value) {
if (name == '\0' || !value) {
free_ast(value);
return NULL;
}
let_node_t *node = malloc(sizeof(let_node_t));
assert(node);
node->base.type = LET;
node->name = name;
node->value = value;
return (node_t *) node;
}
node_t *init_label_node(char *label) {
if (!label) {
return NULL;
}
label_node_t *node = malloc(sizeof(label_node_t));
assert(node);
node->base.type = LABEL;
node->label = label;
return (node_t *) node;
}
node_t *init_goto_node(char *label) {
if (!label) {
return NULL;
}
goto_node_t *node = malloc(sizeof(goto_node_t));
assert(node);
node->base.type = GOTO;
node->label = label;
return (node_t *) node;
}
node_t *init_cond_node(node_t *condition, node_t *if_branch) {
if (!condition || !if_branch) {
free_ast(condition);
free_ast(if_branch);
return NULL;
}
cond_node_t *node = malloc(sizeof(cond_node_t));
assert(node);
node->base.type = COND;
node->condition = condition;
node->if_branch = if_branch;
return (node_t *) node;
}
void free_ast(node_t *node) {
if (!node) {
return;
}
if (node->type == BINARY_OP) {
binary_node_t *bin = (binary_node_t *) node;
free_ast(bin->left);
free_ast(bin->right);
}
else if (node->type == PRINT) {
free_ast(((print_node_t *) node)->expr);
}
else if (node->type == LET) {
free_ast(((let_node_t *) node)->value);
}
else if (node->type == LABEL) {
free(((label_node_t *) node)->label);
}
else if (node->type == GOTO) {
free(((goto_node_t *) node)->label);
}
else if (node->type == COND) {
cond_node_t *cond = (cond_node_t *) node;
free_ast(cond->condition);
free_ast(cond->if_branch);
}
free(node);
}
void print_ast(node_t *node) {
if (node->type == NUM) {
fprintf(stderr, "%" PRId64, ((num_node_t *) node)->value);
}
else if (node->type == BINARY_OP) {
binary_node_t *bin = (binary_node_t *) node;
fprintf(stderr, "%c(", bin->op);
print_ast(bin->left);
fprintf(stderr, ", ");
print_ast(bin->right);
fprintf(stderr, ")");
}
else if (node->type == VAR) {
fprintf(stderr, "%c", ((var_node_t *) node)->name);
}
else if (node->type == PRINT) {
fprintf(stderr, "PRINT(");
print_ast(((print_node_t *) node)->expr);
fprintf(stderr, ")");
}
else if (node->type == LET) {
let_node_t *let = (let_node_t *) node;
fprintf(stderr, "LET(%c, ", let->name);
print_ast(let->value);
fprintf(stderr, ")");
}
else if (node->type == LABEL) {
fprintf(stderr, "LABEL(%s)", ((label_node_t *) node)->label);
}
else if (node->type == GOTO) {
fprintf(stderr, "GOTO(%s)", ((goto_node_t *) node)->label);
}
else if (node->type == COND) {
cond_node_t *cond = (cond_node_t *) node;
fprintf(stderr, "IF(");
print_ast(cond->condition);
fprintf(stderr, ", ");
print_ast(cond->if_branch);
fprintf(stderr, ")");
}
else {
fprintf(stderr, "\nUnknown node type: %d\n", node->type);
exit(1);
}
}
#include <stdlib.h>
#include <stdio.h>
#include "compile.h"
bool compile_ast(node_t *node) {
/* You should remove this cast to void in your solution.
* It is just here so the code compiles without warnings. */
(void) node;
return false; // for now, every statement causes a compilation failure
}
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include "parser.h"
#include "compile.h"
void usage(char *program) {
fprintf(stderr, "USAGE: %s <program file>\n", program);
exit(1);
}
/**
* Prints the start of the the x86-64 assembly output.
* The assembly code implementing the TeenyBASIC statements
* goes between the header and the footer.
*/
void header(void) {
puts(
"# Declares a string constant to pass to printf()\n"
".section .rodata\n"
"intfmt:\n"
" .string \"%" PRId64 "\\n\"\n"
"\n"
"# The code section of the assembly file\n"
".text\n"
"print_int:\n"
" # Calls printf(intfmt, %rdi)\n"
" movq %rdi, %rsi\n"
" leaq intfmt(%rip), %rdi # LABEL(%rip) computes the address of LABEL relative to %rip\n"
" movb $0, %al # %al stores the number of float arguments to printf()\n"
" call printf@plt\n"
" ret\n"
"\n"
".globl main\n"
"main:\n"
" # The main() function"
);
}
/**
* Prints the end of the x86-64 assembly output.
* The assembly code implementing the TeenyBASIC statements
* goes between the header and the footer.
*/
void footer(void) {
puts(
" movl $0, %eax # return 0 from main()\n"
" ret"
);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
usage(argv[0]);
}
FILE *program = fopen(argv[1], "r");
if (!program) {
usage(argv[0]);
}
header();
while (!feof(program)) {
node_t *ast = parse(program);
if (ast) { // skip comments; only compile statements
// Display the AST for debugging purposes
print_ast(ast);
fprintf(stderr, "\n");
// Compile the AST into assembly instructions
if (!compile_ast(ast)) {
fprintf(stderr, "Compilation Error.\n");
fclose(program);
exit(3);
}
free_ast(ast);
}
}
fclose(program);
footer();
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include <ctype.h>
#include "parser.h"
// maxint = -9223372036854775808
#define MAX_KEYWORD_LENGTH 100
typedef struct {
FILE *stream;
} parser_state_t;
bool is_variable_name(char c) {
return isupper(c);
}
bool is_number_start(char c) {
return c == '+' || c == '-' || isdigit(c);
}
bool is_expression_start(char c) {
return c == '(' || is_variable_name(c) || is_number_start(c);
}
bool is_operator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' ||
c == '<' || c == '=' || c == '>' ||
c == '(' || c == ')';
}
/*
* Advances the provided state to the next token.
*/
char advance(parser_state_t *state) {
int result;
do {
result = fgetc(state->stream);
if (result == EOF) {
return '\0';
}
} while (isspace(result));
return result;
}
void rewind_one(parser_state_t *state) {
fseek(state->stream, -1, SEEK_CUR);
}
char peek(parser_state_t *state) {
char result = advance(state);
rewind_one(state);
return result;
}
char *advance_until_separator(parser_state_t *state) {
char *result = malloc((MAX_KEYWORD_LENGTH + 1) * sizeof(char));
assert(result);
size_t index = 0;
while (true) {
int c = fgetc(state->stream);
if (c == EOF) {
free(result);
return NULL;
}
if (is_operator(c) && index > 0) {
rewind_one(state);
c = ' ';
}
if (isspace(c)) {
result[index] = '\0';
return result;
}
result[index++] = c;
}
}
void skip_line(parser_state_t *state) {
rewind_one(state);
while (true) {
int character = fgetc(state->stream);
if (character == EOF || character == '\n') {
break;
}
}
}
node_t *expression(parser_state_t *);
node_t *factor(parser_state_t *state) {
char next = peek(state);
if (next == '\0') {
return NULL;
}
if (next == '(') {
advance(state);
node_t *node = expression(state);
char next = advance(state);
if (next != ')') {
rewind_one(state);
return NULL;
}
return node;
}
if (is_variable_name(next)) {
return init_var_node(advance(state));
}
if (is_number_start(next)) {
return init_num_node(advance_until_separator(state));
}
return NULL;
}
node_t *term(parser_state_t *state) {
node_t *result = factor(state);
while (true) {
char next = advance(state);
if (!(next == '*' || next == '/')) {
rewind_one(state);
break;
}
result = init_binary_node(next, result, factor(state));
}
return result;
}
node_t *expression(parser_state_t *state) {
if (!is_expression_start(peek(state))) {
return NULL;
}
node_t *result = term(state);
while (true) {
char next = advance(state);
if (!(next == '+' || next == '-')) {
rewind_one(state);
break;
}
result = init_binary_node(next, result, term(state));
}
return result;
}
node_t *comparison(parser_state_t *state) {
node_t *left = expression(state);
char op = advance(state);
if (!(op == '<' || op == '=' || op == '>')) {
return NULL;
}
return init_binary_node(op, left, expression(state));
}
node_t *statement(parser_state_t *state) {
char *next = advance_until_separator(state);
if (!next || next[0] == '\0') {
free(next);
return NULL;
}
if (next[0] == '#') {
free(next);
skip_line(state);
return NULL;
}
if (!strcmp("GOTO", next)) {
free(next);
return init_goto_node(advance_until_separator(state));
}
else if (!strcmp("PRINT", next)) {
free(next);
return init_print_node(expression(state));
}
else if (!strcmp("LET", next)) {
free(next);
char var = advance(state);
if (isupper(var) && advance(state) == '=') {
return init_let_node(var, expression(state));
}
else {
return NULL;
}
}
else if (!strcmp("IF", next)) {
free(next);
node_t *cond = comparison(state);
next = advance_until_separator(state);
if (strcmp(next, "THEN")) {
free(next);
return NULL;
}
else {
free(next);
return init_cond_node(cond, statement(state));
}
}
else {
return init_label_node(next);
}
}
node_t *parse(FILE *stream) {
parser_state_t *state = malloc(sizeof(parser_state_t));
assert(state);
state->stream = stream;
node_t *ast = statement(state);
free(state);
return ast;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment