■ 四則演算インタプリタ
/*
* interp.c : 四則演算インタプリタ
*
* Copyright (c) 2001, 2002 AOK.
*
* 2001/10/26 - 初版
* 2002/03/22 - 2版
*
* 再帰下降解析を使った簡単なインタプリタです。加減乗除
* [+,-,*,/]と括弧[(,)]と正負符号(+,-)が使えます。
*
* 例: 7*6+5*(8-4)/2+1 【=53】
*
*/
#include <stdio.h>
#include <stdlib.h>
#define isspace(x) ((x==' ')||(x=='\t'))
#define isdigit(x) ((x>='0')&&(x<='9'))
#define isop(x) ((x=='+')||(x=='-')||(x=='*')||(x=='/')||(x=='(')||(x==')'))
char buf[127], sym;
int num, pc, err;
int addsub(void);
/* デバグ用 */
void debug(const char *s)
{
printf("* %-11s sym=%c num=%d\n", s, sym, num);
}
/* エラー表示 */
void error(const char *s)
{
fprintf(stderr, "[%02d:%c] %s\n", pc, sym, s);
sym = '?';
err++;
}
/* 1文字を得る */
void getnext(void)
{
sym = buf[pc++];
if (!isdigit(sym) && !isop(sym) && sym !='\0' && !isspace(sym))
error("不正な文字");
}
/* シンボルの種類の判定 */
void getsym(void)
{
sym = ' ';
while (isspace(sym)) getnext();
if (isdigit(sym)) {
num = 0;
while (isdigit(sym)) {
num = num * 10 + sym - '0';
getnext();
}
sym = '@';
pc--;
}
}
/* 因子 */
int factor(void)
{
int n;
debug("factor in");
if (sym == '(') {
getsym();
n = addsub();
if (sym != ')') error("')'がありません");
getsym();
} else if (sym == '@') {
n = num;
getsym();
} else {
error("式が正しくありません");
}
debug("factor out");
return n;
}
/* 乗除算 */
int muldiv(void)
{
int m, n;
debug("muldiv in");
n = factor();
while (sym == '*' || sym == '/') {
if (sym == '*') {
getsym();
n *= factor();
} else if (sym == '/') {
getsym();
if ((m = factor()) != 0)
n /= m;
else {
error("ゼロで除算できません");
break;
}
}
}
debug("muldiv out");
return n;
}
/* 加減算 */
int addsub(void)
{
int n;
debug("addsub in");
if (sym == '+') {
getsym();
n = muldiv();
} else if (sym == '-') {
getsym();
n = -muldiv();
} else {
n = muldiv();
}
while (sym == '+' || sym == '-') {
if (sym == '+') {
getsym();
n += muldiv();
} else if (sym == '-') {
getsym();
n -= muldiv();
}
}
debug("addsub out");
return n;
}
/* メインルーチン */
int main(void)
{
int r;
for (;;) {
buf[0] = '\0';
num = pc = err = 0;
putchar('>');
gets(buf);
if (buf[0]=='\0') break;
getsym();
r = addsub();
if (sym != '\0') /* 式を最後まで評価したかのチェック */
error("式が正しくありません");
if (err) fprintf(stderr, "%d個のエラーが発生\n", err);
else printf("%s=%d\n", buf, r);
}
return 0;
}