Kaleidoscope 语言: Parser and AST

类型定义 #

/// ExprAST - AST 的基类
class ExprAST {
public:
  virtual ~ExprAST() = default;
};

/// NumberExprAST - 数值类型的 AST 节点
class NumberExprAST : public ExprAST {
  double Val;

public:
  NumberExprAST(double Val) : Val(Val) {}
};


/// VariableExprAST - 变量类型的 AST 节点
class VariableExprAST : public ExprAST {
  std::string Name;

public:
  VariableExprAST(const std::string &Name) : Name(Name) {}
};

/// BinaryExprAST - 二元运算类型的 AST 节点
class BinaryExprAST : public ExprAST {
  char Op;
  std::unique_ptr<ExprAST> LHS, RHS;

public:
  BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,
                std::unique_ptr<ExprAST> RHS)
    : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
};

/// CallExprAST - 调用函数类型的 AST 节点
class CallExprAST : public ExprAST {
  std::string Callee;
  std::vector<std::unique_ptr<ExprAST>> Args;

public:
  CallExprAST(const std::string &Callee,
              std::vector<std::unique_ptr<ExprAST>> Args)
    : Callee(Callee), Args(std::move(Args)) {}
};


/// PrototypeAST - 函数原形定义类型的 AST 节点
class PrototypeAST {
  std::string Name;
  std::vector<std::string> Args;

public:
  PrototypeAST(const std::string &Name, std::vector<std::string> Args)
    : Name(Name), Args(std::move(Args)) {}

  const std::string &getName() const { return Name; }
};

/// FunctionAST - 函数定义类型的 AST 节点
class FunctionAST {
  std::unique_ptr<PrototypeAST> Proto;
  std::unique_ptr<ExprAST> Body;

public:
  FunctionAST(std::unique_ptr<PrototypeAST> Proto,
              std::unique_ptr<ExprAST> Body)
    : Proto(std::move(Proto)), Body(std::move(Body)) {}
};

Parser #

/// top ::= definition | external | expression | ';'
/// 在主循环中,我们就是解析,TOP 由 definition | externale | expresson | ';' 构成
static void MainLoop() {
    while (true) {
        fprintf(stderr, "ready> ");
        switch (CurTok) {
            case tok_eof:
                return;
            case ';': // ignore top-level semicolons.
                getNextToken();
                break;
            case tok_def:
                HandleDefinition();
                break;
            case tok_extern:
                HandleExtern();
                break;
            default:
                HandleTopLevelExpression();
                break;
        }
    }
}
// ParseTopLevelExpr 解释逻辑,是从 TOP 处理,也就是类似于 Main,
// PrototypeAST 特殊中 name 就是 "", 无参数
std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
    if (auto E = ParseExpression()) {
        // Make an anonymous proto.
        auto Proto = std::make_unique<PrototypeAST>("", std::vector<std::string>());
        return std::make_unique<FunctionAST>(std::move(Proto), std::move(E));
    }
    return nullptr;
}

不过这里 Parser 使用的是 Top-down parsing

需要解决一个优先级的问题 比如在 * 优先级高于 + ,比如在解析

1 + 2 * 3

因此在这里比较复杂的代码如下


// 确定优先级表格
// 1 is lowest precedence.
BinopPrecedence['<'] = 10;
BinopPrecedence['+'] = 20;
BinopPrecedence['-'] = 20;
BinopPrecedence['*'] = 40;  // highest.

/// binoprhs
///   ::= ('+' primary)*
/// ExprPrec 代表之前的优先级
// [EXAMPLE] 这里用 1 + 2 * 3 + 4 来解释一下
// [EXAMPLE] 第一次进这个函数, ExprPrec = 0, LHS = 1
std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
                                              std::unique_ptr<ExprAST> LHS) {
    // 一个 Loop 循环
    while (1) {
        // 得到当前 Token 的优先级,比如 - 就是 20, * 就是 40
        // [EXAMPLE] Token = + , TokPrec = 20
        int TokPrec = GetTokPrecedence();

        // 如果 前序的优先级比当前优先级高,就返回前序 AST 即可
        if (TokPrec < ExprPrec)
            return LHS;
        // 存一下当前的 Token 操作符
        int BinOp = CurTok;
        getNextToken();  // 继续读取下一个 Token

        // 解析 操作符后面的内容
        // [EXAMPLE] RHS = 2
        auto RHS = ParsePrimary();
        if (!RHS)
            return nullptr;
        // 获取下一个操作符的优先级
        // [EXAMPLE] NextToken = *, NextPrec = 40, 
        int NextPrec = GetTokPrecedence();

        // 如果下一个操作符的优先级比当前操作符的优先级高,就把这个 RHS 传入开辟一个新的 BinOpRHS 来解析
        // [EXAMPLE] 因为 NextPre 比 TokPrec 高,显然 2 应该和 后面的 * 进行组合,因此,把 2 传入 ParseBinOpRHS 解析 
        if (TokPrec < NextPrec) {
            RHS = ParseBinOpRHS(TokPrec+1, std::move(RHS));
            if (!RHS)
                return nullptr;
        }
        // Merge LHS/RHS.
        LHS = std::make_unique<BinaryExprAST>(BinOp, std::move(LHS),
                                              std::move(RHS));
    }  // loop around to the top of the while loop.
}

参考 #

comments powered by Disqus