shuntyard

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

shuntyard.c (1781B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <stdbool.h>
      5 #include "stack.h"
      6 
      7 char isop(char c);
      8 int  op_isleft(char c); // associativity (left/right)
      9 int  op_prec(char c);   // precendence
     10 
     11 int main(int argc, char *argv[])
     12 {
     13 	size_t len = 0;
     14 	for (int i = 1; i < argc; ++i) {
     15 		if (argv[i])
     16 		len += strlen(argv[i]);
     17 	}
     18 	char *input = calloc(1, len+1);
     19 	for (int i = 1; i < argc; ++i) {
     20 		strcat(input, argv[i]);
     21 	}
     22 	puts(input);
     23 
     24 	struct stack *ops = stack_new();
     25 	struct stack *out = stack_new();
     26 
     27 	int tok;
     28 	for (size_t i = 0; i < len+1; ++i) {
     29 		tok = input[i];
     30 		if (isop(tok)) {
     31 			while (!stack_isempty(ops)) {
     32 				int assoc = op_isleft(tok);
     33 				int prec = op_prec(tok);
     34 				if ((assoc && prec <= op_prec(stack_peek(ops))) ||
     35 					(!assoc && prec < op_prec(stack_peek(ops)))) {
     36 					stack_push(out, stack_pop(ops));
     37 				} else {
     38 					break;
     39 				}
     40 			}
     41 			stack_push(ops, tok);
     42 		} else if (tok == '(') {
     43 			stack_push(ops, tok);
     44 		} else if (tok == ')') {
     45 			while (stack_peek(ops) != '(')
     46 				stack_push(out, stack_pop(ops));
     47 			stack_pop(ops);
     48 		} else {
     49 			stack_push(out, tok);
     50 		}
     51 	}
     52 
     53 	while (!stack_isempty(ops))
     54 		stack_push(out, stack_pop(ops));
     55 
     56 	for (int i = 0; i <= out->sp; ++i)
     57 		putchar(out->s[i]);
     58 	puts("");
     59 
     60 	return 0;
     61 }
     62 
     63 char isop(char c)
     64 {
     65 	char ret = 0;
     66 	switch (c) {
     67 		case '*':
     68 		case '/':
     69 		case '-':
     70 		case '+':
     71 		case '^':
     72 			ret = c;
     73 			break;
     74 	}
     75 	return ret;
     76 }
     77 
     78 int op_isleft(char op)
     79 {
     80 	int ret = 0;
     81 	switch (op) {
     82 		case '*':
     83 		case '/':
     84 		case '+':
     85 		case '-':
     86 			ret = 1;
     87 			break;
     88 		case '^':
     89 			break;
     90 	}
     91 	return ret;
     92 }
     93 
     94 int op_prec(char op)
     95 {
     96 	int ret = 0;
     97 	switch (op) {
     98 		case '^':
     99 			ret = 4;
    100 			break;
    101 		case '*':
    102 		case '/':
    103 			ret = 3;
    104 			break;
    105 		case '+':
    106 		case '-':
    107 			ret = 2;
    108 			break;
    109 	}
    110 	return ret;
    111 }