开发编程语言(八):表达式的执行 eval.c

随笔 2016-10-27

起步

表达式的解析是运行的核心,表达式又可以嵌套,func(4+8) || (a == 8 -3 && b != "s")像这个包含了函数表达式,加法,立即数, 布尔运算,字符串比较等。

从头看

从语法分析看是如何定义一个表达式的(部分省略):

expression
        : logical_or_expression
        | IDENTIFIER ASSIGN expression
        ;
logical_or_expression
        : logical_and_expression
        | logical_or_expression LOGICAL_OR logical_and_expression
        ;

relational_expression
        : additive_expression
        | relational_expression GT additive_expression
        ;
additive_expression
        : multiplicative_expression
        | additive_expression ADD multiplicative_expression
        | additive_expression SUB multiplicative_expression
        ;
multiplicative_expression
        | multiplicative_expression MUL unary_expression
        | multiplicative_expression DIV unary_expression
        | multiplicative_expression MOD unary_expression
        ;

primary_expression
        : IDENTIFIER LP argument_list RP
        | IDENTIFIER LP RP
        | LP expression RP
        | IDENTIFIER
        | INT_LITERAL
        | DOUBLE_LITERAL
        | STRING_LITERAL
        | TRUE_O
        | FALSE_O
        | NULL_O
        ;

利用文法的顺序可以定义出运算符之间的优先级,expression: logical_or_expression和后面logical_or_expression: logical_and_expression可以出来表达式的优先级低于 表达式

表达式的运行

运行也是采用统一的入口

ORG_Value org_eval_expression(ORG_Interpreter *inter, LocalEnvironment *env, Expression *expr) {
    return eval_expression(inter, env, expr);
}

下一层的执行函数:

// 运行表达式 或者表达式结果
static ORG_Value eval_expression(ORG_Interpreter *inter, LocalEnvironment *env, Expression *expr) {
    ORG_Value v;
    switch (expr->type) {
        case BOOLEAN_EXPRESSION:
            v = eval_boolean_expression(expr->u.boolean_value);
            break;
        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 STRING_EXPRESSION:
            v = eval_string_expression(inter, expr->u.string_value);
            break;
        case IDENTIFIER_EXPRESSION:
            v = eval_identifier_expression(inter, env, expr);
            break;
        case ASSIGN_EXPRESSION:
            v = eval_assign_expression(inter, env, expr->u.assign_expression.variable, expr->u.assign_expression.operand);
            break;
        case ADD_EXPRESSION:        /* fail */
        case SUB_EXPRESSION:        /* fail */
        case MUL_EXPRESSION:        /* fail */
        case DIV_EXPRESSION:        /* fail */
        case MOD_EXPRESSION:        /* fail */
        case EQ_EXPRESSION: /* fail */
        case NE_EXPRESSION: /* fail */
        case GT_EXPRESSION: /* fail */
        case GE_EXPRESSION: /* fail */
        case LT_EXPRESSION: /* fail */
        case LE_EXPRESSION:
            v = org_eval_binary_expression(inter, env, expr->type, expr->u.binary_expression.left, expr->u.binary_expression.right);
            break;
        case LOGICAL_AND_EXPRESSION:/* FALLTHRU */
        case LOGICAL_OR_EXPRESSION:
            v = eval_logical_and_or_expression(inter, env, expr->type, expr->u.binary_expression.left, expr->u.binary_expression.right);
            break;
        case MINUS_EXPRESSION:
            v = org_eval_minus_expression(inter, env, expr->u.minus_expression);
            break;
        case FUNCTION_CALL_EXPRESSION:
            v = eval_function_call_expression(inter, env, expr);
            break;
        case NULL_EXPRESSION:
            v = eval_null_expression();
            break;
        case BIG_DATA_EXPRESSION:
            // 这里需要加eval_bignum_expression()
            v = eval_bignum_expression(inter, env, expr);
            break;
        case EXPRESSION_TYPE_COUNT_PLUS_1:  /* FALLTHRU */
        default:
            //DBG_panic(("bad case. type..%d\n", expr->type));
            //printf("");
            break;
    }
    return v;
}

采用switch对不同表达式类型做不一样的运算,弱类型语言,用了一个union来保存它的类型,不是指数据的基本类型,而是语义上的类型。

二元表达式

这边我将二元表达式(+ - * / > < == !=)合在一个函数里org_eval_binary_expression()处理。

ORG_Value org_eval_binary_expression(ORG_Interpreter *inter, LocalEnvironment *env,
                                     ExpressionType op, Expression *left, Expression *right) {

    ORG_Value left_val;
    ORG_Value right_val;
    ORG_Value result;

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

    /**
     * 对于加法运算
     * 1 整数 + 整数   返回整数
     * 2 实数 + 实数   返回实数
     * 3 整数 + 实数   左边转换为实数
     * 4 实数 + 整数   右边转换为实数
     * 5 字符串 + 字符串 返回连接后的字符串
     * 6 字符串 + 整数   右边转换为字符串
     * 7 字符串 + 实数    右边转换为字符串
     * 8 字符串 + 布尔    右边转换为true或false的字符串
     * 9 字符串 + null    右边转换为null的字符串
     */

    //省略代码
}

布尔运算的短路求值

二元表达式格式:expression op expression,表达式左侧本身也是表达式,所以又调用了表达式的执行函数left_val = eval_expression(inter, env, left);,有的递归的意思。二元运算中,要能支持短路求值。所以就要运行左侧表达式后对操作符进行判断:

    left_val = eval_expression(inter, env, left);
    if (op == LOGICAL_AND_EXPRESSION) {
        if (!left_val.u.boolean_value) {
            result.u.boolean_value = ORG_FALSE;
            return result;//短路求值
        }
    } else if (op == LOGICAL_OR_EXPRESSION) {
        if (left_val.u.boolean_value) {
            result.u.boolean_value = ORG_TRUE;
            return result;
        }
    }
    right_val = eval_expression(inter, env, right);
    result.u.boolean_value = right_val.u.boolean_value;
    return result;

形如左侧为,操作符,那就不用对右侧进行判断了,返回真。有了短路求值右侧的结果其实就是这个二元表达式的结果了。


本文由 hongweipeng 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

赏个馒头吧