| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1590 人关注过本帖, 1 人收藏
标题:. . . LALR(1) 表达式计算器 源代码
只看楼主 加入收藏
flyue
Rank: 10Rank: 10Rank: 10
来 自:江南西道
等 级:贵宾
威 望:19
帖 子:3465
专家分:1563
注 册:2006-6-20
结帖率:100%
收藏(1)
 问题点数:0 回复次数:10 
. . . LALR(1) 表达式计算器 源代码
程序代码:
/* 产生式
lines    : lines expr '\n'
        | lines '\n'
        | error '\n'
        ;

expr    : expr '+' term
        | expr '-' term
        | term
        ;

term    : term '*' factor
        | term '/' factor
        | factor
        ;

factor    : '(' expr ')'
        | '(' expr error
        | '-' factor
        | NUMBER
        ;
*/


// 110211 Flying Blue 整理
// 像天书一样.. 不过速度确实很快!
// 编译器的词法, 语法分析, 就是采用这种方式实现的

#include <ctype.h>
#include <stdio.h>

#define STYPE double

#define NUMBER 257
#define ERRCODE 256

short lhs_tbl[] =
{
    -1, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
};
short len_tbl[] =
{
    2, 3, 2, 0, 2, 3, 3, 1, 3, 3, 1, 3, 3, 2, 1,
};
short defred_tbl[] =
{
    0, 0, 0, 4, 14, 2, 0, 0, 0, 0, 10, 13, 0, 1, 0, 0, 0, 0, 12, 11, 0, 0, 8, 9,
};
short dgoto_tbl[] =
{
    2, 8, 9, 10,
};
short sindex_tbl[] =
{
    - 251, 5, -10, 0, 0, 0, - 38, - 38, - 6, - 29, 0, 0, - 35, 0, - 38, - 38, - 38, - 38,
    0, 0, - 29, - 29, 0, 0,
};
short rindex_tbl[] =
{
    1, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 4, 0, 0,
};
short gindex_tbl[] =
{
    0, 12, 2, 6,
};


#define TABLESIZE 260

short main_tbl[] =
{
    5,
    3,    7,    7,   13,    1,   19,    6,   14,    5,   15,
    3,   11,   16,    6,    3,   20,   21,   17,   12,    0,
    0,   22,   23,    0,    0,    0,    0,    0,    0,    7,
    0,    0,    0,    7,    6,    7,   14,    7,   15,    5,
    3,    5,    0,    5,    6,    3,    6,    0,    6,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    4,    0,
    18,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    4,    0,    7,    0,
    0,    0,    0,    0,    5,    0,    0,    3,    0,    6,
};
short check_tbl[] =
{
    10,
    0,   40,   10,   10,  256,   41,   45,   43,   10,   45,
    10,    6,   42,   10,   10,   14,   15,   47,    7,   -1,
    -1,   16,   17,   -1,   -1,   -1,   -1,   -1,   -1,   40,
    -1,   -1,   -1,   41,   45,   43,   43,   45,   45,   41,
    40,   43,   -1,   45,   41,   45,   43,   -1,   45,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  257,   -1,
    256,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,  257,   -1,  256,   -1,
    -1,   -1,   -1,   -1,  256,   -1,   -1,  257,   -1,  256,
};

#define FINAL 2

#define STACKSIZE 500
#define MAXDEPTH 500

#define errok        (errflag=0)

int nerrs;
int errflag;
int mychar;
short *state_stack_ptr;
STYPE *vsp;
STYPE val;
STYPE lex_val;
short state_stack[STACKSIZE];
STYPE val_stack[STACKSIZE];

//-------------------------------------------------------------------------

char formula[256] = "111 + 222 - 333 + 4.5\n";
int formula_ptr = 0;

int lex(void)
{
    int c;

    while((c = formula[formula_ptr]) == ' ')
        formula_ptr++;
    if(c == '.' || isdigit(c))
    {
        int tmp;

        sscanf(formula + formula_ptr, "%lf%n", &lex_val, &tmp);
        formula_ptr += tmp;
        return NUMBER;
    }
    else formula_ptr++;
    return c;
}

//-------------------------------------------------------------------------

int parse()
{
    int m, n, state;

    formula_ptr = 0;
    nerrs = 0;
    errflag = 0;
    mychar = ( -1);

    state_stack_ptr = state_stack;
    vsp = val_stack;
    *state_stack_ptr = state = 0;

loop:
    if(n = defred_tbl[state])
    {
        goto reduce;
    }
    if(mychar < 0)
    {
        if((mychar = lex()) < 0)
        {
            mychar = 0;
        }
    }
    if((n = sindex_tbl[state]) && (n += mychar) >= 0 && n <= TABLESIZE && check_tbl[n] == mychar)
    {
        if(state_stack_ptr >= state_stack + STACKSIZE - 1)
        {
            goto overflow;
        }
        *++state_stack_ptr = state = main_tbl[n];
        *++vsp = lex_val;
        mychar = ( -1);

        if(errflag > 0)
        {
            --errflag;
        }
        goto loop;
    }
    if((n = rindex_tbl[state]) && (n += mychar) >= 0 && n <= TABLESIZE && check_tbl[n] == mychar)
    {
        n = main_tbl[n];
        goto reduce;
    }
    if(errflag)
    {
        goto inrecovery;
    }

    printf("error: 语法错误!\n");

    ++nerrs;

inrecovery:
    if(errflag < 3)
    {
        errflag = 3;
        for(;;)
        {
            if((n = sindex_tbl[ *state_stack_ptr]) && (n += ERRCODE) >= 0 && n <= TABLESIZE && check_tbl[n] == ERRCODE)
            {
                if(state_stack_ptr >= state_stack + STACKSIZE - 1)
                {
                    goto overflow;
                }
                *++state_stack_ptr = state = main_tbl[n];
                *++vsp = lex_val;
                goto loop;
            }
            else
            {
                if(state_stack_ptr <= state_stack)
                {
                    goto abort;
                }
                --state_stack_ptr;
                --vsp;
            }
        }
    }
    else
    {
        if(mychar == 0)
        {
            goto abort;
        }

        mychar = ( -1);
        goto loop;
    }
reduce:


    m = len_tbl[n];
    val = vsp[1-m];
    switch(n)
    {
    case 1:
        {
            printf("* 运算结果: %g\n", vsp[-1]);
        }
        break;
    case 4:
        {
            printf("error: 请重新输入: ");
            errok;
        }
        break;
    case 5:
        {
            val = vsp[-2] + vsp[0];
        }
        break;
    case 6:
        {
            val = vsp[-2] - vsp[0];
        }
        break;
    case 8:
        {
            val = vsp[-2] *vsp[0];
        }
        break;
    case 9:
        {
            val = vsp[-2] / vsp[0];
        }
        break;
    case 11:
        {
            val = vsp[-1];
        }
        break;
    case 12:
        {
            val = vsp[-1];
            printf("error: 缺少')'\n");
            errok;
        }
        break;
    case 13:
        {
            val = - vsp[0];
        }
        break;

    }

    state_stack_ptr -= m;
    state = *state_stack_ptr;
    vsp -= m;
    m = lhs_tbl[n];

    if(state == 0 && m == 0)
    {
        state = FINAL;
        *++state_stack_ptr = FINAL;
        *++vsp = val;
        if(mychar < 0)
        {
            if((mychar = lex()) < 0)
            {
                mychar = 0;
            }
        }
        if(mychar == 0)
        {
            goto accept;
        }
        goto loop;
    }
    if((n = gindex_tbl[m]) && (n += state) >= 0 && n <= TABLESIZE && check_tbl[n] == state)
    {
        state = main_tbl[n];
    }
    else
    {
        state = dgoto_tbl[m];
    }

    if(state_stack_ptr >= state_stack + STACKSIZE -1)
    {
        goto overflow;
    }
    *++state_stack_ptr = state;
    *++vsp = val;
    goto loop;


overflow:
    printf("error: 堆栈溢出!\n");
abort:
    return (1);
accept:
    return (0);
}

int main(void)
{
    char currch;
    int cptr;

    printf("======== LALR(1) 表达式计算器========\n\n");

    while(1)
    {
        printf("* 请输入表达式: ");

        cptr = 0;

        do
        {
            currch = getchar();
            if(currch == '#') return 0;

            formula[cptr] = currch;
            cptr++;
        } while(currch != '\n');

        formula[cptr] = 0;

        parse();
    }
    return 0;
}


[ 本帖最后由 flyue 于 2011-2-12 20:18 编辑 ]
搜索更多相关主题的帖子: 计算器 表达式 源代码 
2011-02-12 19:57
cnfarer
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:179
帖 子:3330
专家分:21157
注 册:2010-1-19
收藏
得分:0 
!!

★★★★★为人民服务★★★★★
2011-02-12 20:04
flyue
Rank: 10Rank: 10Rank: 10
来 自:江南西道
等 级:贵宾
威 望:19
帖 子:3465
专家分:1563
注 册:2006-6-20
收藏
得分:0 
天书......

以上代码使用 lex&yacc 生成

天之道,损有余而补不足.人之道则不然,损不足以奉有余.孰能有余以奉天下,唯有道者.
2011-02-12 20:53
flyue
Rank: 10Rank: 10Rank: 10
来 自:江南西道
等 级:贵宾
威 望:19
帖 子:3465
专家分:1563
注 册:2006-6-20
收藏
得分:0 
哎…我发的东西没人看啊~

天之道,损有余而补不足.人之道则不然,损不足以奉有余.孰能有余以奉天下,唯有道者.
2011-02-12 22:48
huangapple
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
帖 子:545
专家分:1790
注 册:2010-12-30
收藏
得分:0 

勤能补拙,熟能生巧!
2011-02-12 22:52
点线面
Rank: 8Rank: 8
来 自:NO.-1
等 级:蝙蝠侠
帖 子:525
专家分:980
注 册:2011-1-3
收藏
得分:0 
用了不少goto,程序可读性降低不少。

小代码,大智慧
2011-02-12 22:53
水中无月
Rank: 1
等 级:新手上路
帖 子:190
专家分:9
注 册:2008-6-17
收藏
得分:0 
不错哦,支持楼主写自己的编译器

十里平湖霜满天,寸寸青丝愁华年,对月形单望相互,只羡鸳鸯不羡仙.
2011-02-12 22:56
baobaoisme
Rank: 7Rank: 7Rank: 7
来 自:AVATAR
等 级:黑侠
帖 子:260
专家分:506
注 册:2010-7-9
收藏
得分:0 
有点晕
2011-02-13 01:16
wujieru
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:1
帖 子:1108
专家分:1939
注 册:2010-10-9
收藏
得分:0 
看这些做什么 垃圾代码
2011-02-13 10:38
moonvs2010
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2010-9-18
收藏
得分:0 
加点注释啊,看着好费劲
2011-02-13 10:59
快速回复:. . . LALR(1) 表达式计算器 源代码
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.037610 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved