北大编译实践2022 lab Lv1

作为新启用的lab实践方案,助教小哥哥写了一个非常详细的上手文档https://pku-minic.github.io/online-doc/#/,这里就记录一下具体实践流程和踩过的坑x

首先上手的Lv1,可以说助教xgg已经写的非常详尽了,基本照抄代码即可

一直照抄到Lv1.2,我们成功实现了hello.c

接下来实际上就是把之前代码中的string变成了AST对应的结构体,并中间实现Dump()函数进行输出操作。我们可以照着例子将下面所有块都派生一个AST的结构体,实现对应功能。

同时对于Lv1.4,即将对应的dump修改使得符合要求,由于目前代码简单我们就考虑实现要求操作,后续扩展可重新修改。(这里我保留了生成ast的dump

#include <iostream>
#include <memory>
class BaseAST {
 public:
  virtual ~BaseAST() = default;

  virtual void Dump() const = 0;
  virtual void DumpAST() const = 0;
};

class CompUnitAST : public BaseAST {
 public:
  std::unique_ptr<BaseAST> func_def;

  void Dump() const override {
    func_def->Dump();
  }
  void DumpAST() const override {
    std::cout << "CompUnitAST { ";
    func_def->DumpAST();
    std::cout << " }";
  }
};

class FuncDefAST : public BaseAST {
 public:
  std::unique_ptr<BaseAST> func_type;
  std::string ident;
  std::unique_ptr<BaseAST> block;

  void Dump() const override {
    std::cout << "fun ";
    std::cout << "@" << ident << "(): ";
    func_type->Dump();
    std::cout << "{ " << std::endl;
    block->Dump();
    std::cout << "} " << std::endl;
  }
  void DumpAST() const override {
    std::cout << "FuncDefAST { ";
    func_type->DumpAST();
    std::cout << ", " << ident << ", ";
    block->DumpAST();
    std::cout << " }";
  }
};

class FuncTypeAST : public BaseAST {
 public:
  std::string type;
  void Dump() const override {
    std::cout << "i32" << " ";
  }
  void DumpAST() const override {
    std::cout << "FuncTypeAST { ";
    std::cout << type;
    std::cout << " }";
  }
};

class BlockAST : public BaseAST {
 public:
  std::unique_ptr<BaseAST> stmt;
  void Dump() const override {
    std::cout << "\%entry" << ": " << std::endl;
    stmt->Dump();
    std::cout << std::endl;
  }
  void DumpAST() const override {
    std::cout << "BlockAST { ";
    stmt->DumpAST();
    std::cout << " }";
  }
};

class StmtAST : public BaseAST {
 public:
  int number;
  void Dump() const override {
    std::cout << "  ret ";
    std::cout << number;
  }
  void DumpAST() const override {
    std::cout << "StmtAST { ";
    std::cout << number;
    std::cout << " }";
  }
};

这样我们按照他要求的输出格式修改main.cpp,利用freopen输出

  freopen(output,"w",stdout);
  ast->Dump();
  fclose(stdout);

此时我们就可以进行测试了,但是我们发现其中一个comment测试点没有通过,我们首先添加一下error信息,发现没有正确识别’/’

void yyerror(std::unique_ptr<BaseAST> &ast, const char *s) {
  
    extern int yylineno;    // defined and maintained in lex
    extern char *yytext;    // defined and maintained in lex
    int len=strlen(yytext);
    int i;
    char buf[512]={0};
    for (i=0;i<len;++i){
        sprintf(buf,"%s%d ",buf,yytext[i]);
    }
    fprintf(stderr, "ERROR: %s at symbol '%s' on line %d\n", s, buf, yylineno);

}

这时可以发现我们应该在.l文件中进行注释块的匹配并将他忽略,这样百度了一个匹配方案,添加进去,这样就通过了全部测试点。

BlockComment  "/*"(?:[^\*]|\*+[^\/\*])*\*+\/

评论

  • CCY 回复

    求更新

发表评论

衫小寨 出品