. . . 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 编辑 ]








