加载函数
我们想构建一个函数,当传入文件名称时加载并对文件中表达式求值。为了实现这个函数,我们需要用到语法解析器,因为我们需要其来读取文件内容、解析表达式并求值。加载函数将依赖于名为Lispy
的mpc_parser*
。
因此,就像函数一样,我们需要前向声明解析器指针,并将其放置于文件的顶端。
mpc_parser_t* Number;
mpc_parser_t* Symbol;
mpc_parser_t* String;
mpc_parser_t* Comment;
mpc_parser_t* Sexpr;
mpc_parser_t* Qexpr;
mpc_parser_t* Expr;
mpc_parser_t* Lispy;
我们的load
函数就像任何其他内置函数一样。其首先需要检查输入参数是否为单个字符串。然后我们调用mpc_parse_contents
函数通过语法解析器读入文件的内容。就像mpc_parse
一样,它将文件内容解析为一些其中包含抽象语法树或错误的mpc_result
对象。
与命令提示符略有不同,在成功解析文件时,我们不应将其视为一个表达式。在输入文件时,我们让用户列出多个表达式并对所有表达式单独求值。为了实现这个需求,我们需要遍历文件内容中的每个表达式并逐个进行求值。如果出现任何错误,我们应该打印错误信息并继续。
若解析出错,我们将提取错误信息并返回一个error型lval
。若解析正确,则此内置函数的返回值为一个空表达式。完整代码如下。
lval* builtin_load(lenv* e, lval* a) {
LASSERT_NUM("load", a, 1);
LASSERT_TYPE("load", a, 0, LVAL_STR);
/* Parse File given by string name */
mpc_result_t r;
if (mpc_parse_contents(a->cell[0]->str, Lispy, &r)) {
/* Read contents */
lval* expr = lval_read(r.output);
mpc_ast_delete(r.output);
/* Evaluate each Expression */
while (expr->count) {
lval* x = lval_eval(e, lval_pop(expr, 0));
/* If Evaluation leads to error print it */
if (x->type == LVAL_ERR) { lval_println(x); }
lval_del(x);
}
/* Delete expressions and arguments */
lval_del(expr);
lval_del(a);
/* Return empty list */
return lval_sexpr();
} else {
/* Get Parse Error as String */
char* err_msg = mpc_err_string(r.error);
mpc_err_delete(r.error);
/* Create new error message using it */
lval* err = lval_err("Could not load Library %s", err_msg);
free(err_msg);
lval_del(a);
/* Cleanup and return error */
return err;
}
}
当前内容版权归 NoahDragon 译 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 NoahDragon 译 .