解析用户输入

上面的代码为波兰表达式创建了一个 mpc 的解析器,本节我们就使用它来解析用户的每一条输入。我们需要更改之前的 while 循环,使它不再只是简单的将用户输入的内容打印回去,而是传进我们的解析器进行解析。我们可以把之前的 printf 语句替换成下面的代码:

  1. /* Attempt to Parse the user Input */
  2. mpc_result_t r;
  3. if (mpc_parse("<stdin>", input, Lispy, &r)) {
  4. /* On Success Print the AST */
  5. mpc_ast_print(r.output);
  6. mpc_ast_delete(r.output);
  7. } else {
  8. /* Otherwise Print the Error */
  9. mpc_err_print(r.error);
  10. mpc_err_delete(r.error);
  11. }

我们调用了 mpc_parse 函数,并将 Lispy 解析器和用户输入 input 作为参数。它将解析的结果保存到 &r 中,如果解析成功,返回值为 1,失败为 0。对 r,我们使用了取地址符 &,关于这个符号我们会在后面的章节中讨论。

  • 解析成功时会产生一个内部结构,并保存到 routput 字段中。我们可以使用 mpc_ast_print 将这个结构打印出来,使用 mpc_ast_delete 将其删除。
  • 解析失败时则会将错误信息保存在 rerror 字段中。我们可以使用 mpc_err_print 将这个结构打印出来,使用 mpc_err_delete 将其删除。

重新编译程序,尝试不同的输入,看看程序的返回信息是什么。正常情况下返回值应该如下所示:

  1. Lispy Version 0.0.0.0.2
  2. Press Ctrl+c to Exit
  3. lispy> + 5 (* 2 2)
  4. >
  5. regex
  6. operator|char:1:1 '+'
  7. expr|number|regex:1:3 '5'
  8. expr|>
  9. char:1:5 '('
  10. operator|char:1:6 '*'
  11. expr|number|regex:1:8 '2'
  12. expr|number|regex:1:10 '2'
  13. char:1:11 ')'
  14. regex
  15. lispy> hello
  16. <stdin>:1:1: error: expected whitespace, '+', '-', '*' or '/' at 'h'
  17. lispy> / 1dog
  18. <stdin>:1:4: error: expected one of '0123456789', whitespace, '-', one or more of one of '0123456789', '(' or end of input at 'd'
  19. lispy>

编译的时候得到一个错误:<stdin>:1:1: error: Parser Undefined!

出现这个错误说明传给 mpca_lang 函数的语法规则存在错误,请仔细检查一下出错的地方。