其它解析

下一步的目标是处理函数声明。在Kaleidoscope中有两种函数声明方式,一是用"extern"声明外部函数,二是直接声明函数体。实现这部分的代码很简单直接,但是并不那么有趣:

  1. /// prototype
  2. /// ::= id '(' id* ')'
  3. static PrototypeAST *ParsePrototype() {
  4. if (CurTok != tok_identifier)
  5. return ErrorP("Expected function name in prototype");
  6.  
  7. std::string FnName = IdentifierStr;
  8. getNextToken();
  9.  
  10. if (CurTok != '(')
  11. return ErrorP("Expected '(' in prototype");
  12.  
  13. // Read the list of argument names.
  14. std::vector<std::string> ArgNames;
  15. while (getNextToken() == tok_identifier)
  16. ArgNames.push_back(IdentifierStr);
  17. if (CurTok != ')')
  18. return ErrorP("Expected ')' in prototype");
  19.  
  20. // success.
  21. getNextToken(); // eat ')'.
  22.  
  23. return new PrototypeAST(FnName, ArgNames);
  24. }

有了以上,记录一个声明的函数就很简单了——仅仅需要保存一个函数原型和函数体的一串表达式:

  1. /// definition ::= 'def' prototype expression
  2. static FunctionAST *ParseDefinition() {
  3. getNextToken(); // eat def.
  4. PrototypeAST *Proto = ParsePrototype();
  5. if (Proto == 0) return 0;
  6.  
  7. if (ExprAST *E = ParseExpression())
  8. return new FunctionAST(Proto, E);
  9. return 0;
  10. }

另外,我们也支持"extern"声明外部函数比如"sin"和"cos"或者用户定义的函数。"extern"与上面函数声明的区别仅仅在于没有具体的函数体:

  1. /// external ::= 'extern' prototype
  2. static PrototypeAST *ParseExtern() {
  3. getNextToken(); // eat extern.
  4. return ParsePrototype();
  5. }

最后,我们将让用户输入任意的外层表达式(top-level expressions),在运行的同时会计算出表达式结果。为此,我们需要处理无参数函数:

  1. /// toplevelexpr ::= expression
  2. static FunctionAST *ParseTopLevelExpr() {
  3. if (ExprAST *E = ParseExpression()) {
  4. // Make an anonymous proto.
  5. PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
  6. return new FunctionAST(Proto, E);
  7. }
  8. return 0;
  9. }

现在我们完成了所有的零碎的部分,让我们用一段短小的驱动代码来调用他们吧!