flex + bison
This commit is contained in:
parent
2a3907eef7
commit
4ba1dbb9d4
22
src/ram.l
Normal file
22
src/ram.l
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
%{
|
||||||
|
#ifndef YYSTYPE
|
||||||
|
#define YYSTYPE char *
|
||||||
|
#endif
|
||||||
|
#include "ram.tab.h"
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
|
||||||
|
%%
|
||||||
|
[rio][0-9]* { yylval = yytext; return REGISTER;}
|
||||||
|
[rio]@[rio][0-9]* { yylval = yytext; return REGISTER_REF}
|
||||||
|
[0-9]* { yylval = yytext; return VALUE;}
|
||||||
|
ADD|SUB|MULT|DIV { yylval = yytext; return OP;}
|
||||||
|
JUMP|JE|JL { yylval = yytext; return OP_CTRL;}
|
||||||
|
, {return COMMA}
|
||||||
|
\( {return PAR_O;}
|
||||||
|
\) {return PAR_C;}
|
||||||
|
\n {return SEPARATION; }
|
||||||
|
. {printf("token inconnu\n"); yyterminate();}
|
||||||
|
%%
|
44
src/ram.py
44
src/ram.py
@ -11,20 +11,19 @@ class Ram(object):
|
|||||||
'''
|
'''
|
||||||
Read from a register
|
Read from a register
|
||||||
'''
|
'''
|
||||||
self.current += 1
|
if type_register == "i": # input
|
||||||
if type_register == "input":
|
|
||||||
return self.input_registers[index]
|
return self.input_registers[index]
|
||||||
elif type_register == "work":
|
elif type_register == "r": # work
|
||||||
value = self.work_registers[index]
|
value = self.work_registers[index]
|
||||||
if value is None:
|
if value is None:
|
||||||
raise ValueError("register empty")
|
raise ValueError("register empty")
|
||||||
else:
|
else:
|
||||||
return self.work_registers[index]
|
return self.work_registers[index]
|
||||||
elif type_register == "output":
|
elif type_register == "o": # output
|
||||||
raise TypeError("output registers are write only")
|
raise TypeError("output registers are write only")
|
||||||
elif type_register == "value":
|
elif type_register == "value":
|
||||||
return index
|
return index
|
||||||
elif type_register == "reference":
|
elif type_register == "@": # reference
|
||||||
target_index = self.read_register(ref_origin, index)
|
target_index = self.read_register(ref_origin, index)
|
||||||
return self.read_register(ref_target, target_index)
|
return self.read_register(ref_target, target_index)
|
||||||
|
|
||||||
@ -32,63 +31,63 @@ class Ram(object):
|
|||||||
'''
|
'''
|
||||||
Write to a register
|
Write to a register
|
||||||
'''
|
'''
|
||||||
self.current += 1
|
if type_register == "i": # input
|
||||||
if type_register == "input":
|
raise TypeError("input registers are read only")
|
||||||
raise TypeError("output registers are read only")
|
elif type_register == "r": # work
|
||||||
elif type_register == "work":
|
|
||||||
if len(self.work_registers) <= index:
|
if len(self.work_registers) <= index:
|
||||||
self.work_registers.extend([None] * (index + 1 - len(self.work_registers))) # extend with uninitialized values
|
self.work_registers.extend([None] * (index + 1 - len(self.work_registers))) # extend with uninitialized values
|
||||||
self.work_registers[index] = value
|
self.work_registers[index] = value
|
||||||
elif type_register == "output":
|
elif type_register == "o": #output
|
||||||
if len(self.output_registers) <= index:
|
if len(self.output_registers) <= index:
|
||||||
self.output_registers.extend([None] * (index + 1 - len(self.output_registers))) # extend with uninitialized values
|
self.output_registers.extend([None] * (index + 1 - len(self.output_registers))) # extend with uninitialized values
|
||||||
self.output_registers[index] = value
|
self.output_registers[index] = value
|
||||||
elif type_register == "value":
|
elif type_register == "value":
|
||||||
raise TypeError("cannot write on value")
|
raise TypeError("cannot write on value")
|
||||||
elif type_register == "reference":
|
elif type_register == "@": # reference
|
||||||
target_index = self.read_register(ref_origin, index)
|
target_index = self.read_register(ref_origin, index)
|
||||||
self.write_register(ref_target, target_index, value)
|
self.write_register(ref_target, target_index, value)
|
||||||
|
|
||||||
def op(self, type_op, r1, r2, r3):
|
def op(self, type_op, r1, r2, r3):
|
||||||
if type_op == 'add':
|
self.current += 1
|
||||||
|
if type_op == 'ADD':
|
||||||
value_1 = self.read_register(*r1)
|
value_1 = self.read_register(*r1)
|
||||||
value_2 = self.read_register(*r2)
|
value_2 = self.read_register(*r2)
|
||||||
value_3 = value_1 + value_2
|
value_3 = value_1 + value_2
|
||||||
self.write_register(value_3, *r3)
|
self.write_register(value_3, *r3)
|
||||||
elif type_op == 'sub':
|
elif type_op == 'SUB':
|
||||||
value_1 = self.read_register(*r1)
|
value_1 = self.read_register(*r1)
|
||||||
value_2 = self.read_register(*r2)
|
value_2 = self.read_register(*r2)
|
||||||
value_3 = value_1 - value_2
|
value_3 = value_1 - value_2
|
||||||
self.write_register(value_3, *r3)
|
self.write_register(value_3, *r3)
|
||||||
elif type_op == 'div':
|
elif type_op == 'DIV':
|
||||||
value_1 = self.read_register(*r1)
|
value_1 = self.read_register(*r1)
|
||||||
value_2 = self.read_register(*r2)
|
value_2 = self.read_register(*r2)
|
||||||
value_3 = value_1 / value_2
|
value_3 = value_1 / value_2
|
||||||
self.write_register(value_3, *r3)
|
self.write_register(value_3, *r3)
|
||||||
elif type_op == 'mul':
|
elif type_op == 'MULT':
|
||||||
value_1 = self.read_register(*r1)
|
value_1 = self.read_register(*r1)
|
||||||
value_2 = self.read_register(*r2)
|
value_2 = self.read_register(*r2)
|
||||||
value_3 = value_1 * value_2
|
value_3 = value_1 * value_2
|
||||||
self.write_register(value_3, *r3)
|
self.write_register(value_3, *r3)
|
||||||
|
|
||||||
def op_ctrl(self, type_op, z, r1=None, r2=None):
|
def op_ctrl(self, type_op, z, r1=None, r2=None):
|
||||||
if type_op == 'jump':
|
if type_op == 'JUMP':
|
||||||
if isinstance(z, int):
|
if isinstance(z, int):
|
||||||
self.current += z
|
self.current += z
|
||||||
else:
|
else:
|
||||||
raise ValueError("wrong operand type (should be integer)")
|
raise ValueError("wrong operand type (should be integer)")
|
||||||
if type_op == 'je':
|
if type_op == 'JE':
|
||||||
value_1 = self.read_register(*r1)
|
value_1 = self.read_register(*r1)
|
||||||
value_2 = self.read_register(*r2)
|
value_2 = self.read_register(*r2)
|
||||||
if value_1 == value_2:
|
if value_1 == value_2:
|
||||||
self.op_ctrl('jump', z)
|
self.op_ctrl('JUMP', z)
|
||||||
else:
|
else:
|
||||||
self.current += 1
|
self.current += 1
|
||||||
if type_op == 'jl':
|
if type_op == 'JL':
|
||||||
value_1 = self.read_register(*r1)
|
value_1 = self.read_register(*r1)
|
||||||
value_2 = self.read_register(*r2)
|
value_2 = self.read_register(*r2)
|
||||||
if value_1 > value_2:
|
if value_1 > value_2:
|
||||||
self.op_ctrl('jump', z)
|
self.op_ctrl('JUMP', z)
|
||||||
else:
|
else:
|
||||||
self.current += 1
|
self.current += 1
|
||||||
|
|
||||||
@ -101,10 +100,11 @@ class Ram(object):
|
|||||||
|
|
||||||
|
|
||||||
### example
|
### example
|
||||||
input_registers = [10, 5]
|
input_registers = [10, 5, 1]
|
||||||
|
|
||||||
instructions = [
|
instructions = [
|
||||||
{'op': Ram.op, 'args': ('add', ('input', 0), ('value', 1), ('output', 2))},
|
{'op': Ram.op, 'args': ('ADD', ('i', 0), ('value', 1), ('o', 2))},
|
||||||
|
{'op': Ram.op, 'args': ('ADD', ('value', 0), ('@', 2, 'i', 'i'), ('o', 1))},
|
||||||
]
|
]
|
||||||
|
|
||||||
ram = Ram(instructions, input_registers)
|
ram = Ram(instructions, input_registers)
|
||||||
|
85
src/ram.y
Normal file
85
src/ram.y
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifndef YYSTYPE
|
||||||
|
#define YYSTYPE char *
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char* result = "";
|
||||||
|
|
||||||
|
int yylex(void);
|
||||||
|
int yyerror(char* s);
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%token REGISTER REGISTER_REF OP OP_CTRL VALUE
|
||||||
|
%token PAR_O PAR_F
|
||||||
|
%left COMMA
|
||||||
|
%right SEPARATION
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
instruction:
|
||||||
|
line SEPARATION instruction {
|
||||||
|
asprintf(&$$, "%s\n%s", $1, $3);
|
||||||
|
}
|
||||||
|
| line SEPARATION {
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
| line {
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
line:
|
||||||
|
OP_CTRL PAR_O args_ctrl PAR_F {
|
||||||
|
asprintf(&$$, "{\"op\": Ram.op, \"args\": (%s, %s)}, ", $1, $2);
|
||||||
|
}
|
||||||
|
| OP PAR_O args PAR_F {
|
||||||
|
asprintf(&$$, "{\"op\": Ram.op_ctrl, \"args\": (%s, %s)}, ", $1, $2);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
args:
|
||||||
|
arg COMMA arg COMMA arg {
|
||||||
|
asprintf(&$$, "%s, %s, %s", $1, $3, $5);
|
||||||
|
}
|
||||||
|
| arg {
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
args_ctrl:
|
||||||
|
VALUE COMMA arg COMMA arg {
|
||||||
|
asprintf(&$$, "%c, %s, %s", $1, $3, $5);
|
||||||
|
}
|
||||||
|
| VALUE {
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg:
|
||||||
|
REGISTER_REF {
|
||||||
|
char *index_str = strdup($1 + 3); // copy from 4th char
|
||||||
|
asprintf(&$$, "('%c', '%c', '%c', %s), ", $1[1], index_str, $1[2], $1[0]);
|
||||||
|
// r@i1 -> r register, index in i1
|
||||||
|
// Python args: type_register, index, ref_origin, ref_target
|
||||||
|
// r@i1 -> ('@', '1', 'i', 'r')
|
||||||
|
free(index_str);
|
||||||
|
}
|
||||||
|
| REGISTER {
|
||||||
|
char *index_str = strdup($1 + 1); // copy from 2nd char
|
||||||
|
asprintf(&$$, "('%c', %s), ", $1[0], index_str);
|
||||||
|
free(index_str);
|
||||||
|
}
|
||||||
|
| VALUE {
|
||||||
|
asprintf(&$$, "('value', %s), ", $1);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
yyparse();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user