1、Cale语言介绍
1.1、cale语言的语法形式(无二义性且非左递归文法)
1.2、cale语言示例
2、语义分析器
语义分析器负责遍历 AST 并检查语言的各种语义规则,例如:在使用变量之前必须声明变量,或者变量的类型必须在表达式中兼容。如果发现可以改进的情况,还可以输出警告。
2.1、语义分析类Sema定义
class Sema {
public:
bool semantic(AST *Tree);
};
2.2、Sema类方法实现
semantic方法负责检查传入的AST语法书是否存在语义错误。其中DeclCheck类通过访问者模式对AST树进行语义检查。
bool Sema::semantic(AST *Tree) {
if (!Tree)
return false;
DeclCheck Check;
// 当前AST树接受访问者Check的访问
Tree->accept(Check);
return Check.hasError();
}
2.3、DeclCheck类实现
class DeclCheck : public ASTVisitor {
llvm::StringSet<> Scope; // 记录形参列表名称
bool HasError; // 记录语义检查时是否存在错误
// 错误类型:表达式使用未命名的形参、同名形参被指定两种错误
enum ErrorType { Twice, Not };
// 打印错误信息
void error(ErrorType ET, llvm::StringRef V) {
llvm::errs() << "Variable " << V << " "
<< (ET == Twice ? "already" : "not")
<< " declared\n";
HasError = true;
}
public:
DeclCheck() : HasError(false) {}
bool hasError() { return HasError; }
// 检查Factor对象,如果Factor对应的标识符未在形参列表中声明,视为存在未声明的形参错误
virtual void visit(Factor &Node) override {
if (Node.getKind() == Factor::Ident) {
if (Scope.find(Node.getVal()) == Scope.end())
error(Not, Node.getVal());
}
};
// 检查二元运算BinaryOp对象
virtual void visit(BinaryOp &Node) override {
// 递归检查左右表达式,并判断左右表达式是否存在
if (Node.getLeft())
// 二元运算的左表达式接受当前vistor访问
Node.getLeft()->accept(*this);
else
HasError = true;
if (Node.getRight())
// 二元运算的右表达式接受当前vistor访问
Node.getRight()->accept(*this);
else
HasError = true;
};
// 检查WithDecl对象
virtual void visit(WithDecl &Node) override {
// 编译calc语句所有的形参,保存到Scope容器中
for (auto I = Node.begin(), E = Node.end(); I != E;
++I) {
// 如果Scope容器中已存在当前形参,插入失败,认为存在同名形参错误
if (!Scope.insert(*I).second)
error(Twice, *I);
}
// 检查Calc语句的表达式
if (Node.getExpr())
// Calc语句的表达式接受当前vistor访问
Node.getExpr()->accept(*this);
else
HasError = true;
};
};