C++ C/C+的类型检查器+;喜欢的语言

C++ C/C+的类型检查器+;喜欢的语言,c++,casting,compiler-construction,typechecking,bnfc,C++,Casting,Compiler Construction,Typechecking,Bnfc,目前我正在为C/C++类语言编写一个编译器,更具体地说是一个类型检查器。 我已经用语法和bnfc工具生成了一个解析器。对于我的typechecker,我需要推断表达式的类型。所有表达式都派生自抽象基类Exp,如下所示: class Exp { ... } class ExpPlus : public { ... } class ExpAnd : public { ... } ... ExpPlus分别指Exp+Exp和Exp&&Exp。 我的推断函数接受一个表达式并返回其类型,如下所

目前我正在为C/C++类语言编写一个编译器,更具体地说是一个类型检查器。 我已经用语法和bnfc工具生成了一个解析器。对于我的typechecker,我需要推断表达式的类型。所有表达式都派生自抽象基类Exp,如下所示:

class Exp {
...
}

class ExpPlus : public {
 ...
}

class ExpAnd : public {
 ...
} 
...
ExpPlus分别指
Exp+Exp
Exp&&Exp
。 我的推断函数接受一个表达式并返回其类型,如下所示:

ype *TypeChecker::infer(Exp *exp)
{
    // check for kind of expression
    /* Base cases */
    if(dynamic_cast<ETrue*>(exp))
    {
        Type *tBool = new Type_bool;
        return tBool;
    }
    if(dynamic_cast<EFalse*>(exp))
    {
        Type *tBool = new Type_bool;
        return tBool;
    }
    if(dynamic_cast<EInt*>(exp))
    {
        Type *tInt = new Type_int;
        return tInt;
    }
    if(dynamic_cast<EDouble*>(exp))
    {
        Type *tDouble = new Type_double;
        return tDouble;
    }
    if(dynamic_cast<EId*>(exp))   // search for type of given Id in contexts
    {
        EId *eId = dynamic_cast<EId*>(exp);

        Type *typeOfSearchedId = env_->lookupVarTypeFromContext(eId->id_);
        return typeOfSearchedId;
    }
    /* Base cases end*/

    /* check expressions */
    if(dynamic_cast<EApp*>(exp))
    {
        EApp *eApp = dynamic_cast<EApp*>(exp);
        Type *retType = env_->lookupFunTypeFromSymbolTable(eApp->id_).returnType;

        return retType;
    }
    if(dynamic_cast<EUPlus*>(exp))
    {
        // cast exp to type of exp
        EUPlus *eu_plus = dynamic_cast<EUPlus*>(exp);

        // infer till base case is derived
        Type *typeExp = infer(eu_plus->exp_);

        // if type is int or double
        if(dynamic_cast<Type_int*>(typeExp) || dynamic_cast<Type_double*>(typeExp))
            return typeExp;

        throw TypeException("Trying to unary add wrong type: " + env_->getStringRepresentationOfType(typeExp));
    }
...
ype*TypeChecker::推断(Exp*Exp)
{
//检查表达的类型
/*基本情况*/
if(动态_转换(exp))
{
类型*tBool=新类型\u bool;
返回tBool;
}
if(动态_转换(exp))
{
类型*tBool=新类型\u bool;
返回tBool;
}
if(动态_转换(exp))
{
类型*tInt=新类型\u int;
返色;
}
if(动态_转换(exp))
{
类型*t加倍=新类型\u加倍;
返回t加倍;
}
if(dynamic_cast(exp))//在上下文中搜索给定Id的类型
{
EId*EId=dynamic_cast(exp);
Type*typeOfSearchedId=env_->lookupVarTypeFromContext(eId->id_);
searchedid的返回类型;
}
/*基本情况结束*/
/*检查表达式*/
if(动态_转换(exp))
{
EApp*EApp=动态投影(exp);
Type*retType=env_uu->lookupFunTypeFromSymbolTable(eApp->id_u)。returnType;
返回类型;
}
if(动态_转换(exp))
{
//将exp转换为exp的类型
EUPlus*eu_plus=动态_投射(exp);
//推断直到导出基本情况
Type*typeExp=exper(eu\u plus->exp\ux);
//如果类型为int或double
if(动态_转换(typeExp)|动态_转换(typeExp))
返回typeExp;
抛出TypeException(“试图添加错误的一元类型:”+env_u2;->getStringRepresentationOfType(typeExp));
}
...

正如你所看到的,我有一个很长的If语句列表,它检查了表达式的具体表达式类型,它可以很好地工作,但是我想知道是否有更优雅的方法来做到这一点。

你搞错了

与此相反:

class Base {};

class Derived1 : public Base {};
class Derived2 : public Base {};
class Derived3 : public Base {};
//...

void foo(Base* b) {
    if(dynamic_cast<Derived1*>(b)) {
        do_something( dynamic_cast<Derived1*>(b));
    } else if (dynamic_cast<Derived2*>(b)) {
        do_something( dynamic_cast<Derived2*>(b));
    } else if ....
}
请注意,现在不是每个使用
Base*
并根据动态类型期望不同行为的方法都必须真正知道动态类型。
foo
只调用
do\u something
和虚拟分派选择要调用的正确方法。如果您编写一些
bar(Base*)
您不需要第二块
if-else
,而是再次调用虚拟方法


我简化了很多示例,尽管在您的代码中似乎所有分支都返回一个
类型
,唯一的区别是不同派生类的不同实现。

如果(dynamic_cast使用虚拟函数而不是dynamic cast请注意,您发布的代码,无意冒犯,有点混乱。
:public
没有提到基类,
在类定义之后缺失,
推断
是如此不完整,以至于很难理解它的实际功能。请阅读相关内容您应该研究访问者模式。通常最好使用访问者模式,而不是让AST类包含每个编译阶段的方法。在我看来,将所有类型检查逻辑放在一个专用于类型检查的文件中,将所有代码生成逻辑放在一个专用于代码检查的文件中更有意义我承认我只关注多态性的使用,而忽略了实际的用例。tbh我认为任何东西都比OP目前拥有的要好;)
class Base {
    virtual void do_something() = 0;
    virtual ~Base() {}
};

class Derived1 : public Base {
    void do_something() override { /*...*/ }
};
class Derived2 : public Base {
    void do_something() override { /*...*/ }
};
//...

void foo(Base* b) {
    b->do_something();
}