From ad2bc056ae684f8de57f2ff880e51440d07ee04a Mon Sep 17 00:00:00 2001
From: Julian T <julian@jtle.dk>
Date: Thu, 24 Oct 2019 07:51:51 +0200
Subject: Simple calculator assignment

---
 sem1/osc/mm11/opgaver.md    |  3 +++
 sem1/osc/mm11/regn/Makefile | 30 +++++++++++++++++++++++++
 sem1/osc/mm11/regn/regn.l   | 40 +++++++++++++++++++++++++++++++++
 sem1/osc/mm11/regn/regn.y   | 54 +++++++++++++++++++++++++++++++++++++++++++++
 sem1/osc/mm11/regn/symtab.c | 50 +++++++++++++++++++++++++++++++++++++++++
 sem1/osc/mm11/regn/symtab.h | 20 +++++++++++++++++
 6 files changed, 197 insertions(+)
 create mode 100644 sem1/osc/mm11/regn/Makefile
 create mode 100644 sem1/osc/mm11/regn/regn.l
 create mode 100644 sem1/osc/mm11/regn/regn.y
 create mode 100644 sem1/osc/mm11/regn/symtab.c
 create mode 100644 sem1/osc/mm11/regn/symtab.h

diff --git a/sem1/osc/mm11/opgaver.md b/sem1/osc/mm11/opgaver.md
index 09edad0..8fab5c4 100644
--- a/sem1/osc/mm11/opgaver.md
+++ b/sem1/osc/mm11/opgaver.md
@@ -23,3 +23,6 @@ Mange af dem er okay.
 Denne laver jeg måske senere.
 
 # Opgave 3
+
+Denne er løst i regn mappen. 
+Kør `make run` deri for at køre.
diff --git a/sem1/osc/mm11/regn/Makefile b/sem1/osc/mm11/regn/Makefile
new file mode 100644
index 0000000..442feba
--- /dev/null
+++ b/sem1/osc/mm11/regn/Makefile
@@ -0,0 +1,30 @@
+
+LEX=flex
+YACC=bison
+LIBS=-ly -lfl -lm
+CC=gcc
+
+PROG=regn
+TRASH=lex.yy.c $(PROG).tab.c $(PROG) $(PROG).tab.h $(PROG).output
+
+$(PROG): $(PROG).tab.o lex.yy.o symtab.o
+		$(CC) -o $@ $^ $(LIBS) 
+
+$(PROG).tab.c $(PROG).tab.h: $(PROG).y
+		$(YACC) -d -v $(PROG).y
+
+lex.yy.c: $(PROG).l
+		$(LEX) $(PROG).l
+
+%.o: %.c
+	$(CC) -c -o $@ $^
+
+PHONY: clean run
+
+run: $(PROG)
+	./$(PROG)
+
+clean:
+	rm -f *.o
+	rm -f $(TRASH)
+
diff --git a/sem1/osc/mm11/regn/regn.l b/sem1/osc/mm11/regn/regn.l
new file mode 100644
index 0000000..bbaadb8
--- /dev/null
+++ b/sem1/osc/mm11/regn/regn.l
@@ -0,0 +1,40 @@
+%{
+#include <math.h>
+#include <string.h>
+#include "symtab.h"
+#include "regn.tab.h"
+%}
+
+realtal      ([0-9]+|([0-9]*\.[0-9]+))([eE][-+]?[0-9]+)?
+var_begin	 let
+op_log		 log
+op_exp		 exp
+op_sqrt		 sqrt
+var			 [A-Za-z][A-Za-z0-9]*
+
+%%
+{realtal}      {yylval.dval = atof(yytext); 
+                return TAL;}
+{var_begin}	   {return VAR_BEGIN;}
+{op_log}	   {return LOG;}
+{op_exp}	   {return EXP;}
+{op_sqrt}	   {return SQRT;}
+
+{var}		   {yylval.string = strdup(yytext); return VAR;}
+
+[ \t] ;
+
+
+'$'            {return 0;} 
+
+\n|.           {return yytext[0];} 
+
+%%
+
+void init_sym()
+{
+	int  i;
+	for (i = 0; i < HASHSIZE; i++)
+		symbolarray[i] = NULL;
+}
+
diff --git a/sem1/osc/mm11/regn/regn.y b/sem1/osc/mm11/regn/regn.y
new file mode 100644
index 0000000..d0f67eb
--- /dev/null
+++ b/sem1/osc/mm11/regn/regn.y
@@ -0,0 +1,54 @@
+%{
+#include <stdio.h>
+#include <math.h>
+#include "symtab.h"
+#include <string.h>
+%}
+
+%union {
+	char           *string;
+	double          dval;
+}
+
+%token <string> VAR
+%token <dval> TAL
+%token LOG EXP SQRT VAR_BEGIN
+
+%left '-' '+'
+%right LOG EXP SQRT
+%left '*' '/'
+%right UMINUS
+
+%type <dval> expression
+
+%%
+
+statement_list: statement '\n'
+	  | statement_list statement '\n' ;
+
+statement:  expression					{printf("= %f\n",$1);}
+	  | VAR_BEGIN VAR '=' expression	{symnode_t *n = sym_lookup($2);
+										 if( !n ) {n = sym_insert($2); }
+										 n->value = $4;};
+
+expression: expression '+' expression   {$$ = $1 + $3;}
+	  | expression '-' expression   {$$ = $1 - $3;}
+	  | expression '*' expression   {$$ = $1 * $3;}
+	  | expression '/' expression   {if ($3 == 0.0) 
+                                           yyerror("divide dy zero");
+                                         else $$ = $1 / $3;}
+	  | '-' expression %prec UMINUS {$$ =  - $2;}
+	  | '(' expression ')'          {$$= $2;}
+	  | LOG expression				{$$ = log($2);}
+	  | EXP expression				{$$ = exp($2);}
+	  | SQRT expression				{$$ = sqrt($2);}
+          | TAL                         {$$ = $1;}
+	  | VAR							{symnode_t *n = sym_lookup($1);
+									 if( !n ) { yyerror("Var not found"); } else { $$ = n->value;} };
+%%
+
+int main()
+{ 
+  yyparse(); 
+}
+
diff --git a/sem1/osc/mm11/regn/symtab.c b/sem1/osc/mm11/regn/symtab.c
new file mode 100644
index 0000000..8103203
--- /dev/null
+++ b/sem1/osc/mm11/regn/symtab.c
@@ -0,0 +1,50 @@
+#include "symtab.h"
+#include <stdlib.h>
+#include <string.h>
+
+unsigned int hash(char *s) {
+	uint32_t hv = 0;
+	for( int i = 0; s[i] != '\0'; i++ ) {
+		// take MSB 6 bits of hv and xors with LSB of s[i]
+		uint32_t v = ( hv >> 26 ) ^ (s[i] & 0x3f);
+
+		// Push those back on hv
+		hv = (hv << 4) | v;
+	}
+	// Return appropriate size
+	return hv % HASHSIZE;
+}
+
+
+symnode_t *sym_insert(char *var) {
+	unsigned int index = hash(var);
+
+	// Save old value
+	symnode_t *oldSym = symbolarray[index];
+
+	// Make new
+	symbolarray[index] = malloc(sizeof(symnode_t));
+	if( symbolarray[index] == NULL ) {
+		// If malloc failed
+		symbolarray[index] = oldSym;
+		return NULL;
+	}
+
+	// Link old one
+	symbolarray[index]->next = oldSym;
+	symbolarray[index]->name = var;
+
+	return symbolarray[index];
+}
+
+symnode_t *sym_lookup(char *var) {
+	unsigned int index = hash(var);
+	symnode_t *n = symbolarray[index];
+
+	// Look trough list
+	while(n != NULL && strcmp(n->name, var) != 0) {
+		n = n->next;
+	}
+
+	return n;
+}
diff --git a/sem1/osc/mm11/regn/symtab.h b/sem1/osc/mm11/regn/symtab.h
new file mode 100644
index 0000000..c61f3a8
--- /dev/null
+++ b/sem1/osc/mm11/regn/symtab.h
@@ -0,0 +1,20 @@
+#include <stdint.h>
+#define HASHSIZE 100
+
+typedef struct symnode_struct {
+	char *name;
+	struct symnode_struct *next;
+	double value;
+} symnode_t;
+
+symnode_t *sym_insert(char *var);
+symnode_t *sym_lookup(char *var);
+
+struct symnode {
+	struct symnode *next;
+	char *name;
+	int type;
+	double value;
+};
+
+symnode_t *symbolarray[HASHSIZE];
-- 
cgit v1.2.3