File: expr.c | Size: 7,895 bytes | Download file | Back to directory listing | BWPOW's homepage
/*
    expC - Expressions analyzator and viewer
    Copyright (C) 2004 Samuel Kupka
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include <stdio.h>
#include <string.h>
#include <allegro.h>
 
#include "expC.h"
 
/* Globalne premenne */
EXPR_NODE *expr_tree;
int tree_size;
int tree_used;
int num_leaves;
int expr_max_x;
int expr_max_y;
 
EXPR_ATOM atom[MAX_ATOM];
int num_atom;
 
/* Program */
int err_pos;
 
int expr_show_node(BITMAP *bmp,int node,int orig,int x,int y)
{
  if(node<=orig) return x;
  if(node<0||node>=tree_used) return x;
  if(expr_tree[node].node<=0) return x;
 
  if(expr_tree[node].node<=MAX_ATOM){
    x+=expr_draw_atom(bmp,x,y,expr_tree[node].node,0,-1,1);
    return x;
  }
 
  x+=expr_draw_string(bmp,x,y,"(",0,-1,1);
  x=expr_show_node(bmp,expr_tree[node].next[0],node,x,y);
 
  x+=expr_draw_node(bmp,x,y,node,0,-1,1);
 
  x=expr_show_node(bmp,expr_tree[node].next[1],node,x,y);
  x+=expr_draw_string(bmp,x,y,")",0,-1,1);
 
  return x;
}
 
void expr_show_text(BITMAP *bmp,int x,int y)
{
  x+=expr_draw_string(exp_bmp,x,5,"Vyrok: ",0,-1,1);
  expr_show_node(bmp,0,-1,x,y);
}
 
int expr_draw_string(BITMAP *bmp,int x,int y,char *str,int c1,int c2,char draw)
{
  int w=0,symbol=0;
  char buf[10];
 
  if(!stricmp(str,"alfa")) symbol='a';
  if(!stricmp(str,"alpha")) symbol='a';
  if(!stricmp(str,"beta")) symbol='b';
  if(!stricmp(str,"gamma")) symbol='g';
  if(!stricmp(str,"gama")) symbol='g';
  if(!stricmp(str,"delta")) symbol='d';
 
  if(!stricmp(str,"&")) symbol='Ù';
  if(!stricmp(str,"|")) symbol='Ú';
  if(!stricmp(str,"!")) symbol='Ø';
 
  if(symbol!=0){
    sprintf(buf,"%c",symbol);
    w=text_length(data[sfont].dat,buf)+2;
    if(draw==1) textout_ex(bmp,data[sfont].dat,buf,x+2,y,c1,c2);
  }
  else{
    w=text_length(font,str);
    if(draw==1) textout_ex(bmp,font,str,x,y,c1,c2);
  }
 
  return w;
}
 
int expr_draw_atom(BITMAP *bmp,int x,int y,int num,int c1,int c2,char draw)
{
  if(num<1||num>num_atom) return 0;
  return expr_draw_string(bmp,x,y,atom[num-1].str,c1,c2,draw);
}
 
int expr_draw_node(BITMAP *bmp,int x,int y,int node,int c1,int c2,char draw)
{
  char str[3];
 
  if(node<0||node>=tree_used) return x;
  if(expr_tree[node].node<=0) return x;
 
  if(expr_tree[node].node<=MAX_ATOM){
    x+=expr_draw_atom(bmp,x,y,expr_tree[node].node,0,-1,draw);
    return x;
  }
 
  str[0]=0;
  if(expr_tree[node].node==OPER_AND) str[0]='&';
  if(expr_tree[node].node==OPER_OR) str[0]='|';
  if(expr_tree[node].node==OPER_NOT) str[0]='!';
  str[1]=0;
  x=expr_draw_string(bmp,x,y,str,0,-1,draw);
  return x;
}
 
void expr_init(void)
{
  tree_size=0;
}
 
void expr_exit(void)
{
   if(tree_size>0){
      free(expr_tree);
   }
}
 
int expr_which_oper(unsigned char c)
{
  if(c=='&') return OPER_AND;
  if(c=='|') return OPER_OR;
  if(c=='!') return OPER_NOT;
  return 0;
}
 
int expr_find_oper(char *expr,int s,int e,int *vysl_hl)
{
  int i,f_p=-1,f_h=10000,f_o=0,h=0,o;
 
  if(e<s){err_pos=s; return -1;}
 
  for(i=s;i<=e;i++){
    if(expr[i]=='(') h++;
    if(expr[i]==')') h--;
    o=expr_which_oper(expr[i]);
    if(o>0){
      if(h<f_h){f_p=i;f_h=h;f_o=o;}
      if(h==f_h&&o<f_o){f_p=i;f_h=h;f_o=o;}
    }
  }
 
  if(h!=0){err_pos=s; return -1;}
 
  *vysl_hl=f_h;
  return f_p;
}
 
int expr_find_atom(char *str)
{
  int i;
  for(i=0;i<num_atom;i++){
    if(!stricmp(str,atom[i].str)) return i+1;
  }
 
  if(num_atom>=MAX_ATOM) return -1;
 
  strcpy(atom[num_atom].str,str);
  num_atom++;
  return num_atom;
}
 
 
int expr_str_to_atom(char *expr,int s,int e,int tp)
{
  int i,h=0,z=0,ok,ss=-1,ee=-2;
  char str[16];
 
  for(i=s;i<=e;i++){
    ok=0;
    if(expr[i]=='('){
      if(z){err_pos=i; return -1;}
      h++; expr[i]=' ';
    }
    if(expr[i]==')'){
      h--;z=1;expr[i]=' ';
      if(h<0){err_pos=i; return -1;}
    }
    if(expr[i]==' ') ok=1;
    if(expr[i]=='_') ok=1;
    if(expr[i]>='a'&&expr[i]<='z') ok=1;
    if(expr[i]>='A'&&expr[i]<='Z') ok=1;
    if(expr[i]>='0'&&expr[i]<='9') ok=1;
    if(ok!=1){err_pos=i; return -1;}
  }
 
  for(i=s;i<=e;i++){
    if(expr[i]!=' '){
      ss=i;
      break;
    }
  }
  for(i=e;i>=s;i--){
    if(expr[i]!=' '){
      ee=i;
      break;
    }
  }
  if(ee<ss){err_pos=ss; return -1;}
 
  z=0;
  for(i=ss;i<=ee;i++){
    str[z]=expr[i];
    if(str[z]==' ') str[z]='_';
    z++;
  }
  str[z]=0;
 
  z=expr_find_atom(str);
  if(z<0){ return -1;err_pos=s; }
 
  expr_tree[tree_used].node=z;
  expr_tree[tree_used].x=num_leaves*100;
  num_leaves++;
  tree_used++;
 
  return 0;
}
 
int expr_str_to_tree(char *expr,int s,int e,int tp)
{
  int p,h,o,n,ss,ee,i;
 
  if(tree_used>=tree_size) return -1;
 
  expr_tree[tree_used].prev=tp;
 
  p=expr_find_oper(expr,s,e,&h);
  if(p>=0){
    o=expr_which_oper(expr[p]);
    expr_tree[tree_used].node=o;
 
    tp=tree_used;
    tree_used++;
 
    ss=s;
    ee=e;
    if(h>0){
      n=0;
      ss=-1;
      ee=-1;
      for(i=s;i<p;i++){
        if(expr[i]=='(') n++;
        if(n==h){
          ss=i+1;
          break;
        }
      }
      n=0;
      for(i=e;i>p;i--){
        if(expr[i]==')') n++;
        if(n==h){
          ee=i-1;
          break;
        }
      }
      if(ss<0){err_pos=s; return -1;}
      if(ee<0){err_pos=e; return -1;}
    }
 
    if(o!=OPER_NOT){
      expr_tree[tp].next[0]=tree_used;
      if(expr_str_to_tree(expr,ss,p-1,tp)<0) return -1;
    }
    expr_tree[tp].next[1]=tree_used;
    if(expr_str_to_tree(expr,p+1,ee,tp)<0) return -1;
  }
  else{
    if(expr_str_to_atom(expr,s,e,tp)<0) return -1;
  }
 
  return 0;
}
 
int expr_calc_xy_positions(int p,int h)
{
  int x,poc;
 
  expr_tree[p].y=h*80;
  if(expr_tree[p].y>expr_max_y) expr_max_y=expr_tree[p].y;
 
  if(expr_tree[p].node<=MAX_ATOM){
    if(expr_tree[p].x>expr_max_x) expr_max_x=expr_tree[p].x;
    return expr_tree[p].x;
  }
 
  x=0;poc=0;
  if(expr_tree[p].next[0]>0){
    x+=expr_calc_xy_positions(expr_tree[p].next[0],h+1);
    poc++;
  }
  if(expr_tree[p].next[1]>0){
    x+=expr_calc_xy_positions(expr_tree[p].next[1],h+1);
    poc++;
  }
  if(poc>0){
    x/=poc;
    expr_tree[p].x=x;
    if(x>expr_max_x) expr_max_x=x;
    return x;
  }
  return 0;
}
 
int expr_to_tree(char *expr)
{
  int l,r;
  char tbuf[64];
  l=strlen(expr);
  if(l<1){
    alert("Validator","Vyrok musi obsahovat aspon jeden atom!",NULL,"&OK",0,'o',0);
    return -1;
  }
 
  if(tree_size>0) free(expr_tree);
  tree_size=l;
  num_atom=0;
  tree_used=0;
  num_leaves=0;
  expr_max_x=0;
  expr_max_y=0;
 
  err_pos=0;
 
  expr_tree=(EXPR_NODE *)malloc(tree_size*sizeof(EXPR_NODE));
  memset(expr_tree,0,tree_size*sizeof(EXPR_NODE));
 
  r=expr_str_to_tree(expr,0,l-1,-1);
  if(r<0){
    sprintf(tbuf,"Chyba je pri %d. znaku vyroku.",err_pos+1);
    alert("Validator",tbuf,NULL,"&OK",0,'o',0);
    return r;
  }
  r=expr_calc_xy_positions(0,0);
  if(r<0){
    alert("Validator","Vygenerovany strom nie je korektny.","Jedna sa o chybu v programe!","&OK",0,'o',0);
    return r;
  }
  return 0;
}