shuntyard

Djiskstra's 'Shunting Yard' algorithm
git clone git://src.gearsix.net/shuntyard
Log | Files | Refs | Atom

commit 2b81f891f712c5b3e486dab4d4ee8993ad2ecbea
Author: gearsix <gearsix@tuta.io>
Date:   Mon, 15 Nov 2021 18:24:00 +0000

git init

Diffstat:
Ashuntyard.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astack.c | 43+++++++++++++++++++++++++++++++++++++++++++
Astack.h | 23+++++++++++++++++++++++
3 files changed, 177 insertions(+), 0 deletions(-)

diff --git a/shuntyard.c b/shuntyard.c @@ -0,0 +1,111 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include "stack.h" + +char isop(char c); +int op_isleft(char c); // associativity (left/right) +int op_prec(char c); // precendence + +int main(int argc, char *argv[]) +{ + size_t len = 0; + for (int i = 1; i < argc; ++i) { + if (argv[i]) + len += strlen(argv[i]); + } + char *input = calloc(1, len+1); + for (int i = 1; i < argc; ++i) { + strcat(input, argv[i]); + } + puts(input); + + struct stack *ops = stack_new(); + struct stack *out = stack_new(); + + int tok; + for (size_t i = 0; i < len+1; ++i) { + tok = input[i]; + if (isop(tok)) { + while (!stack_isempty(ops)) { + int assoc = op_isleft(tok); + int prec = op_prec(tok); + if ((assoc && prec <= op_prec(stack_peek(ops))) || + (!assoc && prec < op_prec(stack_peek(ops)))) { + stack_push(out, stack_pop(ops)); + } else { + break; + } + } + stack_push(ops, tok); + } else if (tok == '(') { + stack_push(ops, tok); + } else if (tok == ')') { + while (stack_peek(ops) != '(') + stack_push(out, stack_pop(ops)); + stack_pop(ops); + } else { + stack_push(out, tok); + } + } + + while (!stack_isempty(ops)) + stack_push(out, stack_pop(ops)); + + for (int i = 0; i <= out->sp; ++i) + putchar(out->s[i]); + puts(""); + + return 0; +} + +char isop(char c) +{ + char ret = 0; + switch (c) { + case '*': + case '/': + case '-': + case '+': + case '^': + ret = c; + break; + } + return ret; +} + +int op_isleft(char op) +{ + int ret = 0; + switch (op) { + case '*': + case '/': + case '+': + case '-': + ret = 1; + break; + case '^': + break; + } + return ret; +} + +int op_prec(char op) +{ + int ret = 0; + switch (op) { + case '^': + ret = 4; + break; + case '*': + case '/': + ret = 3; + break; + case '+': + case '-': + ret = 2; + break; + } + return ret; +} diff --git a/stack.c b/stack.c @@ -0,0 +1,43 @@ +#include "stack.h" + +struct stack *stack_new() +{ + const size_t siz = 1024; + + struct stack *s = malloc(sizeof(struct stack *)); + s->s = malloc(siz); + s->sp = -1; + s->siz = siz; + + return s; +} + +int stack_isempty(struct stack *s) +{ + return (s->sp == -1); +} + +int stack_isfull(struct stack *s) +{ + return (s->sp == s->siz); +} + +int stack_peek(struct stack *s) +{ + if (!stack_isempty(s)) + return s->s[s->sp]; + return 0; +} + +void stack_push(struct stack *s, int item) +{ + if (!stack_isfull(s)) + s->s[++s->sp] = item; +} + +int stack_pop(struct stack *s) +{ + if (!stack_isempty(s)) + return s->s[s->sp--]; + return 0; +} diff --git a/stack.h b/stack.h @@ -0,0 +1,23 @@ +#ifndef STACK_H +#define STACK_H + +#include <stdlib.h> + +struct stack { + char *s; + int sp, siz; +}; + +struct stack *stack_new(); + +int stack_isempty(struct stack *s); + +int stack_isfull(struct stack *s); + +int stack_peek(struct stack *s); + +void stack_push(struct stack *s, int item); + +int stack_pop(struct stack *s); + +#endif