aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-20 08:03:20 +0200
committerFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-20 08:03:20 +0200
commit77339ce34a79a7b5a1818c1009d1db1252fe8ea6 (patch)
tree0fa1cc0819b0be255dd37b0774d088b11fc0cc92
parentee64135583d5ba02b57cd520bb50ca8819d37bff (diff)
downloadimp-77339ce34a79a7b5a1818c1009d1db1252fe8ea6.tar.gz
imp-77339ce34a79a7b5a1818c1009d1db1252fe8ea6.zip
cleanup
-rw-r--r--README.md2
-rw-r--r--ast.c226
-rw-r--r--ast.h35
-rw-r--r--lexer.l4
-rw-r--r--parser.y6
5 files changed, 141 insertions, 132 deletions
diff --git a/README.md b/README.md
index b05b025..bbc7b31 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
A small interpreter of the IMP programming language.
-# Build
+## Build
- `make all` to build interpreter.
- `make run` to interpret "example.imp".
diff --git a/ast.c b/ast.c
index ab7e1e0..4663cd2 100644
--- a/ast.c
+++ b/ast.c
@@ -4,13 +4,9 @@
#include "ast.h"
static ASTNode *new_node(NodeType type) {
- ASTNode *n = malloc(sizeof(ASTNode));
- if (!n) {
- fprintf(stderr, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
- n->type = type;
- return n;
+ ASTNode *node = malloc(sizeof(ASTNode));
+ node->type = type;
+ return node;
}
ASTNode *ast_skip(void) {
@@ -18,142 +14,148 @@ ASTNode *ast_skip(void) {
}
ASTNode *ast_assign(ASTNode *var, ASTNode *aexp) {
- ASTNode *n = new_node(NT_ASSIGN);
- n->u.assign.var = var;
- n->u.assign.aexp = aexp;
- return n;
+ ASTNode *node = new_node(NT_ASSIGN);
+ node->u.d_assign.var = var;
+ node->u.d_assign.aexp = aexp;
+ return node;
}
-ASTNode *ast_seq(ASTNode *s1, ASTNode *s2) {
- ASTNode *n = new_node(NT_SEQ);
- n->u.seq.s1 = s1;
- n->u.seq.s2 = s2;
- return n;
+ASTNode *ast_seq(ASTNode *stm1, ASTNode *stm2) {
+ ASTNode *node = new_node(NT_SEQ);
+ node->u.d_seq.stm1 = stm1;
+ node->u.d_seq.stm2 = stm2;
+ return node;
}
-ASTNode *ast_if(ASTNode *bexp, ASTNode *s1, ASTNode *s2) {
- ASTNode *n = new_node(NT_IF);
- n->u.cond.bexp = bexp;
- n->u.cond.s1 = s1;
- n->u.cond.s2 = s2;
- return n;
+ASTNode *ast_if(ASTNode *bexp, ASTNode *stm1, ASTNode *stm2) {
+ ASTNode *node = new_node(NT_IF);
+ node->u.d_if.bexp = bexp;
+ node->u.d_if.stm1 = stm1;
+ node->u.d_if.stm2 = stm2;
+ return node;
}
-ASTNode *ast_while(ASTNode *bexp, ASTNode *s) {
- ASTNode *n = new_node(NT_WHILE);
- n->u.cond.bexp = bexp;
- n->u.cond.s1 = s;
- return n;
+ASTNode *ast_while(ASTNode *bexp, ASTNode *stm) {
+ ASTNode *node = new_node(NT_WHILE);
+ node->u.d_while.bexp = bexp;
+ node->u.d_while.stm = stm;
+ return node;
}
ASTNode *ast_int(int val) {
- ASTNode *n = new_node(NT_INT);
- n->u.val = val;
- return n;
+ ASTNode *node = new_node(NT_INT);
+ node->u.d_int.val = val;
+ return node;
}
-ASTNode *ast_var(char *var) {
- ASTNode *n = new_node(NT_VAR);
- n->u.var = strdup(var);
- return n;
+ASTNode *ast_var(char *name) {
+ ASTNode *node = new_node(NT_VAR);
+ node->u.d_var.name = strdup(name);
+ return node;
}
-ASTNode *ast_aop(AOp op, ASTNode *aexp1, ASTNode *aexp2) {
- ASTNode *n = new_node(NT_AOP);
- n->u.bin.exp1 = aexp1;
- n->u.bin.exp2 = aexp2;
- n->u.bin.op.aop = op;
- return n;
+ASTNode *ast_aop(AOp aop, ASTNode *aexp1, ASTNode *aexp2) {
+ ASTNode *node = new_node(NT_AOP);
+ node->u.d_aop.aexp1 = aexp1;
+ node->u.d_aop.aexp2 = aexp2;
+ node->u.d_aop.aop = aop;
+ return node;
}
-ASTNode *ast_bop(BOp op, ASTNode *bexp1, ASTNode *bexp2) {
- ASTNode *n = new_node(NT_BOP);
- n->u.bin.exp1 = bexp1;
- n->u.bin.exp2 = bexp2;
- n->u.bin.op.bop = op;
- return n;
+ASTNode *ast_bop(BOp bop, ASTNode *bexp1, ASTNode *bexp2) {
+ ASTNode *node = new_node(NT_BOP);
+ node->u.d_bop.bexp1 = bexp1;
+ node->u.d_bop.bexp2 = bexp2;
+ node->u.d_bop.bop = bop;
+ return node;
}
ASTNode *ast_not(ASTNode *bexp) {
- ASTNode *n = new_node(NT_NOT);
- n->u.bexp = bexp;
- return n;
+ ASTNode *node = new_node(NT_NOT);
+ node->u.d_not.bexp = bexp;
+ return node;
}
-ASTNode *ast_rop(ROp op, ASTNode *aexp1, ASTNode *aexp2) {
- ASTNode *n = new_node(NT_ROP);
- n->u.bin.exp1 = aexp1;
- n->u.bin.exp2 = aexp2;
- n->u.bin.op.rop = op;
- return n;
+ASTNode *ast_rop(ROp rop, ASTNode *aexp1, ASTNode *aexp2) {
+ ASTNode *node = new_node(NT_ROP);
+ node->u.d_rop.aexp1 = aexp1;
+ node->u.d_rop.aexp2 = aexp2;
+ node->u.d_rop.rop = rop;
+ return node;
}
-void free_ast(ASTNode *n) {
- if (!n) return;
- switch (n->type) {
+void free_ast(ASTNode *node) {
+ if (!node) return;
+ switch (node->type) {
case NT_SKIP:
break;
case NT_ASSIGN:
- free_ast(n->u.assign.var);
- free_ast(n->u.assign.aexp);
+ free_ast(node->u.d_assign.var);
+ free_ast(node->u.d_assign.aexp);
break;
case NT_SEQ:
- free_ast(n->u.seq.s1);
- free_ast(n->u.seq.s2);
+ free_ast(node->u.d_seq.stm1);
+ free_ast(node->u.d_seq.stm2);
break;
case NT_IF:
- free_ast(n->u.cond.bexp);
- free_ast(n->u.cond.s1);
- free_ast(n->u.cond.s2);
+ free_ast(node->u.d_if.bexp);
+ free_ast(node->u.d_if.stm1);
+ free_ast(node->u.d_if.stm2);
break;
case NT_WHILE:
- free_ast(n->u.cond.bexp);
- free_ast(n->u.cond.s1);
+ free_ast(node->u.d_while.bexp);
+ free_ast(node->u.d_while.stm);
break;
case NT_INT:
break;
case NT_VAR:
- free(n->u.var);
+ free(node->u.d_var.name);
break;
case NT_AOP:
+ free_ast(node->u.d_aop.aexp1);
+ free_ast(node->u.d_aop.aexp2);
+ break;
case NT_BOP:
+ free_ast(node->u.d_bop.bexp1);
+ free_ast(node->u.d_bop.bexp2);
+ break;
case NT_ROP:
- free_ast(n->u.bin.exp1);
- free_ast(n->u.bin.exp2);
+ free_ast(node->u.d_rop.aexp1);
+ free_ast(node->u.d_rop.aexp2);
break;
case NT_NOT:
- free_ast(n->u.bexp);
+ free_ast(node->u.d_not.bexp);
break;
}
- free(n);
+ free(node);
}
typedef struct Env {
- char *var;
+ char *name;
int val;
struct Env *next;
} Env;
static Env *env = NULL;
-static int env_lookup(const char *var) {
+static int env_lookup(const char *name) {
for (Env *e = env; e; e = e->next) {
- if (strcmp(e->var, var) == 0)
+ if (strcmp(e->name, name) == 0)
return e->val;
}
- fprintf(stderr, "Undefined variable %s\n", var);
+ fprintf(stderr, "Undefined variable %s\n", name);
exit(EXIT_FAILURE);
}
-static void env_update(const char *var, int val) {
+static void env_update(const char *name, int val) {
for (Env *e = env; e; e = e->next) {
- if (strcmp(e->var, var) == 0) {
+ if (strcmp(e->name, name) == 0) {
e->val = val;
return;
}
}
Env *e = malloc(sizeof(Env));
- e->var = strdup(var);
+ e->name = strdup(name);
e->val = val;
e->next = env;
env = e;
@@ -162,47 +164,47 @@ static void env_update(const char *var, int val) {
void env_print(void) {
Env *current_env = env;
while (current_env) {
- printf("%s = %d\n", current_env->var, current_env->val);
+ printf("%s = %d\n", current_env->name, current_env->val);
current_env = current_env->next;
}
}
-static int eval_aexpr(ASTNode *n) {
- switch (n->type) {
- case NT_INT: return n->u.val;
- case NT_VAR: return env_lookup(n->u.var);
+static int eval_aexpr(ASTNode *node) {
+ switch (node->type) {
+ case NT_INT: return node->u.d_int.val;
+ case NT_VAR: return env_lookup(node->u.d_var.name);
case NT_AOP: {
- int aexp1 = eval_aexpr(n->u.bin.exp1);
- int aexp2 = eval_aexpr(n->u.bin.exp2);
- switch (n->u.bin.op.aop) {
+ int aexp1 = eval_aexpr(node->u.d_aop.aexp1);
+ int aexp2 = eval_aexpr(node->u.d_aop.aexp2);
+ switch (node->u.d_aop.aop) {
case AOP_ADD: return aexp1 + aexp2;
case AOP_SUB: return aexp1 - aexp2;
case AOP_MUL: return aexp1 * aexp2;
}
}
default:
- fprintf(stderr, "Bad aexpr node %d\n", n->type);
+ fprintf(stderr, "Bad aexpr node %d\n", node->type);
exit(EXIT_FAILURE);
}
}
-static int eval_bexpr(ASTNode *n) {
- switch (n->type) {
+static int eval_bexpr(ASTNode *node) {
+ switch (node->type) {
case NT_BOP: {
- int bexp1 = eval_bexpr(n->u.bin.exp1);
- int bexp2 = eval_bexpr(n->u.bin.exp2);
- switch (n->u.bin.op.bop) {
+ int bexp1 = eval_bexpr(node->u.d_bop.bexp1);
+ int bexp2 = eval_bexpr(node->u.d_bop.bexp2);
+ switch (node->u.d_bop.bop) {
case BOP_AND: return bexp1 && bexp2;
case BOP_OR: return bexp1 || bexp2;
}
}
case NT_NOT:
- return !eval_bexpr(n->u.bexp);
+ return !eval_bexpr(node->u.d_not.bexp);
case NT_ROP: {
- int aexp1 = eval_aexpr(n->u.bin.exp1);
- int aexp2 = eval_aexpr(n->u.bin.exp2);
- switch (n->u.bin.op.rop) {
+ int aexp1 = eval_aexpr(node->u.d_rop.aexp1);
+ int aexp2 = eval_aexpr(node->u.d_rop.aexp2);
+ switch (node->u.d_rop.rop) {
case ROP_EQ: return aexp1 == aexp2;
case ROP_NE: return aexp1 != aexp2;
case ROP_LT: return aexp1 < aexp2;
@@ -212,39 +214,39 @@ static int eval_bexpr(ASTNode *n) {
}
}
default:
- fprintf(stderr, "Bad bexpr node %d\n", n->type);
+ fprintf(stderr, "Bad bexpr node %d\n", node->type);
exit(EXIT_FAILURE);
}
}
-void exec_stmt(ASTNode *n) {
- while (n) {
- switch (n->type) {
+void exec_stmt(ASTNode *node) {
+ while (node) {
+ switch (node->type) {
case NT_SKIP:
return;
case NT_ASSIGN: {
- char *var = n->u.assign.var->u.var;
- int val = eval_aexpr(n->u.assign.aexp);
+ char *var = node->u.d_assign.var->u.d_var.name;
+ int val = eval_aexpr(node->u.d_assign.aexp);
env_update(var, val);
return;
}
case NT_SEQ:
- exec_stmt(n->u.seq.s1);
- n = n->u.seq.s2;
- continue;
+ exec_stmt(node->u.d_seq.stm1);
+ exec_stmt(node->u.d_seq.stm2);
+ return;
case NT_IF:
- if (eval_bexpr(n->u.cond.bexp))
- exec_stmt(n->u.cond.s1);
+ if (eval_bexpr(node->u.d_if.bexp))
+ exec_stmt(node->u.d_if.stm1);
else
- exec_stmt(n->u.cond.s2);
+ exec_stmt(node->u.d_if.stm2);
return;
case NT_WHILE:
- while (eval_bexpr(n->u.cond.bexp)) {
- exec_stmt(n->u.cond.s1);
+ while (eval_bexpr(node->u.d_while.bexp)) {
+ exec_stmt(node->u.d_while.stm);
}
return;
default:
- fprintf(stderr, "Bad stmt node %d\n", n->type);
+ fprintf(stderr, "Bad stmt node %d\n", node->type);
exit(EXIT_FAILURE);
}
}
diff --git a/ast.h b/ast.h
index 67d6228..7a58372 100644
--- a/ast.h
+++ b/ast.h
@@ -13,30 +13,33 @@ typedef enum { ROP_EQ, ROP_NE, ROP_LT, ROP_LE, ROP_GT, ROP_GE } ROp;
typedef struct ASTNode {
NodeType type;
union {
- int val;
- char *var;
- struct { struct ASTNode *var, *aexp; } assign;
- struct { struct ASTNode *exp1, *exp2; union { AOp aop; BOp bop; ROp rop; } op;} bin;
- struct ASTNode *bexp;
- struct { struct ASTNode *bexp, *s1, *s2; } cond;
- struct { struct ASTNode *s1, *s2; } seq;
+ struct { struct ASTNode *var, *aexp; } d_assign;
+ struct { struct ASTNode *stm1, *stm2; } d_seq;
+ struct { struct ASTNode *bexp, *stm1, *stm2; } d_if;
+ struct { struct ASTNode *bexp, *stm; } d_while;
+ struct { int val; } d_int ;
+ struct { char *name; } d_var;
+ struct { AOp aop; struct ASTNode *aexp1, *aexp2; } d_aop;
+ struct { BOp bop; struct ASTNode *bexp1, *bexp2; } d_bop;
+ struct { struct ASTNode *bexp; } d_not;
+ struct { ROp rop; struct ASTNode *aexp1, *aexp2; } d_rop;
} u;
} ASTNode;
ASTNode *ast_skip(void);
ASTNode *ast_assign(ASTNode *var, ASTNode *aexp);
-ASTNode *ast_seq(ASTNode *s1, ASTNode *s2);
-ASTNode *ast_if(ASTNode *bexp, ASTNode *s1, ASTNode *s2);
-ASTNode *ast_while(ASTNode *bexp, ASTNode *s);
+ASTNode *ast_seq(ASTNode *stm1, ASTNode *stm2);
+ASTNode *ast_if(ASTNode *bexp, ASTNode *stm1, ASTNode *stm2);
+ASTNode *ast_while(ASTNode *bexp, ASTNode *stm);
ASTNode *ast_int(int val);
-ASTNode *ast_var(char *var);
-ASTNode *ast_aop(AOp, ASTNode *aexp1, ASTNode *aexp2);
-ASTNode *ast_bop(BOp, ASTNode *bexp1, ASTNode *bexp2);
+ASTNode *ast_var(char *name);
+ASTNode *ast_aop(AOp aop, ASTNode *aexp1, ASTNode *aexp2);
+ASTNode *ast_bop(BOp bop, ASTNode *bexp1, ASTNode *bexp2);
ASTNode *ast_not(ASTNode *bexp);
-ASTNode *ast_rop(ROp, ASTNode *aexp1, ASTNode *aexp2);
+ASTNode *ast_rop(ROp rop, ASTNode *aexp1, ASTNode *aexp2);
-void exec_stmt(ASTNode *n);
-void free_ast(ASTNode *n);
+void exec_stmt(ASTNode *node);
+void free_ast(ASTNode *node);
void env_print(void);
#endif
diff --git a/lexer.l b/lexer.l
index 4895b24..c9aaff0 100644
--- a/lexer.l
+++ b/lexer.l
@@ -6,7 +6,7 @@
DIGIT [0-9]
IDENT [A-Za-z][A-Za-z0-9]*
-WS [ \t\r\n]+
+WHITESPACE [ \t\r\n]+
%%
@@ -41,7 +41,7 @@ WS [ \t\r\n]+
{DIGIT}+ { yylval.num = atoi(yytext); return TOKEN_NUMERAL; }
{IDENT} { yylval.id = strdup(yytext); return TOKEN_IDENTIFIER; }
-{WS} { }
+{WHITESPACE} { }
. { fprintf(stderr, "Unknown char: %s\n", yytext); }
%%
diff --git a/parser.y b/parser.y
index 5974b96..9a94480 100644
--- a/parser.y
+++ b/parser.y
@@ -5,8 +5,12 @@
extern char *yytext;
extern int yylineno;
extern int yylex();
-void yyerror(const char *s) { fprintf(stderr, "Parse error at token \"%s\", line %d: %s\n", yytext, yylineno, s); }
+
ASTNode *ast_root;
+
+void yyerror(const char *s) {
+ fprintf(stderr, "Parse error at token \"%s\", line %d: %s\n", yytext, yylineno, s);
+}
%}