二分木を利用した構文解析

二分木が熱い!
数式の構文解析をするための二分木構造をつくってみました
まだ書きかけですが...

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void blacket_cut(char[]);
enum type{value,symbol};
typedef struct tree_tag{
  struct tree_tag *right;
  struct tree_tag *left;
  enum type t;
  int id;
  char formula[80];
}node;
char enzns[8] ="+-*/^";
void ExpansionNode(node *p)
{
  int i=0,j,k;
  blacket_cut(p->formula);
  if(p->formula[0] == '('){
    k=1;
    while(k!=0){
      i++;
      if(p->formula[i] == '(')
        k++;
      else if(p->formula[i] == ')')
        k--;
    }
    p->t=symbol;
    p->id = p->formula[i+1];
    node *right,*left;
    right = (node*)malloc(sizeof(struct tree_tag));
    right->right = NULL;
    right->left = NULL;
    left = (node*)malloc(sizeof(struct tree_tag));
    left->right = NULL;
    left->left = NULL;
    p->right = right;
    p->left = left;
    strcpy(right->formula,&(p->formula[i+2]));
    p->formula[i+1] = '\0';
    strcpy(left->formula,p->formula);
    ExpansionNode(p->right);
    ExpansionNode(p->left);
    return;
  }else{
    for(i=0;i<strlen(p->formula);i++){
      if(strchr(enzns,p->formula[i])){
        p->t = symbol;
        p->id = p->formula[i];
        p->t=symbol;
        node *right,*left;
        right = (node*)malloc(sizeof(struct tree_tag));
        right->right = NULL;
        right->left = NULL;
        left = (node*)malloc(sizeof(struct tree_tag));
        left->right = NULL;
        left->left = NULL;
        p->right = right;
        p->left = left;
        strcpy(right->formula,&p->formula[i+1]);
        p->formula[i] = '\0';
        strcpy(left->formula,p->formula);
        ExpansionNode(p->right);
        ExpansionNode(p->left);
        return;
    }

  }
    p->t = value;
    p->id = atoi(p->formula);
    return;
  }
}
void simplize(char shiki[])
{
  int i,k,len=strlen(shiki);
  for(i=0;i<len;i++)
    if(shiki[i] == ' '){
      for(k=i;shiki[k+1];k++)
        shiki[k] = shiki[k+1];
      shiki[k] = '\0';
      i--;
    }
  blacket_cut(shiki);
}

void blacket_cut(char shiki[])
{
  if(shiki[0] == '(' && shiki[strlen(shiki)-1] == ')'){
    int i,k=1;
    for(i=1;i<strlen(shiki);i++){
      if(shiki[i] == '(')
        k++;
      else if(shiki[i] == ')')
        k--;
      if(k==0)
        break;
    }
    if(i == (strlen(shiki) -1)){
    shiki[strlen(shiki)-1] = '\0';
    for(i=0;shiki[i+1];i++)
      shiki[i] = shiki[i+1];
    shiki[i] = '\0';
    blacket_cut(shiki);
    }
  }else
    return;
  return;
}

void tansaku(node *p)
{
  if(p->left != NULL)
    tansaku(p->left);
  switch(p->t){
  case symbol:
    printf("%c",p->id);
    break;
  case value:
    printf("%d",p->id);
    break;
  }
  if(p->right != NULL)
    tansaku(p->right);

}

int main()
{
  char shiki[256];
  fgets(shiki,256,stdin);
  shiki[strlen(shiki)-1] = '\0';
  simplize(shiki);
  node root;
  strcpy(root.formula,shiki);
  printf("通りがけ走査 : ");
  ExpansionNode(&root);
  tansaku(&root);
  printf("\n");

}

実行結果

((66*7+99/7)*(66+22-4+0))
通りがけ走査 : 66*7+99/7*66+22-4+0


かなり行き当たりばったりで作っているのでサブルーチン化できそうな改善点がたくさんあります^^;
標準入力から数式を持ってきて、simplizeという関数でスペースをすべて詰めています。
その数式を構造体ノードのformulaに突っ込んでExpansionNodeを実行。
括弧を削るためのblaket_cutなどを用いながらExpansionNodeを再帰的に実行して葉の部分に数値が集まります。
作られた木に対して、通りがけ走査を実施し、それぞれの要素を印字していきます。
なんの工夫もなく走査しているので、実行結果をみてみると、入力された結果に対して括弧がぬけています。
そこで走査の部分をこのように改変してみました

void tansaku(node *p)
{
  printf("(");
  if(p->left != NULL)
    tansaku(p->left);
  switch(p->t){
  case symbol:
    printf("%c",p->id);
    break;
  case value:
    printf("%d",p->id);
    break;
  }
  if(p->right != NULL)
    tansaku(p->right);
  printf(")");

}

実行結果

((66*7+99/7)*(66+22-4+0))
通りがけ走査 : (((66)*((7)+((99)/(7))))*((66)+((22)-((4)+(0)))))

ウーン括弧をつけた部分は演算順序が守られているけど、それ以外はめちゃくちゃになってしまっています
演算の優先順位についても考慮する必要がありそうです
これを利用してコンソール上で動く電卓のようなものを作ろうと思っています