1  拡張(小松 裕君の解答)

初等関数を導入する方法としては,文法上,小松君の方法が参考になる。また,この部分は多くの人が よい考察をしていた。

sin,cos,tanと累乗(^)を扱えるようにした。大まかな流れとしては、

  1. 字句解析の改良
  2. 構文解析の改良
  3. ヘッダファイルに宣言を追加
  4. 解析木作成を改良
  5. 式評価を改良
となる。

1.1  字句解析の改良

sinやcosという文字がきたときトークンとして返す。
< INITIAL > ßin"   return SIN; < INITIAL > "cos"   return COS; < INITIAL > "tan"   return TAN; < INITIAL > "^"    return POW;

1.2  構文解析の改良

sinやcosは「-」などと同じく前置式と考える。累乗は後置式なので新たに後置式という構文規則を追加し、下のようにする。

< 関連性のない式 > : = < 後置式 > | < 前置式 > < 前置式 > : = ßin" < 後置式 > | "cos" < 後置式 > | "tan" < 後置式 > | "-" < 後置式 > < 後置式 > : = < 一次式 > | < 一次式 > "^" < 後置式 >

それをBisonの定義にし、アクションを追加すると

type  < expression >  prefix_expressionunary_expression  : postfix_expression  | prefix_expression  ;prefix_expression  : SIN postfix_expression  {    $$ = clc_create_sin_expression($2);  }  | COS postfix_expression  {    $$ = clc_create_cos_expression($2);  }  | TAN postfix_expression  {    $$ = clc_create_tan_expression($2);  }  | SUB unary_expression  {    $$ = clc_create_minus_expression($2);  }  ;postfix_expression  : primary_expression  | primary_expression POW postfix_expression  {    $$ = clc_create_binary_expression(POW_EXPRESSION, $1, $3);  }  ;

のようになる。

1.3  ヘッダファイルに宣言を追加

関数の宣言をcalc.hに追加

typedef enum {  ...  POW_EXPRESSION,  SIN_EXPRESSION,   COS_EXPRESSION,   TAN_EXPRESSION,   ...} ExpressionType;Expression *clc_create_sin_expression(Expression *operand);Expression *clc_create_cos_expression(Expression *operand);Expression *clc_create_tan_expression(Expression *operand);Value clc_eval_sin_expression(LocalEnvironment *env, Expression *operand);Value clc_eval_cos_expression(LocalEnvironment *env, Expression *operand);Value clc_eval_tan_expression(LocalEnvironment *env, Expression *operand);

1.4  解析木作成に追加

(sin)Expression *clc_create_sin_expression(Expression *operand){  if (operand- > type = = INT_EXPRESSION   || operand- > type = = DOUBLE_EXPRESSION) {    Value  v;    v = clc_eval_sin_expression(NULL, operand);    /* Notice! Overwriting operand expression. */    *operand = convert_value_to_expression(&v);    return operand;  } else {    Expression *exp;    exp = clc_alloc_expression(SIN_EXPRESSION);    exp- > u.minus_expression = operand;    return exp;  }}
(cos)Expression *clc_create_cos_expression(Expression *operand){  if (operand- > type = = INT_EXPRESSION   || operand- > type = = DOUBLE_EXPRESSION) {    Value  v;    v = clc_eval_cos_expression(NULL, operand);    /* Notice! Overwriting operand expression. */    *operand = convert_value_to_expression(&v);    return operand;  } else {    Expression *exp;    exp = clc_alloc_expression(COS_EXPRESSION);    exp- > u.minus_expression = operand;    return exp;  }}

(tan)Expression *clc_create_tan_expression(Expression *operand){  if (operand- > type = = INT_EXPRESSION   || operand- > type = = DOUBLE_EXPRESSION) {    Value  v;    v = clc_eval_tan_expression(NULL, operand);    /* Notice! Overwriting operand expression. */    *operand = convert_value_to_expression(&v);    return operand;  } else {    Expression *exp;    exp = clc_alloc_expression(TAN_EXPRESSION);    exp- > u.minus_expression = operand;    return exp;  }}

1.5  式評価を改良

累乗の場合は整数または小数となるのでそれぞれの評価関数に追記します。

 
static int
eval_binary_int(ExpressionType operator, int left, int right)
{
    ...
      case POW_EXPRESSION: 
    result = (int)pow(left,right);
    break;
    ...
      case MINUS_EXPRESSION:    /* FALLTHRU */
      case SIN_EXPRESSION:  /* FALLTHRU */ /* sin追加 */
      case COS_EXPRESSION:  /* FALLTHRU */ /* cos追加 */
      case TAN_EXPRESSION:  /* FALLTHRU */ /* tan追加 */
    ...
}

static void
eval_binary_double(ExpressionType operator, double left, double right,
           Value *result)
{
    if (operator == ADD_EXPRESSION || operator == SUB_EXPRESSION
     || operator == MUL_EXPRESSION || operator == DIV_EXPRESSION
     || operator == MOD_EXPRESSION || operator == POW_EXPRESSION) { 
        result->type = DOUBLE_VALUE;
    }
    ...
      case POW_EXPRESSION: 
    result->u.double_value = pow(left, right);
    break;
    ...
      case MINUS_EXPRESSION:    /* FALLTHRU */
      case SIN_EXPRESSION:  /* FALLTHRU */ 
      case COS_EXPRESSION:  /* FALLTHRU */ 
      case TAN_EXPRESSION:  /* FALLTHRU */ 
   ...
}




続いてsin,cos,tanの各評価関数を追加。

Value
clc_eval_sin_expression(LocalEnvironment *env, Expression *operand)
{
    Value   operand_val;
    Value   result;

    operand_val = eval_expression(env, operand);
    if (operand_val.type == INT_VALUE) {
        result.type = DOUBLE_VALUE;
        result.u.double_value = sin(operand_val.u.int_value);
    } else {
        DBG_assert(operand_val.type == DOUBLE_VALUE,
           ("operand_val.type..%d", operand_val.type));
        result.type = DOUBLE_VALUE;
        result.u.double_value = sin(operand_val.u.double_value);
    }
    return result;
}


Value
clc_eval_cos_expression(LocalEnvironment *env, Expression *operand)
{
    Value   operand_val;
    Value   result;

    operand_val = eval_expression(env, operand);
    if (operand_val.type == INT_VALUE) {
        result.type = DOUBLE_VALUE;
        result.u.double_value = cos(operand_val.u.int_value);
    } else {
        DBG_assert(operand_val.type == DOUBLE_VALUE,
           ("operand_val.type..%d", operand_val.type));
        result.type = DOUBLE_VALUE;
        result.u.double_value = cos(operand_val.u.double_value);
    }
    return result;
}


Value
clc_eval_tan_expression(LocalEnvironment *env, Expression *operand)
{
    Value   operand_val;
    Value   result;

    operand_val = eval_expression(env, operand);
    if (operand_val.type == INT_VALUE) {
        result.type = DOUBLE_VALUE;
        result.u.double_value = tan(operand_val.u.int_value);
    } else {
        DBG_assert(operand_val.type == DOUBLE_VALUE,
           ("operand_val.type..%d", operand_val.type));
        result.type = DOUBLE_VALUE;
        result.u.double_value = tan(operand_val.u.double_value);
    }
    return result;
}

static Value
eval_expression(LocalEnvironment *env, Expression *expr)
{
    ...
      case POW_EXPRESSION:  /* FALLTHRU */ 
    ...
      case MINUS_EXPRESSION:
    v = clc_eval_minus_expression(env, expr->u.minus_expression);
    break;
      case SIN_EXPRESSION: 
    v = clc_eval_sin_expression(env, expr->u.minus_expression);
    break;
      case COS_EXPRESSION: 
    v = clc_eval_cos_expression(env, expr->u.minus_expression);
    break;
      case TAN_EXPRESSION: 
    v = clc_eval_tan_expression(env, expr->u.minus_expression);
    break;
    ...
}





2  for文と複素数を導入した例(森田 和樹君)

for文は前橋氏のwhile文の定義を見れば,簡単に導入できることがわかる。複素数は, LAPACKの複素行列の定義を考えると,森田君の複素数(普通こうやるが)において Complex *complex_matrixにするのが正解となる。複素行列まで扱った人は いなかったようであるが。初等関数の導入法は,mfcalcの影響が見られる(大石のコメント)。

2.1  プログラム(以下森田君)

基本的に変更箇所を掲載します

2.1.1  calc.l

虚数単位の'i'を追加しています

%{
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) (result = my_yyinput(buf, max_size))
#include <stdio.h>
#include <string.h>
#include <readline/readline.h>
#include "DBG.h"
#include "calc.h"
#include "y.tab.h"

static int my_yyinput(char *buf, int max_size);
%}
%start COMMENT
%%
<INITIAL>"define"	return DEFINE;
<INITIAL>"if"		return IF;
<INITIAL>"else"		return ELSE;
<INITIAL>"while"	return WHILE;
<INITIAL>"for"		return FOR;
<INITIAL>"i"		return I;
<INITIAL>"("		return LP;
<INITIAL>")"		return RP;
<INITIAL>"{"		return LC;
<INITIAL>"}"		return RC;
<INITIAL>";"		return SEMICOLON;
<INITIAL>","		return COMMA;
<INITIAL>"="		return ASSIGN;
<INITIAL>"=="		return EQ;
<INITIAL>"!="		return NE;
<INITIAL>">"		return GT;
<INITIAL>">="		return GE;
<INITIAL>"<"		return LT;
<INITIAL>"<="		return LE;
<INITIAL>"+"		return ADD;
<INITIAL>"-"		return SUB;


以下は前橋氏と同じなので省略

2.1.2  calc.y

構文規則としてFor文と、さらに複素数の処理のための部分を加えています。

%{
#include <stdio.h>
#include "calc.h"
#define YYDEBUG 1
%}
%union {
    char		*identifier;
    ParameterList	*parameter_list;
    Expression		*expression;
}
%token <expression>	INT_LITERAL
%token <expression>	DOUBLE_LITERAL
%token <identifier>	IDENTIFIER
%token DEFINE IF ELSE WHILE FOR I LP RP LC RC SEMICOLON COMMA ASSIGN
	EQ NE GT GE LT LE ADD SUB MUL DIV MOD
%type   <parameter_list> parameter_list
%type   <expression> expression expression_list
        equality_expression relational_expression
	additive_expression multiplicative_expression
	unary_expression postfix_expression primary_expression
	if_expression while_expression for_expression
%%
translation_unit
	: definition_or_expression
	| translation_unit definition_or_expression
	;

省略

primary_expression
	: IDENTIFIER LP expression_list RP
	{
	    $$ = clc_create_function_call_expression($1, $3);
	}
	| IDENTIFIER LP RP
	{
	    $$ = clc_create_function_call_expression($1, NULL);
	}
	| if_expression
	| while_expression
	| for_expression
	| LP expression RP
	{
	    $$ = $2;
	}
	| IDENTIFIER
	{
	    $$ = clc_create_identifier_expression($1);
	}
	| INT_LITERAL I
	{
	    $$ = clc_create_complex_expression($1);
	}
	| DOUBLE_LITERAL I
	{
	    $$ = clc_create_complex_expression($1);
	}
	| INT_LITERAL
	| DOUBLE_LITERAL
	;
if_expression
	: IF expression LC expression_list RC
	{
	    $$ = clc_create_if_expression($2, $4, NULL);
	}
	| IF expression LC expression_list RC ELSE LC expression_list RC
	{
	    $$ = clc_create_if_expression($2, $4, $8);
	}
	;
while_expression
	: WHILE expression LC expression_list RC
	{
	    $$ = clc_create_while_expression($2, $4);
	}
	;
for_expression
	: FOR LP expression SEMICOLON expression SEMICOLON expression RP LC expression_list RC
	{
	    $$ = clc_create_for_expression($3, $5, $7, $10);
	}
	;
%%

2.1.3  calc.h

For文、複素数、数学関数のための構造体を追加しています。

#ifndef PRIVATE_CALC_H_INCLUDED
#define PRIVATE_CALC_H_INCLUDED
#include <stdio.h>
#include <setjmp.h>
#include "MEM.h"
#include "CLC.h"

#define smaller(a, b) ((a) < (b) ? (a) : (b))
#define larger(a, b) ((a) > (b) ? (a) : (b))

struct symrec
{
  char *name;  
  double (*fnctptr)();  
  struct symrec *next;   
};

typedef struct symrec symrec;

extern symrec *sym_table;

symrec *putsym ();
symrec *getsym ();

省略

typedef enum {
    INT_EXPRESSION = 1,
    DOUBLE_EXPRESSION,
    COMPLEX_EXPRESSION,
    IDENTIFIER_EXPRESSION,
    EXPRESSION_LIST_EXPRESSION,
    ASSIGN_EXPRESSION,
    ADD_EXPRESSION,
    SUB_EXPRESSION,
    MUL_EXPRESSION,
    DIV_EXPRESSION,
    MOD_EXPRESSION,
    EQ_EXPRESSION,
    NE_EXPRESSION,
    GT_EXPRESSION,
    GE_EXPRESSION,
    LT_EXPRESSION,
    LE_EXPRESSION,
    MINUS_EXPRESSION,
    IF_EXPRESSION,
    WHILE_EXPRESSION,
    FOR_EXPRESSION,
    FUNCTION_CALL_EXPRESSION,
    EXPRESSION_TYPE_NUM
} ExpressionType;

省略

typedef struct {
    Expression	*condition1;
    Expression	*condition2;
    Expression	*condition3;
    Expression	*expression_list;
} ForExpression;

typedef struct {
    char	*identifier;
    Expression	*argument;
} FunctionCallExpression;

typedef struct {
    double	r;
    double	i;
} Complex;

struct Expression_tag {
    ExpressionType type;
    union {
	int			int_value;
	double			double_value;
	Complex			complex_value;
	char			*identifier;
	ExpressionList		expression_list;
	AssignExpression	assign_expression;
	BinaryExpression	binary_expression;
	Expression		*minus_expression;
	IfExpression		if_expression;
	FunctionCallExpression	function_call_expression;
	WhileExpression		while_expression;
	ForExpression		for_expression;
    } u;
};

typedef struct ParameterList_tag {
    char	*name;
    struct ParameterList_tag *next;
} ParameterList;

typedef struct FunctionDefinition_tag {
    char		*name;
    ParameterList	*parameter;
    Expression		*expression_list;
    MEM_Storage		storage;
    struct FunctionDefinition_tag	*next;
} FunctionDefinition;

typedef enum {
    INT_VALUE = 1,
    DOUBLE_VALUE,
    COMPLEX_VALUE,
    NULL_VALUE
} ValueType;

typedef struct {
    ValueType	type;
    union {
	int	int_value;
	double	double_value;
	Complex	complex_value;
    } u;
} Value;

省略


2.1.4  create.c

複素数とFor文のための関数を追加


Expression *
clc_create_complex_expression(Expression *operand)
{
    if (operand->type == INT_EXPRESSION) {
	operand->u.complex_value.i = operand->u.int_value;
    } else {
	operand->u.complex_value.i = operand->u.double_value;
    }
    operand->u.complex_value.r = 0;
    operand->type = COMPLEX_EXPRESSION;
    return operand;
}

Expression *
clc_create_for_expression(Expression *condition1,
			    Expression *condition2,
			    Expression *condition3,
			    Expression *expression)
{
    Expression	*exp;

    exp = clc_alloc_expression(FOR_EXPRESSION);
    exp->u.for_expression.condition1 = condition1;
    exp->u.for_expression.condition2 = condition2;
    exp->u.for_expression.condition3 = condition3;
    exp->u.for_expression.expression_list = expression;

    return exp;
}


2.1.5  eval.c

いくつかの関数をFor文、複素数のために追加、書き換えを行い、 関数呼び出しの際に登録された数学関数と一致すればその値を返すようにする。

#include <stdio.h>
#include <math.h>
#include "MEM.h"
#include "DBG.h"
#include "calc.h"

static Value
eval_int_expression(int int_value)
{
    Value	v;

    v.type = INT_VALUE;
    v.u.int_value = int_value;

    return v;
}

static Value
eval_double_expression(double double_value)
{
    Value	v;

    v.type = DOUBLE_VALUE;
    v.u.double_value = double_value;

    return v;
}

static Value
eval_complex_expression(Complex complex_value)
{
    Value	v;

    v.type = COMPLEX_VALUE;
    v.u.complex_value.r = complex_value.r;
    v.u.complex_value.i = complex_value.i;

    return v;
}

省略

static void
eval_binary_complex(ExpressionType operator, Complex left, Complex right,
		   Value *result)
{
    if (operator == ADD_EXPRESSION || operator == SUB_EXPRESSION
	|| operator == MUL_EXPRESSION ) {
	result->type = COMPLEX_VALUE;
    }
    switch (operator) {
      case INT_EXPRESSION:	/* FALLTHRU */
      case DOUBLE_EXPRESSION:	/* FALLTHRU */
      case IDENTIFIER_EXPRESSION:	/* FALLTHRU */
      case EXPRESSION_LIST_EXPRESSION:	/* FALLTHRU */
      case ASSIGN_EXPRESSION:
	DBG_assert(0, ("bad case...%d", operator));
	break;
      case ADD_EXPRESSION:
	result->u.complex_value.r = left.r + right.r;
	result->u.complex_value.i = left.i + right.i;
	break;
      case SUB_EXPRESSION:
	result->u.complex_value.r = left.r - right.r;
	result->u.complex_value.i = left.i - right.i;
	break;
      case MUL_EXPRESSION:
	result->u.complex_value.r = left.r * right.r - left.i * right.i;
	result->u.complex_value.i = left.i * right.r + left.r * right.i;
	break;
      case DIV_EXPRESSION:
      case MOD_EXPRESSION:
      case EQ_EXPRESSION:
      case NE_EXPRESSION:
      case GT_EXPRESSION:
      case GE_EXPRESSION:
      case LT_EXPRESSION:
      case LE_EXPRESSION:
      case MINUS_EXPRESSION:	/* FALLTHRU */
      case IF_EXPRESSION:	/* FALLTHRU */
      case WHILE_EXPRESSION:	/* FALLTHRU */
      case FOR_EXPRESSION:	/* FALLTHRU */
      case FUNCTION_CALL_EXPRESSION:	/* FALLTHRU */
      case EXPRESSION_TYPE_NUM:	/* FALLTHRU */
      default:
	DBG_assert(0, ("bad default...%d", operator));
    }
}

void
convert_value_to_complex(Value *v)
{
    if (v->type == INT_VALUE) {
	v->u.complex_value.r = v->u.int_value;
    } else {
	v->u.complex_value.r = v->u.double_value;
    }

    v->type = COMPLEX_EXPRESSION;
    v->u.complex_value.i = 0;
}

Value
clc_eval_binary_expression(LocalEnvironment *env,
			   ExpressionType operator,
			   Expression *left, Expression *right)
{
    Value	left_val;
    Value	right_val;
    Value	result;

    left_val = eval_expression(env, left);
    right_val = eval_expression(env, right);

    if (left_val.type == COMPLEX_VALUE
	&& right_val.type == COMPLEX_VALUE) {
	eval_binary_complex(operator,
			left_val.u.complex_value, right_val.u.complex_value,
			&result);
    } else if (left_val.type == COMPLEX_VALUE) {
	convert_value_to_complex(&right_val);
	eval_binary_complex(operator,
			left_val.u.complex_value, right_val.u.complex_value,
			&result);
    } else if (right_val.type == COMPLEX_VALUE) {
	convert_value_to_complex(&left_val);
	eval_binary_complex(operator,
			left_val.u.complex_value, right_val.u.complex_value,
			&result);
    } else if (left_val.type == INT_VALUE
	&& right_val.type == INT_VALUE) {
	result.type = INT_VALUE;
	result.u.int_value
	    = eval_binary_int(operator,
			      left_val.u.int_value, right_val.u.int_value);
    } else if (left_val.type == DOUBLE_VALUE
	       && right_val.type == DOUBLE_VALUE) {
	eval_binary_double(operator,
			   left_val.u.double_value, right_val.u.double_value,
			   &result);
    } else {
	/* cast int to double */
	if (left_val.type == INT_VALUE) {
	    left_val.u.double_value = left_val.u.int_value;
	} else {
	    right_val.u.double_value = right_val.u.int_value;
	}
	eval_binary_double(operator,
			   left_val.u.double_value, right_val.u.double_value,
			   &result);
    }
    return result;
}

Value
clc_eval_minus_expression(LocalEnvironment *env, Expression *operand)
{
    Value	operand_val;
    Value	result;

    operand_val = eval_expression(env, operand);
    if (operand_val.type == INT_VALUE) {
	result.type = INT_VALUE;
	result.u.int_value = -operand_val.u.int_value;
    } else if (operand_val.type == DOUBLE_VALUE) {
	DBG_assert(operand_val.type == DOUBLE_VALUE,
		   ("operand_val.type..%d", operand_val.type));
	result.type = DOUBLE_VALUE;
	result.u.double_value = -operand_val.u.double_value;
    } else {
	DBG_assert(operand_val.type == COMPLEX_VALUE,
		   ("operand_val.type..%d", operand_val.type));
	result.type = COMPLEX_VALUE;
	result.u.complex_value.r = -operand_val.u.complex_value.r;
	result.u.complex_value.i = -operand_val.u.complex_value.i;
    }
    return result;
}

省略

static Value
eval_for_expression(LocalEnvironment *env,
			Expression *condition1, Expression *condition2,
			Expression *condition3, Expression *expression_list)
{
    Value	condition_val;
    Value	result;


    condition_val = eval_expression(env, condition1);

    for (;;) {
	condition_val = eval_expression(env, condition2);
	if (condition_val.type != INT_VALUE) {
	    clc_runtime_error(BOOLEAN_EXPECTED_ERR, NULL);
	}
	if (!condition_val.u.int_value)
	    break;

	result = eval_expression(env, expression_list);
	condition_val = eval_expression(env, condition3);
    }
    return result;
}

static LocalEnvironment *
alloc_local_environment()
{
    LocalEnvironment *ret;

    ret = MEM_malloc(sizeof(LocalEnvironment));
    ret->variable = NULL;

    return ret;
}

static void
dispose_local_environment(LocalEnvironment *env)
{
    while (env->variable) {
	Variable	*temp;
	temp = env->variable->next;
	MEM_free(env->variable);
	env->variable = temp;
    }
    MEM_free(env);
}

static Value
eval_function_call_expression(LocalEnvironment *env,
			      char *identifier, Expression *argument)
{
    Value	result;
    Expression		*arg_p;
    ParameterList	*param_p;
    LocalEnvironment	*local_env;
    FunctionDefinition	*func;
    symrec *s;

    s = getsym (identifier);
    if (s != 0){
	result = eval_expression(env,
				  argument->u.expression_list.expression);
	if (result.type == INT_VALUE) {
	/* cast int to double */
		result.u.double_value = result.u.int_value;
	}
	result.u.double_value = (*(s->fnctptr))(result.u.double_value);
	result.type = DOUBLE_VALUE;

	return result;
    }

    func = clc_search_function(identifier);
    if (func == NULL) {
	clc_runtime_error(FUNCTION_NOT_FOUND_ERR, "name..%s\n", identifier);
    }
    local_env = alloc_local_environment();

    DBG_assert(argument->type == EXPRESSION_LIST_EXPRESSION,
	       ("type..%d\n", argument->type));

    for (arg_p = argument, param_p = func->parameter;
	 arg_p;
	 arg_p = arg_p->u.expression_list.next,
	 param_p = param_p->next) {
	Value arg_val;

	if (param_p == NULL) {
	    clc_runtime_error(ARGUMENT_TOO_MANY_ERR, NULL);
	}
	arg_val = eval_expression(env,
				  arg_p->u.expression_list.expression);
	clc_add_local_variable(local_env, param_p->name, &arg_val);
    }
    if (param_p) {
	clc_runtime_error(ARGUMENT_TOO_FEW_ERR, NULL);
    }
    result = eval_expression(local_env, func->expression_list);

    dispose_local_environment(local_env);

    return result;
}

static Value
eval_expression(LocalEnvironment *env, Expression *expr)
{
    Value	v;
    switch (expr->type) {
      case INT_EXPRESSION:
	v = eval_int_expression(expr->u.int_value);
	break;
      case DOUBLE_EXPRESSION:
	v = eval_double_expression(expr->u.double_value);
	break;
      case COMPLEX_EXPRESSION:
	v = eval_complex_expression(expr->u.complex_value);
	break;
      case IDENTIFIER_EXPRESSION:
	v = eval_identifier_expression(env, expr->u.identifier);
	break;
      case EXPRESSION_LIST_EXPRESSION:
	v = eval_expression_list_expression
	    (env,
	     expr->u.expression_list.expression,
	     expr->u.expression_list.next);
	break;
      case ASSIGN_EXPRESSION:
	v = eval_assign_expression(env,
				   expr->u.assign_expression.variable,
				   expr->u.assign_expression.operand);
	break;
      case ADD_EXPRESSION:	/* FALLTHRU */
      case SUB_EXPRESSION:	/* FALLTHRU */
      case MUL_EXPRESSION:	/* FALLTHRU */
      case DIV_EXPRESSION:	/* FALLTHRU */
      case MOD_EXPRESSION:	/* FALLTHRU */
      case EQ_EXPRESSION:	/* FALLTHRU */
      case NE_EXPRESSION:	/* FALLTHRU */
      case GT_EXPRESSION:	/* FALLTHRU */
      case GE_EXPRESSION:	/* FALLTHRU */
      case LT_EXPRESSION:	/* FALLTHRU */
      case LE_EXPRESSION:	/* FALLTHRU */
	v = clc_eval_binary_expression(env,
				       expr->type,
				       expr->u.binary_expression.left,
				       expr->u.binary_expression.right);
	break;
      case MINUS_EXPRESSION:
	v = clc_eval_minus_expression(env, expr->u.minus_expression);
	break;
      case IF_EXPRESSION:
	v = eval_if_expression(env,
			       expr->u.if_expression.condition,
			       expr->u.if_expression.then_expression,
			       expr->u.if_expression.else_expression);
	break;
      case WHILE_EXPRESSION:
	v = eval_while_expression(env,
				  expr->u.while_expression.condition,
				  expr->u.while_expression.expression_list);
	break;
      case FOR_EXPRESSION:
	v = eval_for_expression(env,
				  expr->u.for_expression.condition1,
				  expr->u.for_expression.condition2,
				  expr->u.for_expression.condition3,
				  expr->u.for_expression.expression_list);
	break;
      case FUNCTION_CALL_EXPRESSION:
	v = eval_function_call_expression
	    (env,
	     expr->u.function_call_expression.identifier,
	     expr->u.function_call_expression.argument);
	break;
      case EXPRESSION_TYPE_NUM:	/* FALLTHRU */
      default:
	DBG_assert(0, ("bad case. type..%d\n", expr->type));
    }
    return v;
}

void
clc_eval_expression(Expression *expression)
{
    Value		v;
    RuntimeError	error_id;

    if ((error_id = (RuntimeError)setjmp(clc_current_interpreter
					 ->error_recovery_environment)) == 0) {
	v = eval_expression(NULL, expression);
	if (clc_current_interpreter->input_mode == CLC_TTY_INPUT_MODE) {
	    if (v.type == INT_VALUE) {
		printf(">>%d\n", v.u.int_value);
	    } else if (v.type == DOUBLE_VALUE) {
		printf(">>%f\n", v.u.double_value);
	    } else if (v.type == COMPLEX_VALUE) {
		printf(">>%f + %f i\n", v.u.complex_value.r,
						v.u.complex_value.i);
	    } else {
		printf("<void>\n");
	    }
	}
    } else {
    }
    clc_reopen_current_storage();
}


2.1.6  main.c

数学関数の初期化などを追加
#include <stdio.h>
#include <math.h>
#include "CLC.h"
#include "calc.h"

int
main(int argc, char **argv)
{
    CLC_Interpreter	interpreter;

    printf("---- Wellcome ----");
    printf("\n");
    init_table ();

    interpreter = CLC_create_interpreter();
    CLC_interpret(interpreter, stdin, CLC_TTY_INPUT_MODE);
    CLC_dispose_interpreter(interpreter);

    return 0;
}

struct init
{
  char *fname;
  double (*fnct)();
};

struct init arith_fncts[]
= {
  "sin", sin,
  "cos", cos,
  "asin", asin,
  "acos", acos,
  "atan", atan,
  "ln", log,
  "exp", exp,
  "sqrt", sqrt,
  "tan",tan,
   0, 0
};


symrec *sym_table = (symrec *)0;

void init_table ()  
{
  int i;
  symrec *ptr;
  for (i = 0; arith_fncts[i].fname != 0; i++)
    {
      ptr = putsym (arith_fncts[i].fname);
      ptr->fnctptr = arith_fncts[i].fnct;
    }
}

symrec *
putsym (sym_name)
     char *sym_name;
{
  symrec *ptr;
  ptr = (symrec *) malloc (sizeof (symrec));
  ptr->name = (char *) malloc (strlen (sym_name) + 1);
  strcpy (ptr->name,sym_name);
  ptr->next = (struct symrec *)sym_table;
  sym_table = ptr;
  return ptr;
}

symrec *
getsym (sym_name)
     char *sym_name;
{
  symrec *ptr;
  for (ptr = sym_table; ptr != (symrec *) 0;
       ptr = (symrec *)ptr->next)
    if (strcmp (ptr->name,sym_name) == 0)
      return ptr;
  return 0;
}





File translated from TEX by TTH, version 2.80.
On 23 Aug 2001, 14:26.