add interpreter
This commit is contained in:
parent
a1c0f7a19f
commit
e3ea8ee709
7 changed files with 310 additions and 3 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -1,6 +1,9 @@
|
|||
/as.tab.c
|
||||
/as.tab.h
|
||||
/compilateur
|
||||
/lex.yy.c
|
||||
|
||||
/as.output
|
||||
/instruction_table.txt
|
||||
/test
|
||||
/interpreter/interpreter
|
||||
*.tab.c
|
||||
*.tab.h
|
||||
*.yy.c
|
||||
|
|
8
interpreter/input.txt
Normal file
8
interpreter/input.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
AFC 0 1
|
||||
AFC 10 20
|
||||
ADD 0 0 10
|
||||
AFC 1 8888
|
||||
SUP 2 0 1
|
||||
JMF 2 7
|
||||
PRI 1
|
||||
PRI 0
|
14
interpreter/makefile
Executable file
14
interpreter/makefile
Executable file
|
@ -0,0 +1,14 @@
|
|||
SRCC:= ./src/*.c
|
||||
|
||||
all: interpreter
|
||||
|
||||
interpreter: ./src/interpreter.y ./src/interpreter.l ./src/instructions.c
|
||||
yacc -d ./src/interpreter.y
|
||||
lex ./src/interpreter.l
|
||||
gcc lex.yy.c y.tab.c ./src/instructions.c -Isrc -o interpreter
|
||||
|
||||
run: interpreter
|
||||
./interpreter < input.txt
|
||||
|
||||
clean:
|
||||
rm -f lex.yy.c interpreter y.tab.h y.tab.c *.o
|
145
interpreter/src/instructions.c
Executable file
145
interpreter/src/instructions.c
Executable file
|
@ -0,0 +1,145 @@
|
|||
#include <stdio.h>
|
||||
#include "instructions.h"
|
||||
|
||||
struct instruction {
|
||||
char ins;
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
};
|
||||
|
||||
struct instruction instructions[MAX_INSTRUCTIONS_SIZE];
|
||||
int current_line;
|
||||
int has_error;
|
||||
|
||||
int memory[MAX_MEMORY_SIZE];
|
||||
|
||||
int exec(int ip);
|
||||
int valid_memory_addr(int address);
|
||||
|
||||
/***** Public funciton *****/
|
||||
|
||||
void asm_init() {
|
||||
current_line = 0;
|
||||
has_error = 0;
|
||||
}
|
||||
|
||||
void asm_add_3(char ins, int arg1, int arg2, int arg3) {
|
||||
if (current_line >= MAX_INSTRUCTIONS_SIZE) {
|
||||
fprintf(stderr, "ERROR readfile : Too much instructions, please modify value of MAX_INSTRUCTIONS_SIZE.\n");
|
||||
has_error = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// ip are validated at runtime; memory addr are validated here
|
||||
if (ins == AFC || ins == JMF) {
|
||||
if (!valid_memory_addr(arg1)) {
|
||||
fprintf(stderr, "ERROR readfile : INVALID addr at line %d, please verify that addr is in range 0 to MAX_MEMORY_SIZE\n", current_line);
|
||||
has_error = 1;
|
||||
return;
|
||||
}
|
||||
} else if (ins == JMP) {
|
||||
// do nothing
|
||||
} else {
|
||||
if (!(valid_memory_addr(arg1) && valid_memory_addr(arg2)
|
||||
&& valid_memory_addr(arg3))) {
|
||||
fprintf(stderr, "ERROR readfile : INVALID addr at line %d, please verify that addr is in range 0 to MAX_MEMORY_SIZE\n", current_line);
|
||||
has_error = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// When OK
|
||||
instructions[current_line].ins = ins;
|
||||
instructions[current_line].arg1 = arg1;
|
||||
instructions[current_line].arg2 = arg2;
|
||||
instructions[current_line].arg3 = arg3;
|
||||
current_line++;
|
||||
}
|
||||
|
||||
void asm_add_2(char ins, int arg1, int arg2) {
|
||||
asm_add_3(ins, arg1, arg2, 0);
|
||||
}
|
||||
|
||||
void asm_add_1(char ins, int arg1) {
|
||||
asm_add_3(ins, arg1, 0, 0);
|
||||
}
|
||||
|
||||
void asm_run() {
|
||||
int ip = 0;
|
||||
if (has_error) {
|
||||
fprintf(stderr, "ERROR run : abandoned due to previous error.\n");
|
||||
return;
|
||||
}
|
||||
printf("INFO run : begin\n");
|
||||
while (ip >= 0 && ip < current_line) {
|
||||
// wait for user input
|
||||
//getchar();
|
||||
// execution
|
||||
ip = exec(ip);
|
||||
}
|
||||
printf("INFO run : end\n");
|
||||
}
|
||||
|
||||
/***** Private funciton *****/
|
||||
|
||||
int valid_memory_addr(int addr) {
|
||||
return addr >= 0 && addr < MAX_MEMORY_SIZE;
|
||||
}
|
||||
|
||||
int exec(int ip) {
|
||||
int next_ip = ip + 1;
|
||||
char ins = instructions[ip].ins;
|
||||
int arg1 = instructions[ip].arg1;
|
||||
int arg2 = instructions[ip].arg2;
|
||||
int arg3 = instructions[ip].arg3;
|
||||
printf("%d : ", ip);
|
||||
|
||||
// execute inst
|
||||
switch (ins) {
|
||||
case ADD:
|
||||
printf("ADD @%d = @%d[%d] + @%d[%d]\n", arg1, arg2, memory[arg2], arg3, memory[arg3]);
|
||||
memory[arg1] = memory[arg2] + memory[arg3]; break;
|
||||
case MUL:
|
||||
printf("MUL @%d = @%d[%d] * @%d[%d]\n", arg1, arg2, memory[arg2], arg3, memory[arg3]);
|
||||
memory[arg1] = memory[arg2] * memory[arg3]; break;
|
||||
case SOU:
|
||||
printf("SOU @%d = @%d[%d] - @%d[%d]\n", arg1, arg2, memory[arg2], arg3, memory[arg3]);
|
||||
memory[arg1] = memory[arg2] - memory[arg3]; break;
|
||||
case DIV:
|
||||
printf("DIV @%d = @%d[%d] / @%d[%d]\n", arg1, arg2, memory[arg2], arg3, memory[arg3]);
|
||||
memory[arg1] = memory[arg2] / memory[arg3]; break;
|
||||
case COP:
|
||||
printf("COP @%d = @%d[%d]\n", arg1, arg2, memory[arg2]);
|
||||
memory[arg1] = memory[arg2]; break;
|
||||
case AFC:
|
||||
printf("AFC @%d = %d\n", arg1, arg2);
|
||||
memory[arg1] = arg2; break;
|
||||
case JMP:
|
||||
printf("JMP to %d\n", arg1);
|
||||
next_ip = arg1; break;
|
||||
case JMF:
|
||||
printf("JMF cond@%d[%d] to %d\n", arg1, memory[arg1], arg2);
|
||||
if (memory[arg1] == 0) next_ip = arg2;
|
||||
break;
|
||||
case INF:
|
||||
printf("INF @%d = @%d[%d] < @%d[%d] ? 1 : 0\n", arg1, arg2, memory[arg2], arg3, memory[arg3]);
|
||||
memory[arg1] = memory[arg2] < memory[arg3] ? 1 : 0;
|
||||
break;
|
||||
case SUP:
|
||||
printf("SUP @%d = @%d[%d] > @%d[%d] ? 1 : 0\n", arg1, arg2, memory[arg2], arg3, memory[arg3]);
|
||||
memory[arg1] = memory[arg2] > memory[arg3] ? 1 : 0;
|
||||
break;
|
||||
case EQU:
|
||||
printf("EQU @%d = @%d[%d] == @%d[%d] ? 1 : 0\n", arg1, arg2, memory[arg2], arg3, memory[arg3]);
|
||||
memory[arg1] = memory[arg2] == memory[arg3] ? 1 : 0;
|
||||
break;
|
||||
case PRI:
|
||||
printf("PRI @%d[%d]\n", arg1, memory[arg1]);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "ERROR run : unknown inst.\n");
|
||||
}
|
||||
|
||||
return next_ip;
|
||||
}
|
26
interpreter/src/instructions.h
Normal file
26
interpreter/src/instructions.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef __INSTRUCTIONS_H__
|
||||
#define __INSTRUCTIONS_H__
|
||||
|
||||
#define ADD 1
|
||||
#define MUL 2
|
||||
#define SOU 3
|
||||
#define DIV 4
|
||||
#define COP 5
|
||||
#define AFC 6
|
||||
#define JMP 7
|
||||
#define JMF 8
|
||||
#define INF 9
|
||||
#define SUP 10
|
||||
#define EQU 11
|
||||
#define PRI 12
|
||||
|
||||
#define MAX_INSTRUCTIONS_SIZE 256
|
||||
#define MAX_MEMORY_SIZE 256
|
||||
|
||||
void asm_init();
|
||||
void asm_add_3(char ins, int arg1, int arg2, int arg3);
|
||||
void asm_add_2(char ins, int arg1, int arg2);
|
||||
void asm_add_1(char ins, int arg1);
|
||||
void asm_run();
|
||||
|
||||
#endif // #ifndef __INSTRUCTIONS_H__
|
38
interpreter/src/interpreter.l
Executable file
38
interpreter/src/interpreter.l
Executable file
|
@ -0,0 +1,38 @@
|
|||
%{
|
||||
#include "y.tab.h"
|
||||
%}
|
||||
|
||||
vSEP [ \t\r\n]
|
||||
|
||||
%%
|
||||
|
||||
ADD {return tADD;}
|
||||
MUL {return tMUL;}
|
||||
SOU {return tSOU;}
|
||||
DIV {return tDIV;}
|
||||
COP {return tCOP;}
|
||||
AFC {return tAFC;}
|
||||
JMP {return tJMP;}
|
||||
JMF {return tJMF;}
|
||||
INF {return tINF;}
|
||||
SUP {return tSUP;}
|
||||
EQU {return tEQU;}
|
||||
PRI {return tPRI;}
|
||||
|
||||
-?[0-9]+ {
|
||||
yylval.nb = atoi(yytext);
|
||||
return tNB;
|
||||
}
|
||||
|
||||
|
||||
{vSEP} {}
|
||||
|
||||
. {
|
||||
fprintf(stderr, "ERROR lex : Unknown pattern %s", yytext);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
int yywrap(void) { return 1; }
|
||||
//int main(int argc, char *argv[]) { while (yylex()!=0) ; return 0; }
|
73
interpreter/src/interpreter.y
Executable file
73
interpreter/src/interpreter.y
Executable file
|
@ -0,0 +1,73 @@
|
|||
%{
|
||||
#include <stdio.h>
|
||||
#include "instructions.h"
|
||||
int yylex();
|
||||
void yyerror(char*);
|
||||
int yydebug = 1;
|
||||
extern int yylineno;
|
||||
%}
|
||||
|
||||
/* Union for yylval */
|
||||
%union {
|
||||
int nb;
|
||||
}
|
||||
|
||||
%token tADD tMUL tSOU tDIV tCOP tAFC tJMP tJMF tINF tSUP tEQU tPRI
|
||||
|
||||
%token <nb> tNB
|
||||
|
||||
%%
|
||||
|
||||
%start File;
|
||||
|
||||
File:
|
||||
Instructions;
|
||||
|
||||
Instructions:
|
||||
/* epsilon */
|
||||
| Instructions Instruction
|
||||
;
|
||||
|
||||
Instruction:
|
||||
tADD tNB tNB tNB
|
||||
{asm_add_3(ADD, $2, $3, $4);}
|
||||
| tMUL tNB tNB tNB
|
||||
{asm_add_3(MUL, $2, $3, $4);}
|
||||
| tSOU tNB tNB tNB
|
||||
{asm_add_3(SOU, $2, $3, $4);}
|
||||
| tDIV tNB tNB tNB
|
||||
{asm_add_3(DIV, $2, $3, $4);}
|
||||
| tCOP tNB tNB
|
||||
{asm_add_2(COP, $2, $3);}
|
||||
| tAFC tNB tNB
|
||||
{asm_add_2(AFC, $2, $3);}
|
||||
| tJMP tNB
|
||||
{asm_add_1(JMP, $2);}
|
||||
| tJMF tNB tNB
|
||||
{asm_add_2(JMF, $2, $3);}
|
||||
| tINF tNB tNB tNB
|
||||
{asm_add_3(INF, $2, $3, $4);}
|
||||
| tSUP tNB tNB tNB
|
||||
{asm_add_3(SUP, $2, $3, $4);}
|
||||
| tEQU tNB tNB tNB
|
||||
{asm_add_3(EQU, $2, $3, $4);}
|
||||
| tPRI tNB
|
||||
{asm_add_1(PRI, $2);}
|
||||
;
|
||||
|
||||
|
||||
%%
|
||||
|
||||
void yyerror(char* str) {
|
||||
extern int yylineno;
|
||||
fprintf(stderr, "ERROR yyparse : Line %d: %s\n", yylineno, str);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
asm_init();
|
||||
yyparse();
|
||||
printf("INFO yyparse : Parsing End\n");
|
||||
asm_run();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in a new issue