#include "ExprParser.h"
/*词法分析*/
int g_type,g_error,g_braBal,g_oper;
double g_value;
const char* g_str,*g_last_str,* g_pos;
int GetNextToken()
{
    static char tokenBuf[32];
    int tokenPos=0,nDot=0;
    g_last_str=g_str;
    while (*g_str==' ')++g_str; //改动1
    if (!*g_str)
        return g_type=END;
    //Comment: Read a number!
    if (isdigit(*g_str))
    {
        while (isdigit(*g_str)||(*g_str=='.'))
        {
            tokenBuf[tokenPos++] = *g_str++;
            if(*g_str=='.')
                nDot++;
        }
        tokenBuf[tokenPos]= 0;
        g_value=atof((const char*)tokenBuf);
        if(nDot<=1)
            return g_type = NUMBER;
        else
            return g_type=ERROR;
    }
    //Comment: Read a operator.
    switch (*g_str++)
    {
    case '+' : g_oper = ADD;return g_type=OPERATOR;
    case '-' : g_oper = SUB;return g_type=OPERATOR;
    case '*' : g_oper = MUL;return g_type=OPERATOR;
    case '/' : g_oper = DIV;return g_type=OPERATOR;
    case '(' : return g_type=LB;
    case ')' : return g_type=RB;
    }
    return g_type=ERROR;
}

void PutBack()
{
    //Comment If any error.
    if (g_str != g_last_str) g_str = g_last_str;
}

TREE* MakeNode(int type, double value, int oper, TREE* l, TREE* r, TREE* p)
{
    TREE* node = (TREE*)malloc(sizeof(TREE));
    node->type = type;
    node->value = value;
    node->oper = oper;
    node->left = l;
    node->right = r;
    node->parent = p;
    return node;
}

void DestroyTree(TREE* tree)
{
    if(!tree)
        return;
    if(tree->left)
        DestroyTree(tree->left);
    if(tree->right)
        DestroyTree(tree->right);
    free(tree);
}

int Level(int oper)
{
    switch(oper)
    {
    case ATOMM:return 0;
    case MUL:case DIV: return 1;
    case ADD:case SUB: return 2;
    case EXPR:return 32;
    }
}

void ShowError()
{
    char buff[256]={0};
    switch (g_error)
    {
        case 1:sprintf(buff, "需要一个运算符\t位置%s\n", g_pos);break;
        case 2:sprintf(buff, "需要一个表达式\t位置%s\n", g_pos);break;
        case 3:sprintf(buff, "括号不匹配\t位置%s\n", g_pos);break;
        case 4:sprintf(buff, "空表达式\t位置%s\n", g_pos);break;
        case 5:sprintf(buff, "表达式不应该在此结束\t位置%s\n", g_pos);break;
    }
    printf(buff);
}

TREE* BuildSyntaxTreeImpl()
{
    TREE* root, *treeTmp,*new_node;
    int use_level=0,state=0;
    root=treeTmp= MakeNode(OPERATOR,0,EXPR,0,0,0);
    //关键在于下面构造语法树的过程
    //原子的优先级很好,对应着直接建立一个结点
    //其它的,要比较结点的优先级
    //要比较结点先计算,意味着,是作为这个结点的孩子
    //否则就是要结点移动
    //对应着就表现出现优先级了
    while(1)
    {
        GetNextToken();
        switch (g_type)
        {
            case NUMBER:
                new_node=MakeNode(NUMBER, g_value, ATOMM, 0, 0, 0);
                use_level=1;
                state = 1;
                break;
            case LB:
                ++g_braBal;
                new_node = BuildSyntaxTreeImpl();
                use_level=0;/*括号表达式的优先级很高,不使用优先级比较,直接建为右子树*/
                state = 1;
                break;
            case RB:
                --g_braBal;
            case END:
                {
                    treeTmp = root->right;
                    free(root);
                    treeTmp->parent = NULL;
                    return treeTmp;
                }
            default:
                new_node = MakeNode(OPERATOR, 0, g_oper, 0, 0, 0);
                use_level=1;
                state = 0;
        }      
        if(use_level)
        {
            while(Level(new_node->oper)>=Level(treeTmp->oper))
                treeTmp=treeTmp->parent;
            new_node->left = treeTmp->right;
            treeTmp->right = new_node;
            new_node->parent = treeTmp;
            treeTmp = new_node;
        }
        else
        {
            treeTmp->right = new_node;
            new_node->parent = treeTmp;
        }
    }
}

TREE* BuildSyntaxTree(const char* expression)
{
    TREE* tree;
    g_braBal = 0;
    g_last_str = g_str = expression;
    tree = BuildSyntaxTreeImpl();
    if (g_braBal)
    {
        PutBack();
        g_error = 3;
        g_pos = g_str;
        DestroyTree(tree);
        tree = 0;
    }
    return tree;
}

double EvalueTree(TREE* tree)
{
    double l, r;
    if (!tree) return 0;
    if (tree->oper==ATOMM) return tree->value;
    l = EvalueTree(tree->left);
    r = EvalueTree(tree->right);
    switch(tree->oper)
    {
    case ADD: return l + r;
    case SUB: return l - r;
    case MUL: return l * r;
    case DIV: return l / r;
    }
    return 0;
}

double Calculate(const char* expression)
{
    TREE* tree = BuildSyntaxTree(expression);
    double value = 0;
    if (!tree) ShowError();
    else value = EvalueTree(tree);
    DestroyTree(tree);
    return value;
}
posted on 2011-06-07 12:46  kangwang1988  阅读(607)  评论(0)    收藏  举报