README
A compiler front end for the C++ language
This repository contains a work in progress compiler front end for C++ 20.
Install
For the latest stable version of the JavaScript bindings:
npm install cxx-frontend
JS Fiddle Playgrounds
Build
On Linux, macOS and Windows:
# configure cxx-frontend
cmake . \
-G Ninja \
-B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=1
# build cxx-frontend
cmake --build build
Dump the AST
Use -ast-dump
to dump the AST of a C++ program.
echo 'int main() { auto f = []{ return 1; }; return f(); }' |
./build/cxx-frontend -ast-dump -
Build the npm package using docker
cd packages/cxx-frontend
# prepare the package
npm ci
# compile WASM and TypeScript code
npm run build
# build the package
npm pack
Use the JavaScript API with Node.JS
//
// example.mjs
//
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(Parser.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();
if (ast) {
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);
Use the JavaScript API in a web browser
<!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@latest/dist/index.js";
const response = await fetch(Parser.DEFAULT_WASM_BINARY_URL);
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>
Release Notes
License
Copyright (c) 2021 Roberto Raggi roberto.raggi@gmail.com
Licensed under the MIT license.