This repository contains a work in progress compiler front end for C++ 20.
For the latest stable version of the JavaScript bindings:
npm install cxx-frontend
https://robertoraggi.github.io/cplusplus/
On Linux, macOS and Windows:
# install the python packages required to run the unit tests
pip install -r tests/unit_tests/requirements.txt
# configure the source code
cmake . \
-G Ninja \
-B build \
-DCMAKE_BUILD_TYPE=Release \
-DCXX_INTERPROCEDURAL_OPTIMIZATION=1
# build
cmake --build build
# run the unit tests
cd build
ctest --progress
Use -emit-ast
to serialize the AST of a C++ program to a flatbuffer binary file
# serialize the AST
$ ./build/src/frontend/cxx -emit-ast source.cc -o source.ast
You can use any flatbuffers supported decoder to read the AST, e.g.
# Use flatc to dump the AST to JSON
$ ./build/_deps/flatbuffers-build/flatc --raw-binary -t build/src/parser/cxx/ast.bfbs -- source.ast
$ ll source.*
source.ast source.cc source.json
cd packages/cxx-frontend
# prepare the package
npm ci
# compile WASM and TypeScript code
npm run build
# build the package
npm pack
//
// example.mjs
//
import DEFAULT_WASM_BINARY_URL from "../dist/defaultWasmBinaryUrl.js";
import { Parser, AST, ASTKind } from "cxx-frontend";
import { readFile } from "fs/promises";
import { fileURLToPath } from "url";
const source = `
template <typename T>
concept CanAdd = requires(T n) {
n + n;
};
auto twice(CanAdd auto n) {
return n + n;
}
int main() {
return twice(2);
}
`;
async function main() {
const wasmBinaryFile = fileURLToPath(DEFAULT_WASM_BINARY_URL);
const wasmBinary = await readFile(wasmBinaryFile);
// initialize the parser
await Parser.init({ wasmBinary });
const parser = new Parser({ source, path: "source.cc" });
parser.parse();
const diagnostics = parser.getDiagnostics();
if (diagnostics.length > 0) {
console.log("diagnostics", diagnostics);
}
const ast = parser.getAST();
ast?.walk().preVisit(({ node, depth }) => {
if (node instanceof AST) {
const ind = " ".repeat(depth * 2);
const kind = ASTKind[node.getKind()];
console.log(`${ind}${kind}`);
}
});
parser.dispose();
}
main().catch(console.error);
<!DOCTYPE html>
<html lang="en">
<head>
<title>C++ Playground</title>
</head>
<body>
<script type="module">
import { Parser, AST, ASTKind } from "https://unpkg.com/cxx-frontend";
const response = await fetch(
"https://unpkg.com/cxx-frontend/dist/cxx-js.wasm"
);
const wasmBinary = new Uint8Array(await response.arrayBuffer());
await Parser.init({ wasmBinary });
const source = `int main()\n{\n return 0;\n}\n`;
const parser = new Parser({
path: "source.cc",
source,
});
parser.parse();
const rows = [];
const ast = parser.getAST();
ast?.walk().preVisit(({ node, depth }) => {
if (node instanceof AST)
rows.push(" ".repeat(depth) + ASTKind[node.getKind()]);
});
parser.dispose();
const sourceOutput = document.createElement("pre");
sourceOutput.style.borderStyle = "solid";
sourceOutput.innerText = source;
document.body.appendChild(sourceOutput);
const astOutput = document.createElement("pre");
astOutput.style.borderStyle = "solid";
astOutput.innerText = rows.join("\n");
document.body.appendChild(astOutput);
</script>
</body>
</html>
Copyright (c) 2023 Roberto Raggi roberto.raggi@gmail.com
Licensed under the MIT license.