Skip to content

Commit ddd1014

Browse files
committed
Implement default traversal for the entire AST
1 parent 68de020 commit ddd1014

File tree

6 files changed

+1370
-228
lines changed

6 files changed

+1370
-228
lines changed

packages/cxx-gen-ast/src/gen.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { gen_ast_slot_cc } from "./gen_ast_slot_cc.js";
3131
import { gen_ast_slot_h } from "./get_ast_slot_h.js";
3232
import { gen_ast_ts } from "./gen_ast_ts.js";
3333
import { gen_ast_visitor_h } from "./gen_ast_visitor_h.js";
34+
import { gen_ast_visitor_cc } from "./gen_ast_visitor_cc.js";
3435
import { gen_ast_visitor_ts } from "./gen_ast_visitor_ts.js";
3536
import { parseAST } from "./parseAST.js";
3637
import { gen_ast_kind_ts } from "./gen_ast_kind_ts.js";
@@ -67,6 +68,10 @@ gen_ast_visitor_h({
6768
ast,
6869
output: path.join(outdir, "src/parser/cxx/ast_visitor.h"),
6970
});
71+
gen_ast_visitor_cc({
72+
ast,
73+
output: path.join(outdir, "src/parser/cxx/ast_visitor.cc"),
74+
});
7075
gen_ast_printer_h({
7176
ast,
7277
output: path.join(outdir, "src/parser/cxx/ast_printer.h"),
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright (c) 2024 Roberto Raggi <[email protected]>
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
// SOFTWARE.
20+
21+
import { groupNodesByBaseType } from "./groupNodesByBaseType.js";
22+
import { AST, getASTNodes } from "./parseAST.js";
23+
import { cpy_header } from "./cpy_header.js";
24+
import * as fs from "fs";
25+
26+
export function gen_ast_visitor_cc({
27+
ast,
28+
output,
29+
}: {
30+
ast: AST;
31+
output: string;
32+
}) {
33+
const code: string[] = [];
34+
const emit = (line = "") => code.push(line);
35+
36+
const by_base = groupNodesByBaseType(ast);
37+
38+
const types = new Set<string>();
39+
40+
ast.nodes.forEach((node) => {
41+
node.members.forEach((m) => {
42+
if (m.kind === "node" || m.kind === "node-list") types.add(m.type);
43+
});
44+
});
45+
46+
by_base.forEach((nodes) => {
47+
nodes.forEach(({ name, members }) => {
48+
members = getASTNodes(members);
49+
50+
emit();
51+
emit(`void ASTVisitor::visit(${name}* ast) {`);
52+
members.forEach((m) => {
53+
if (m.kind === "node") {
54+
emit(`accept(ast->${m.name});`);
55+
} else if (m.kind === "node-list") {
56+
emit(`for (auto node : ListView{ast->${m.name}}) {`);
57+
emit(`accept(node);`);
58+
emit(`}`);
59+
}
60+
});
61+
emit(`}`);
62+
});
63+
});
64+
65+
const out = `${cpy_header}
66+
#include <cxx/ast_visitor.h>
67+
68+
// cxx
69+
#include <cxx/ast.h>
70+
71+
namespace cxx {
72+
73+
auto ASTVisitor::preVisit(AST*) -> bool {
74+
return true;
75+
}
76+
77+
void ASTVisitor::postVisit(AST*) {}
78+
79+
void ASTVisitor::accept(AST* ast) {
80+
if (!ast) return;
81+
if (preVisit(ast)) ast->accept(this);
82+
postVisit(ast);
83+
}
84+
85+
${code.join("\n")}
86+
87+
} // namespace cxx
88+
`;
89+
90+
fs.writeFileSync(output, out);
91+
}

packages/cxx-gen-ast/src/gen_ast_visitor_h.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function gen_ast_visitor_h({
4040
emit();
4141
emit(` // ${base}`);
4242
nodes.forEach(({ name }) => {
43-
emit(` virtual void visit(${name}* ast) = 0;`);
43+
emit(` virtual void visit(${name}* ast);`);
4444
});
4545
});
4646

@@ -55,6 +55,12 @@ namespace cxx {
5555
class ASTVisitor {
5656
public:
5757
virtual ~ASTVisitor() = default;
58+
59+
void accept(AST* ast);
60+
61+
[[nodiscard]] virtual bool preVisit(AST* ast);
62+
virtual void postVisit(AST* ast);
63+
5864
${code.join("\n")}
5965
};
6066

src/parser/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ add_library(cxx-parser
2727
cxx/ast_printer.cc
2828
cxx/ast_rewriter.cc
2929
cxx/ast_slot.cc
30+
cxx/ast_visitor.cc
3031
cxx/ast.cc
3132
cxx/base_classes.cc
3233
cxx/binder.cc

0 commit comments

Comments
 (0)