summaryrefslogtreecommitdiff
path: root/graphs/piscine/evalexpr
diff options
context:
space:
mode:
Diffstat (limited to 'graphs/piscine/evalexpr')
-rw-r--r--graphs/piscine/evalexpr/Makefile23
-rw-r--r--graphs/piscine/evalexpr/src/evalexpr.c93
-rw-r--r--graphs/piscine/evalexpr/src/evalexpr.h43
-rw-r--r--graphs/piscine/evalexpr/src/evalrpn.c145
-rw-r--r--graphs/piscine/evalexpr/src/fifo.h29
-rw-r--r--graphs/piscine/evalexpr/src/fifo_access.c61
-rw-r--r--graphs/piscine/evalexpr/src/fifo_setup_destroy.c44
-rw-r--r--graphs/piscine/evalexpr/src/shunting_yard.c199
-rw-r--r--graphs/piscine/evalexpr/src/stack.c57
-rw-r--r--graphs/piscine/evalexpr/src/stack.h20
-rw-r--r--graphs/piscine/evalexpr/src/stack_struct.h10
-rwxr-xr-xgraphs/piscine/evalexpr/tests/tests.sh82
-rw-r--r--graphs/piscine/evalexpr/tests/unit_tests.c208
13 files changed, 1014 insertions, 0 deletions
diff --git a/graphs/piscine/evalexpr/Makefile b/graphs/piscine/evalexpr/Makefile
new file mode 100644
index 0000000..280f19c
--- /dev/null
+++ b/graphs/piscine/evalexpr/Makefile
@@ -0,0 +1,23 @@
+CC = gcc
+CFLAGS = -Wall -Werror -Wextra -pedantic -std=c99 -Wvla
+AFLAGS = -fsanitize=address
+
+SRC=src/stack.c src/evalrpn.c src/shunting_yard.c src/fifo_access.c src/fifo_setup_destroy.c src/evalexpr.c
+SRC_TEST=tests/unit_tests.c
+#OBJ=src/stack.o src/evalrpn.o
+OBJ=$(SRC:.c=.o)
+#OBJ_TEST=$(SRC_TEST:.c=.o)
+
+all: $(OBJ)
+ $(CC) -o evalexpr $(OBJ)
+
+$(OBJ): $(SRC)
+
+check: #$(OBJ) $(OBJ_TEST)
+# $(CC) $(CFLAGS) -o evaltest $(OBJ) $(OBJ_TEST) -lcriterion
+ tests/tests.sh
+
+.PHONY: clean
+
+clean:
+ rm $(OBJ) evalexpr
diff --git a/graphs/piscine/evalexpr/src/evalexpr.c b/graphs/piscine/evalexpr/src/evalexpr.c
new file mode 100644
index 0000000..5012355
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/evalexpr.c
@@ -0,0 +1,93 @@
+#include "evalexpr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BUFFER_SIZE 10
+
+char *get_input(void)
+{
+ size_t r;
+ char buf[BUFFER_SIZE];
+ size_t size = 0;
+ char *expr = malloc(size * sizeof(char) + 1);
+ if (expr == NULL)
+ return NULL;
+ expr[0] = '\0';
+ do
+ {
+ r = fread(buf, sizeof(char), BUFFER_SIZE - 1, stdin);
+ if (r != 0)
+ {
+ buf[r] = '\0';
+ size += r;
+ char *tmp = realloc(expr, size * sizeof(char) + 1);
+ if (tmp == NULL)
+ {
+ free(expr);
+ return NULL;
+ }
+ expr = tmp;
+ strcat(expr, buf);
+ }
+ } while (r != 0);
+ if (size == 0)
+ {
+ free(expr);
+ return NULL;
+ }
+ if (expr[size - 1] == '\n')
+ expr[size - 1] = '\0';
+ return expr;
+}
+
+void cleanup(char *expr, char *rpn)
+{
+ free(expr);
+ free(rpn);
+}
+
+int main(int argc, char **argv)
+{
+ if ((argc == 2 && strcmp(argv[1], "-rpn") != 0) || (argc > 2))
+ return 4;
+ char *expr = get_input();
+ if (expr == NULL)
+ return 4;
+ if (argc == 1)
+ {
+ char *rpn;
+ int e = shunting_yard(expr, &rpn);
+ if (e != 0)
+ return e;
+ // call shunting yard
+ int retval;
+ e = evalrpn(rpn, &retval);
+ if (e != 0)
+ {
+ cleanup(expr, rpn);
+ return e;
+ }
+ // FREE RPN
+ printf("%d\n", retval);
+ cleanup(expr, rpn);
+ // return
+ return 0;
+ }
+
+ if (argc == 2 && strcmp(argv[1], "-rpn") == 0)
+ {
+ // call rpn eval
+ int retval;
+ int e = evalrpn(expr, &retval);
+ printf("%d\n", retval);
+ // return
+ free(expr);
+ if (e != 0)
+ return e;
+ return 0;
+ }
+
+ return 4;
+}
diff --git a/graphs/piscine/evalexpr/src/evalexpr.h b/graphs/piscine/evalexpr/src/evalexpr.h
new file mode 100644
index 0000000..d440ae1
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/evalexpr.h
@@ -0,0 +1,43 @@
+#ifndef EVALEXPR_H
+#define EVALEXPR_H
+
+#include <stddef.h>
+
+#include "fifo.h"
+#include "stack.h"
+#include "stack_struct.h"
+
+enum token_type
+{
+ NUMBER = 0,
+ SUB = 1,
+ ADD = 1,
+ MOD = 2,
+ DIV = 2,
+ MUL = 2,
+ EXP = 3,
+ UN_PLUS = 4,
+ UN_MINUS = 4,
+ PAR_LEFT = 5,
+ PAR_RIGHT = 5,
+ WRONG_TOKEN = -1,
+};
+
+struct token
+{
+ enum token_type type;
+ int value;
+};
+
+// evalrpn
+int parse_number(const char *expr, size_t *offset);
+int get_operands(struct stack **s, int *op1, int *op2);
+int my_pow(int a, int b);
+int evalrpn(const char *expr, int *retval);
+
+// shunting yard
+int opcmp(struct token *op1, struct token *op2);
+enum token_type get_type(char op);
+int shunting_yard(const char *expr, char **rpn);
+
+#endif /* ! EVALEXPR_H */
diff --git a/graphs/piscine/evalexpr/src/evalrpn.c b/graphs/piscine/evalexpr/src/evalrpn.c
new file mode 100644
index 0000000..db493eb
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/evalrpn.c
@@ -0,0 +1,145 @@
+#include <ctype.h>
+
+#include "evalexpr.h"
+
+int parse_number(const char *expr, size_t *offset)
+{
+ for (*offset = 0;
+ expr[*offset] && expr[*offset] >= '0' && expr[*offset] <= '9';
+ (*offset)++)
+ {
+ continue;
+ }
+ (*offset)--;
+
+ int res = 0;
+ int pow = 1;
+ for (size_t n = 0; n <= *offset; n++, pow *= 10)
+ {
+ res += (expr[*offset - n] - '0') * pow;
+ }
+
+ return res;
+}
+
+int get_operands(struct stack **s, int *op1, int *op2)
+{
+ if (*s == NULL)
+ {
+ return 2;
+ }
+ *op1 = stack_peek(*s);
+ *s = stack_pop(*s);
+ if (*s == NULL)
+ {
+ return 2;
+ }
+ *op2 = stack_peek(*s);
+ *s = stack_pop(*s);
+ return 0;
+}
+
+// Computes a to the bth
+int my_pow(int a, int b)
+{
+ if (b == 0)
+ {
+ return 1;
+ }
+ if (a == 0)
+ {
+ return 0;
+ }
+
+ int res = 1;
+ int c = b / 2;
+ while (c != 0)
+ {
+ res *= a * a;
+ c /= 2;
+ }
+ if (b % 2 != 0)
+ res *= a;
+ return res;
+}
+
+int dispatch(const char c, struct stack **s, int op1, int op2)
+{
+ switch (c)
+ {
+ case '*':
+ *s = stack_push(*s, op1 * op2);
+ break;
+ case '+':
+ *s = stack_push(*s, op1 + op2);
+ break;
+ case '-':
+ *s = stack_push(*s, op2 - op1);
+ break;
+ case '/':
+ if (op1 == 0)
+ {
+ return 3;
+ }
+ *s = stack_push(*s, op2 / op1);
+ break;
+ case '%':
+ if (op1 == 0)
+ {
+ return 3;
+ }
+ *s = stack_push(*s, op2 % op1);
+ break;
+ case '^':
+ if (op1 < 0)
+ {
+ return 3;
+ }
+ *s = stack_push(*s, my_pow(op2, op1));
+ break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+int evalrpn(const char *expr, int *retval)
+{
+ struct stack *s = NULL;
+
+ for (size_t i = 0; expr[i]; i++)
+ {
+ if (expr[i] >= '0' && expr[i] <= '9')
+ {
+ size_t offset;
+ int val = parse_number(expr + i, &offset);
+ s = stack_push(s, val);
+ i += offset;
+ }
+ else if (isspace(expr[i]))
+ continue;
+ else
+ {
+ int op1;
+ int op2;
+ if (get_operands(&s, &op1, &op2) == 2)
+ {
+ return 2;
+ }
+
+ int d = dispatch(expr[i], &s, op1, op2);
+ if (d != 0)
+ {
+ return d;
+ }
+ }
+ }
+
+ if (s == NULL)
+ {
+ return 0;
+ }
+ *retval = stack_peek(s);
+ s = stack_pop(s);
+ return (!s) ? 0 : 2;
+}
diff --git a/graphs/piscine/evalexpr/src/fifo.h b/graphs/piscine/evalexpr/src/fifo.h
new file mode 100644
index 0000000..b330eac
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/fifo.h
@@ -0,0 +1,29 @@
+#ifndef FIFO_H
+#define FIFO_H
+
+#include <stddef.h>
+
+#include "evalexpr.h"
+
+struct list
+{
+ struct token *data;
+ struct list *next;
+};
+
+struct fifo
+{
+ struct list *head;
+ struct list *tail;
+ size_t size;
+};
+
+struct fifo *fifo_init(void);
+size_t fifo_size(struct fifo *fifo);
+void fifo_push(struct fifo *fifo, struct token *elt);
+struct token *fifo_head(struct fifo *fifo);
+void fifo_pop(struct fifo *fifo);
+void fifo_clear(struct fifo *fifo);
+void fifo_destroy(struct fifo *fifo);
+
+#endif /* !FIFO_H */
diff --git a/graphs/piscine/evalexpr/src/fifo_access.c b/graphs/piscine/evalexpr/src/fifo_access.c
new file mode 100644
index 0000000..1986a09
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/fifo_access.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fifo.h"
+
+size_t fifo_size(struct fifo *fifo)
+{
+ return fifo->size;
+}
+
+void fifo_push(struct fifo *fifo, struct token *elt)
+{
+ struct list *new = malloc(sizeof(struct list));
+ if (new == NULL)
+ {
+ return;
+ }
+ new->data = elt;
+
+ if (fifo_size(fifo) == 0)
+ {
+ fifo->head = new;
+ }
+ new->next = NULL;
+ if (fifo_size(fifo) != 0)
+ {
+ fifo->tail->next = new;
+ }
+ fifo->tail = new;
+
+ fifo->size++;
+}
+
+struct token *fifo_head(struct fifo *fifo)
+{
+ return fifo->head->data;
+}
+
+void fifo_pop(struct fifo *fifo)
+{
+ if (fifo_size(fifo) == 0)
+ {
+ return;
+ }
+ if (fifo_size(fifo) == 1)
+ {
+ free(fifo->head->data);
+ free(fifo->head);
+ fifo->head = NULL;
+ fifo->tail = NULL;
+ fifo->size = 0;
+ return;
+ }
+
+ struct list *tmp = fifo->head->next;
+ free(fifo->head->data);
+ free(fifo->head);
+ fifo->head = tmp;
+
+ fifo->size--;
+}
diff --git a/graphs/piscine/evalexpr/src/fifo_setup_destroy.c b/graphs/piscine/evalexpr/src/fifo_setup_destroy.c
new file mode 100644
index 0000000..0f99ad0
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/fifo_setup_destroy.c
@@ -0,0 +1,44 @@
+#include <stdlib.h>
+
+#include "fifo.h"
+
+struct fifo *fifo_init(void)
+{
+ struct fifo *f = malloc(sizeof(struct fifo));
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ f->size = 0;
+ f->head = NULL;
+ f->tail = NULL;
+
+ return f;
+}
+
+void fifo_clear(struct fifo *fifo)
+{
+ for (struct list *l = fifo->head; l != fifo->tail;)
+ {
+ struct list *tmp = l->next;
+ free(l->data);
+ free(l);
+ l = tmp;
+ }
+ if (fifo->tail)
+ {
+ free(fifo->tail->data);
+ free(fifo->tail);
+ }
+
+ fifo->head = NULL;
+ fifo->tail = NULL;
+ fifo->size = 0;
+}
+
+void fifo_destroy(struct fifo *fifo)
+{
+ fifo_clear(fifo);
+ free(fifo);
+}
diff --git a/graphs/piscine/evalexpr/src/shunting_yard.c b/graphs/piscine/evalexpr/src/shunting_yard.c
new file mode 100644
index 0000000..2db5fc8
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/shunting_yard.c
@@ -0,0 +1,199 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "evalexpr.h"
+
+enum assoc
+{
+ NONE,
+ RIGHT,
+ LEFT,
+};
+
+int opcmp(struct token *op1, struct token *op2)
+{
+ return op1->type - op2->type;
+}
+
+enum assoc get_assoc(struct token *op)
+{
+ if (op->type == EXP)
+ {
+ return RIGHT;
+ }
+ return LEFT;
+}
+
+enum token_type get_type(char op)
+{
+ switch (op)
+ {
+ case '*':
+ return MUL;
+ case '/':
+ return DIV;
+ case '-':
+ return SUB;
+ case '+':
+ return ADD;
+ case '%':
+ return MOD;
+ case '^':
+ return EXP;
+ case '(':
+ return PAR_LEFT;
+ case ')':
+ return PAR_RIGHT;
+ default:
+ return WRONG_TOKEN;
+ }
+}
+
+char *fifo_to_expr(struct fifo *output, size_t size_offset)
+{
+ char *res = malloc((2 * fifo_size(output) + size_offset) * sizeof(char));
+ if (!res)
+ {
+ fifo_destroy(output);
+ return NULL;
+ }
+ res[2 * fifo_size(output) + size_offset - 1] = '\0';
+ size_t i = 0;
+ while (fifo_size(output) > 0)
+ {
+ if (fifo_head(output)->type == NUMBER)
+ {
+ i += sprintf(res + i, "%d", fifo_head(output)->value) - 1;
+ }
+ else
+ {
+ res[i] = fifo_head(output)->value;
+ }
+ fifo_pop(output);
+ i++;
+ if (fifo_size(output) != 0)
+ {
+ res[i] = ' ';
+ i++;
+ }
+ }
+ fifo_destroy(output);
+ return res;
+}
+
+int handle_rpar(struct tstack **opstack, struct fifo *output, struct token **t)
+{
+ while (*opstack)
+ {
+ struct token *o2 = tstack_peek(*opstack);
+ if (o2->value == '(')
+ {
+ free(o2);
+ break;
+ }
+ *opstack = tstack_pop(*opstack);
+ fifo_push(output, o2);
+ }
+ if (*opstack == NULL)
+ {
+ free(*t);
+ fifo_destroy(output);
+ return 2;
+ }
+ free(*t);
+ *opstack = tstack_pop(*opstack);
+ return 0;
+}
+
+int empty_opstack(struct tstack **opstack, struct fifo *output)
+{
+ while (*opstack)
+ {
+ struct token *t = tstack_peek(*opstack);
+ if (t->value == '(' || t->value == ')')
+ {
+ fifo_destroy(output);
+ return 1;
+ }
+ *opstack = tstack_pop(*opstack);
+ fifo_push(output, t);
+ }
+ return 0;
+}
+
+void pop_ops(struct tstack **opstack, struct fifo *output, struct token *t)
+{
+ while (*opstack)
+ {
+ struct token *o2 = tstack_peek(*opstack);
+ if (!(o2->value != '('
+ && (opcmp(t, o2) < 0
+ || (opcmp(t, o2) == 0 && get_assoc(t) == LEFT))))
+ {
+ break;
+ }
+
+ *opstack = tstack_pop(*opstack);
+ fifo_push(output, o2);
+ }
+}
+
+void handle_numbers(struct fifo *output, size_t *i, int *size_offset,
+ const char *expr)
+{
+ size_t offset;
+ int val = parse_number(expr + *i, &offset);
+ struct token *t = malloc(sizeof(struct token));
+ t->type = NUMBER;
+ t->value = val;
+ fifo_push(output, t);
+ *i += offset;
+ *size_offset += offset;
+}
+
+int shunting_yard(const char *expr, char **rpn)
+{
+ struct fifo *output = fifo_init();
+ struct tstack *opstack = NULL;
+ int size_offset = 0;
+ for (size_t i = 0; expr[i]; i++)
+ {
+ if (expr[i] >= '0' && expr[i] <= '9')
+ {
+ handle_numbers(output, &i, &size_offset, expr);
+ }
+ else if (expr[i] != ' ')
+ {
+ struct token *t = malloc(sizeof(struct token));
+ t->value = expr[i];
+ if ((t->type = get_type(expr[i])) == WRONG_TOKEN)
+ {
+ free(t);
+ return 1;
+ }
+ if (t->value == '(')
+ {
+ opstack = tstack_push(opstack, t);
+ continue;
+ }
+ else if (t->value == ')')
+ {
+ if (handle_rpar(&opstack, output, &t) != 0)
+ return 2;
+ continue;
+ }
+ pop_ops(&opstack, output, t);
+ opstack = tstack_push(opstack, t);
+ }
+ }
+
+ if (empty_opstack(&opstack, output) != 0)
+ {
+ return 1;
+ }
+ *rpn = fifo_to_expr(output, size_offset);
+ if (!*rpn)
+ return 4;
+
+ return 0;
+}
diff --git a/graphs/piscine/evalexpr/src/stack.c b/graphs/piscine/evalexpr/src/stack.c
new file mode 100644
index 0000000..14f659e
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/stack.c
@@ -0,0 +1,57 @@
+#include "stack.h"
+
+#include <stdlib.h>
+
+struct stack *stack_push(struct stack *s, int e)
+{
+ struct stack *new = malloc(sizeof(struct stack));
+ new->data = e;
+ new->next = NULL;
+
+ new->next = s;
+ return new;
+}
+
+struct stack *stack_pop(struct stack *s)
+{
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ struct stack *res = s->next;
+ free(s);
+ return res;
+}
+
+int stack_peek(struct stack *s)
+{
+ return s->data;
+}
+
+struct tstack *tstack_push(struct tstack *s, struct token *e)
+{
+ struct tstack *new = malloc(sizeof(struct tstack));
+ new->token = e;
+ new->next = NULL;
+
+ new->next = s;
+ return new;
+}
+
+struct tstack *tstack_pop(struct tstack *s)
+{
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ struct tstack *res = s->next;
+ free(s);
+ return res;
+}
+
+struct token *tstack_peek(struct tstack *s)
+{
+ return s->token;
+}
diff --git a/graphs/piscine/evalexpr/src/stack.h b/graphs/piscine/evalexpr/src/stack.h
new file mode 100644
index 0000000..d08e465
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/stack.h
@@ -0,0 +1,20 @@
+#ifndef STACK_H
+#define STACK_H
+
+#include "evalexpr.h"
+#include "stack_struct.h"
+
+struct tstack
+{
+ struct token *token;
+ struct tstack *next;
+};
+
+struct stack *stack_push(struct stack *s, int e);
+struct stack *stack_pop(struct stack *s);
+int stack_peek(struct stack *s);
+
+struct tstack *tstack_push(struct tstack *s, struct token *e);
+struct tstack *tstack_pop(struct tstack *s);
+struct token *tstack_peek(struct tstack *s);
+#endif /* !STACK_H */
diff --git a/graphs/piscine/evalexpr/src/stack_struct.h b/graphs/piscine/evalexpr/src/stack_struct.h
new file mode 100644
index 0000000..105cd5d
--- /dev/null
+++ b/graphs/piscine/evalexpr/src/stack_struct.h
@@ -0,0 +1,10 @@
+#ifndef STACK_STRUCT_H
+#define STACK_STRUCT_H
+
+struct stack
+{
+ int data;
+ struct stack *next;
+};
+
+#endif /* ! STACK_STRUCT_H */
diff --git a/graphs/piscine/evalexpr/tests/tests.sh b/graphs/piscine/evalexpr/tests/tests.sh
new file mode 100755
index 0000000..920f09b
--- /dev/null
+++ b/graphs/piscine/evalexpr/tests/tests.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+REF_OUT="ref.out"
+TEST_OUT="test.out"
+
+testrpn()
+{
+ echo "$2" > "$REF_OUT"
+ echo "Evaluating '$1' in RPN notation..."
+ echo "$1" | ./evalexpr -rpn > "$TEST_OUT"
+ diff "$REF_OUT" "$TEST_OUT" && echo "Success"
+}
+
+testeval()
+{
+ echo "$1" | bc 2> /dev/null > "$REF_OUT"
+ echo "Evaluating '$1' in standard notation..."
+ echo "$1" | ./evalexpr > "$TEST_OUT"
+ diff "$REF_OUT" "$TEST_OUT" && echo "Success"
+}
+
+testerror()
+{
+ echo "Testing error code '$2'..."
+ echo "$1" | ./evalexpr
+ error="$(echo $?)"
+ [ "$2" -eq "$error" ] && echo "Succesful failure" || echo "Wrong error $error"
+}
+
+clean()
+{
+ rm "$REF_OUT" "$TEST_OUT"
+}
+
+# RPN
+
+echo "Tests for RPN:"
+echo "======"
+
+testrpn "1 1 +" 2
+testrpn "5 2 2 ^ 3 + *" 35
+testrpn "10 6 9 3 + 0 11 - * / * 17 + 5 +" 22
+testrpn "3 4 5 * 3 + -" "-20"
+testrpn "3 2 % 9 3 1 2 + * / -" 0
+
+echo
+echo "============================================="
+echo
+
+# Standard
+
+echo "Tests for standard notation:"
+echo "======"
+
+testeval "1 + 1"
+testeval " 1 + 1 +1 "
+testeval "2 * 2"
+testeval "5 * (2 + 4)"
+testeval "5 * (2 % 4)"
+testeval " 5 *(2 ^4) "
+testeval " 5 *(2 ^4 "
+
+echo
+echo "============================================="
+echo
+
+# Errors
+
+echo "Error tests:"
+echo "======"
+
+testerror "" 0
+testerror "a+1" 1
+testerror "1%0" 3
+
+echo "Testing error code '4'..."
+./evalexpr --toto 2> /dev/null
+echo $?
+
+# Cleanup
+
+clean
diff --git a/graphs/piscine/evalexpr/tests/unit_tests.c b/graphs/piscine/evalexpr/tests/unit_tests.c
new file mode 100644
index 0000000..ed445a0
--- /dev/null
+++ b/graphs/piscine/evalexpr/tests/unit_tests.c
@@ -0,0 +1,208 @@
+#include <criterion/criterion.h>
+#include <criterion/assert.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "../src/evalexpr.h"
+
+TestSuite(parse_number);
+
+Test(parse_number, parse_42)
+{
+ size_t o;
+ int actual = parse_number("42", &o);
+ cr_expect(actual == 42, "Attendu : %d, renvoyé : %d", 42, actual);
+ cr_expect(o == 1, "Décalage attendu : %d, renvoyé : %zu", 1, o);
+}
+
+Test(parse_number, parse_4)
+{
+ size_t o;
+ int actual = parse_number("4", &o);
+ cr_expect(actual == 4, "Attendu : %d, renvoyé : %d", 4, actual);
+ cr_expect(o == 0, "Décalage attendu : %d, renvoyé : %zu", 0, o);
+}
+
+TestSuite(my_pow);
+
+Test(my_pow, my_pow00)
+{
+ int actual = my_pow(0, 0);
+ cr_expect(actual == 1, "Attendu : %d, renvoyé : %d", 1, actual);
+}
+
+Test(my_pow, my_pown0)
+{
+ int actual = my_pow(50, 0);
+ cr_expect(actual == 1, "Attendu : %d, renvoyé : %d", 1, actual);
+}
+Test(my_pow, my_pow0n)
+{
+ int actual = my_pow(0, 42);
+ cr_expect(actual == 0, "Attendu : %d, renvoyé : %d", 0, actual);
+}
+Test(my_pow, my_powab)
+{
+ int actual = my_pow(3,3);
+ cr_expect(actual == 27, "Attendu : %d, renvoyé : %d", 27, actual);
+}
+Test(my_pow, my_powab_2)
+{
+ int actual = my_pow(4, 2);
+ cr_expect(actual == 16, "Attendu : %d, renvoyé : %d", 16, actual);
+}
+Test(my_pow, my_powab_3)
+{
+ int actual = my_pow(10, 3);
+ cr_expect(actual == 1000, "Attendu : %d, renvoyé : %d", 1000, actual);
+}
+Test(my_pow, my_pow1n)
+{
+ int actual = my_pow(1, 50);
+ cr_expect(actual == 1, "Attendu : %d, renvoyé : %d", 1, actual);
+}
+
+TestSuite(RPN);
+
+Test(RPN, evalrpn_easiest)
+{
+ const char test[] = "1 1 +";
+ int expected = 0;
+ int retval;
+ int res = 2;
+ int actual = evalrpn(test, &retval);
+ cr_expect(actual == expected, "%s => Retour attendu : %d, renvoyé : %d", test, expected, actual);
+ cr_expect(retval == res, "%s => Résultat attendu : %d, reçu : %d", test, res, retval);
+}
+Test(RPN, evalrpn_35)
+{
+ const char test[] = "5 2 2 ^ 3 + *";
+ int expected = 0;
+ int retval;
+ int res = 35;
+ int actual = evalrpn(test, &retval);
+ cr_expect(actual == expected, "%s => Retour attendu : %d, renvoyé : %d", test, expected, actual);
+ cr_expect(retval == res, "%s => Résultat attendu : %d, reçu : %d", test, res, retval);
+}
+Test(RPN, evalrpn_22)
+{
+ const char test[] = "10 6 9 3 + 0 11 - * / * 17 + 5 +";
+ int expected = 0;
+ int retval;
+ int res = 22;
+ int actual = evalrpn(test, &retval);
+ cr_expect(actual == expected, "%s => Retour attendu : %d, renvoyé : %d", test, expected, actual);
+ cr_expect(retval == res, "%s => Résultat attendu : %d, reçu : %d", test, res, retval);
+}
+Test(RPN, evalrpn_minus20)
+{
+ const char test[] = "3 4 5 * 3 + -";
+ int expected = 0;
+ int retval;
+ int res = -20;
+ int actual = evalrpn(test, &retval);
+ cr_expect(actual == expected, "%s => Retour attendu : %d, renvoyé : %d", test, expected, actual);
+ cr_expect(retval == res, "%s => Résultat attendu : %d, reçu : %d", test, res, retval);
+}
+Test(RPN, evalrpn_zero)
+{
+ const char test[] = "3 2 % 9 3 1 2 + * / -";
+ int expected = 0;
+ int retval;
+ int res = 0;
+ int actual = evalrpn(test, &retval);
+ cr_expect(actual == expected, "%s => Retour attendu : %d, renvoyé : %d", test, expected, actual);
+ cr_expect(retval == res, "%s => Résultat attendu : %d, reçu : %d", test, res, retval);
+}
+
+TestSuite(Precedence);
+
+Test(Precedence, parenthesis_above_all)
+{
+ struct token pleft = { PAR_LEFT, '(' };
+ struct token pright = { PAR_RIGHT, ')' };
+ struct token unplus = { UN_PLUS, '+' };
+ struct token exp = { EXP, '^' };
+ struct token mul = { MUL, '*' };
+ struct token minus = { SUB, '-' };
+ int eq = opcmp(&pleft, &pright);
+ int sup = opcmp(&pleft, &unplus);
+ int inf = opcmp(&unplus, &pright);
+ int parftw = opcmp(&pleft, &exp);
+ int par4ever = opcmp(&pright, &mul);
+ int paragain = opcmp(&pright, &minus);
+ cr_expect(eq == 0, "Wrong order (equal)");
+ cr_expect(sup > 0, "Wrong order (>)");
+ cr_expect(inf < 0, "Wrong order (<)");
+ cr_expect(parftw > 0, "Wrong order (>)");
+ cr_expect(par4ever > 0, "Wrong order (>)");
+ cr_expect(paragain > 0, "Wrong order (>)");
+}
+
+Test(Precedence, other_precedence_tests)
+{
+ struct token exp = { EXP, '^' };
+ struct token mul = { MUL, '*' };
+ struct token unplus = { UN_PLUS, '+' };
+ struct token minus = { SUB, '-' };
+ struct token plus = { ADD, '+' };
+ int eq = opcmp(&minus, &plus);
+ int sup = opcmp(&exp, &mul);
+ int inf = opcmp(&plus, &unplus);
+
+ cr_expect(eq == 0, "Wrong order (equal)");
+ cr_expect(sup > 0, "Wrong order (>)");
+ cr_expect(inf < 0, "Wrong order (<)");
+}
+
+TestSuite(ShuntingTests);
+
+Test(ShuntingTests, shunt_simplest)
+{
+ char *rpn;
+ const char *expr = "1 + 1";
+ int actual = shunting_yard(expr, &rpn);
+ cr_expect(actual == 0, "Expected shunting_yard return value %d, got %d", 0, actual);
+ cr_expect(strcmp(rpn, "1 1 +") == 0, "Expected '1 1 +', got %s", rpn);
+ free(rpn);
+}
+
+Test(ShuntingTests, shunt_nico)
+{
+ char *rpn;
+ const char *expr = "1 + 1 + 1";
+ int actual = shunting_yard(expr, &rpn);
+ cr_expect(actual == 0, "Expected shunting_yard return value %d, got %d", 0, actual);
+ cr_expect(strcmp(rpn, "1 1 + 1 +") == 0, "Expected '1 1 + 1 +', got %s", rpn);
+ free(rpn);
+}
+
+Test(ShuntingTests, shunt_harderdaddy)
+{
+ char *rpn;
+ const char *expr = "5*(2^2+3)";
+ int actual = shunting_yard(expr, &rpn);
+ cr_expect(actual == 0, "Expected shunting_yard return value %d, got %d", 0, actual);
+ cr_expect(strcmp(rpn, "5 2 2 ^ 3 + *") == 0, "Expected '5 2 2 ^ 3 + *', got %s", rpn);
+ free(rpn);
+}
+
+Test(ShuntingTests, shunt_numbers)
+{
+ char *rpn;
+ const char *expr = "42 + 50";
+ int actual = shunting_yard(expr, &rpn);
+ cr_expect(actual == 0, "Expected shunting_yard return value %d, got %d", 0, actual);
+ cr_expect(strcmp(rpn, "42 50 +") == 0, "Expected '42 50 +', got %s", rpn);
+ free(rpn);
+}
+
+Test(ShuntingTests, shunt_mod)
+{
+ char *rpn;
+ const char *expr = "42 % 50";
+ int actual = shunting_yard(expr, &rpn);
+ cr_expect(actual == 0, "Expected shunting_yard return value %d, got %d", 0, actual);
+ cr_expect(strcmp(rpn, "42 50 %") == 0, "Expected '42 50 +', got %s", rpn);
+ free(rpn);
+}