北大编译实践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
求更新
soar
大佬,请教一下,怎么在实验环境里面把代码跑起来啊