From 4ba1dbb9d4b4cad691c448e06a4ecc7b0066fe7f Mon Sep 17 00:00:00 2001 From: Sam Hadow Date: Mon, 25 Mar 2024 13:37:10 +0100 Subject: [PATCH] flex + bison --- src/ram.l | 22 ++++++++++++++ src/ram.py | 44 ++++++++++++++-------------- src/ram.y | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 22 deletions(-) create mode 100644 src/ram.l create mode 100644 src/ram.y diff --git a/src/ram.l b/src/ram.l new file mode 100644 index 0000000..163c15e --- /dev/null +++ b/src/ram.l @@ -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();} +%% diff --git a/src/ram.py b/src/ram.py index d0aceaa..973a987 100644 --- a/src/ram.py +++ b/src/ram.py @@ -11,20 +11,19 @@ class Ram(object): ''' Read from a register ''' - self.current += 1 - if type_register == "input": + if type_register == "i": # input return self.input_registers[index] - elif type_register == "work": + elif type_register == "r": # work value = self.work_registers[index] if value is None: raise ValueError("register empty") else: return self.work_registers[index] - elif type_register == "output": + elif type_register == "o": # output raise TypeError("output registers are write only") elif type_register == "value": return index - elif type_register == "reference": + elif type_register == "@": # reference target_index = self.read_register(ref_origin, index) return self.read_register(ref_target, target_index) @@ -32,63 +31,63 @@ class Ram(object): ''' Write to a register ''' - self.current += 1 - if type_register == "input": - raise TypeError("output registers are read only") - elif type_register == "work": + if type_register == "i": # input + raise TypeError("input registers are read only") + elif type_register == "r": # work if len(self.work_registers) <= index: self.work_registers.extend([None] * (index + 1 - len(self.work_registers))) # extend with uninitialized values self.work_registers[index] = value - elif type_register == "output": + elif type_register == "o": #output if len(self.output_registers) <= index: self.output_registers.extend([None] * (index + 1 - len(self.output_registers))) # extend with uninitialized values self.output_registers[index] = value elif type_register == "value": raise TypeError("cannot write on value") - elif type_register == "reference": + elif type_register == "@": # reference target_index = self.read_register(ref_origin, index) self.write_register(ref_target, target_index, value) 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_2 = self.read_register(*r2) value_3 = value_1 + value_2 self.write_register(value_3, *r3) - elif type_op == 'sub': + elif type_op == 'SUB': value_1 = self.read_register(*r1) value_2 = self.read_register(*r2) value_3 = value_1 - value_2 self.write_register(value_3, *r3) - elif type_op == 'div': + elif type_op == 'DIV': value_1 = self.read_register(*r1) value_2 = self.read_register(*r2) value_3 = value_1 / value_2 self.write_register(value_3, *r3) - elif type_op == 'mul': + elif type_op == 'MULT': value_1 = self.read_register(*r1) value_2 = self.read_register(*r2) value_3 = value_1 * value_2 self.write_register(value_3, *r3) def op_ctrl(self, type_op, z, r1=None, r2=None): - if type_op == 'jump': + if type_op == 'JUMP': if isinstance(z, int): self.current += z else: raise ValueError("wrong operand type (should be integer)") - if type_op == 'je': + if type_op == 'JE': value_1 = self.read_register(*r1) value_2 = self.read_register(*r2) if value_1 == value_2: - self.op_ctrl('jump', z) + self.op_ctrl('JUMP', z) else: self.current += 1 - if type_op == 'jl': + if type_op == 'JL': value_1 = self.read_register(*r1) value_2 = self.read_register(*r2) if value_1 > value_2: - self.op_ctrl('jump', z) + self.op_ctrl('JUMP', z) else: self.current += 1 @@ -101,10 +100,11 @@ class Ram(object): ### example -input_registers = [10, 5] +input_registers = [10, 5, 1] 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) diff --git a/src/ram.y b/src/ram.y new file mode 100644 index 0000000..102bb1d --- /dev/null +++ b/src/ram.y @@ -0,0 +1,85 @@ +%{ +#include +#include +#include +#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; +}