diff --git a/doc/reference-README.md b/doc/reference-README.md index 6a18768..8505009 100644 --- a/doc/reference-README.md +++ b/doc/reference-README.md @@ -51,7 +51,7 @@ cat /test/funcrparams.sysy - 参照SysY语言规范,修改`src/SysY.g4`文件,实现SysY词法/语法的完整定义 - 修改任意代码后需要重新执行`cmake --build build`命令重新构建项目,ANTLR工具会从`SysY.g4`生成词法/语法分析器,生成的文件位于`./build/src`目录 -- (进阶内容)修改`src/ASTPrinter.h`与`src/ASTPrinter.cpp`,实现从AST输出源程序,但输出的源程序是经过格式化的,测试用例为`test/format-test.sy`,格式化后的参考结果为`test/format-ref.sy` +- (进阶内容)修改`src/ASTPrinter.h`与`src/ASTPrinter.cpp`,实现从AST输出源程序,但输出的源程序是经过格式化的 ## 实验2:生成中间表示 diff --git a/src/frontend/SyntaxTreePrinter.cpp b/src/frontend/SyntaxTreePrinter.cpp index 0593105..1ec0cab 100644 --- a/src/frontend/SyntaxTreePrinter.cpp +++ b/src/frontend/SyntaxTreePrinter.cpp @@ -1,9 +1,6 @@ #include "frontend/SyntaxTreePrinter.h" #include -#include - -#include "SysYParser.h" namespace { @@ -23,104 +20,8 @@ std::string GetTokenName(const antlr4::Token* tok, antlr4::Parser* parser) { return token_name; } -bool KeepImportantToken(const std::string& token_name) { - return token_name == "Ident" || token_name == "Number" || - token_name == "Assign" || token_name == "AddOp"; -} - -std::string PrettyPrimary(SysYParser::PrimaryContext* primary) { - if (!primary) { - return ""; - } - if (primary->Number()) { - return primary->Number()->getText(); - } - if (primary->Ident()) { - return primary->Ident()->getText(); - } - if (primary->exp()) { - return "(" + primary->exp()->getText() + ")"; - } - return primary->getText(); -} - -std::string PrettyAddExp(SysYParser::AddExpContext* add_exp) { - if (!add_exp) { - return ""; - } - const auto terms = add_exp->primary(); - if (terms.empty()) { - return ""; - } - std::string out = PrettyPrimary(terms[0]); - for (size_t i = 1; i < terms.size(); ++i) { - out += " + " + PrettyPrimary(terms[i]); - } - return out; -} - -std::string PrettyExp(SysYParser::ExpContext* exp) { - if (!exp || !exp->addExp()) { - return ""; - } - return PrettyAddExp(exp->addExp()); -} - -std::string PrettyRuleText(antlr4::ParserRuleContext* rule) { - if (!rule) { - return ""; - } - if (auto* var_decl = dynamic_cast(rule)) { - std::string out = "int " + var_decl->Ident()->getText(); - if (var_decl->exp()) { - out += " = " + PrettyExp(var_decl->exp()); - } - out += ";"; - return out; - } - if (auto* ret = dynamic_cast(rule)) { - return "return " + PrettyExp(ret->exp()) + ";"; - } - if (dynamic_cast(rule) != nullptr) { - return "int main()"; - } - if (auto* stmt = dynamic_cast(rule)) { - if (stmt->varDecl()) { - return PrettyRuleText(stmt->varDecl()); - } - if (stmt->returnStmt()) { - return PrettyRuleText(stmt->returnStmt()); - } - } - if (auto* exp = dynamic_cast(rule)) { - return PrettyExp(exp); - } - if (auto* add_exp = dynamic_cast(rule)) { - return PrettyAddExp(add_exp); - } - if (auto* primary = dynamic_cast(rule)) { - return PrettyPrimary(primary); - } - return ""; -} - -bool HasVisibleNode(antlr4::tree::ParseTree* node, antlr4::Parser* parser) { - auto* terminal = dynamic_cast(node); - if (terminal) { - const std::string token_name = GetTokenName(terminal->getSymbol(), parser); - return KeepImportantToken(token_name); - } - for (auto* child : node->children) { - if (HasVisibleNode(child, parser)) { - return true; - } - } - return false; -} - -std::string RuleName(antlr4::tree::ParseTree* node, antlr4::Parser* parser) { - auto* rule = dynamic_cast(node); - if (!parser || !rule) { +std::string RuleName(antlr4::ParserRuleContext* rule, antlr4::Parser* parser) { + if (!rule || !parser) { return "unknown"; } const int idx = rule->getRuleIndex(); @@ -131,47 +32,34 @@ std::string RuleName(antlr4::tree::ParseTree* node, antlr4::Parser* parser) { return "unknown"; } -std::string NodeLabel(antlr4::tree::ParseTree* node, antlr4::Parser* parser) { - auto* terminal = dynamic_cast(node); - if (terminal) { - return GetTokenName(terminal->getSymbol(), parser) + ": " + node->getText(); - } - - const std::string rule_name = RuleName(node, parser); - auto* rule = dynamic_cast(node); - const std::string pretty = PrettyRuleText(rule); - if (!pretty.empty()) { - return rule_name + " (" + pretty + ")"; - } - return rule_name; -} - void PrintSyntaxTreeImpl(antlr4::tree::ParseTree* node, antlr4::Parser* parser, std::ostream& os, const std::string& prefix, bool is_last, bool is_root) { - if (!HasVisibleNode(node, parser)) { + if (!node) { return; } - if (is_root) { - os << NodeLabel(node, parser) << "\n"; + std::string label; + if (auto* terminal = dynamic_cast(node)) { + label = GetTokenName(terminal->getSymbol(), parser) + ": " + terminal->getText(); + } else if (auto* rule = dynamic_cast(node)) { + label = RuleName(rule, parser); } else { - os << prefix << (is_last ? "└── " : "├── ") << NodeLabel(node, parser) - << "\n"; + label = "unknown"; } - std::vector children; - for (auto* child : node->children) { - if (HasVisibleNode(child, parser)) { - children.push_back(child); - } + if (is_root) { + os << label << "\n"; + } else { + os << prefix << (is_last ? "`-- " : "|-- ") << label << "\n"; } const std::string child_prefix = - is_root ? "" : prefix + (is_last ? " " : "│ "); - for (size_t i = 0; i < children.size(); ++i) { - PrintSyntaxTreeImpl(children[i], parser, os, child_prefix, - i + 1 == children.size(), false); + is_root ? "" : prefix + (is_last ? " " : "| "); + const size_t child_count = node->children.size(); + for (size_t i = 0; i < child_count; ++i) { + PrintSyntaxTreeImpl(node->children[i], parser, os, child_prefix, + i + 1 == child_count, false); } } diff --git a/src/frontend/SyntaxTreePrinter.h b/src/frontend/SyntaxTreePrinter.h index 5dd6265..4633b5e 100644 --- a/src/frontend/SyntaxTreePrinter.h +++ b/src/frontend/SyntaxTreePrinter.h @@ -4,6 +4,6 @@ #include "antlr4-runtime.h" -// 以树状缩进形式打印语法树(仅保留关键节点/记号)。 +// 以树状缩进形式直接打印 ANTLR parse tree。 void PrintSyntaxTree(antlr4::tree::ParseTree* tree, antlr4::Parser* parser, std::ostream& os);