v0.3.0 — Parser Hardening: C++17/20 Syntax Coverage
This release is a major parser hardening milestone. Across stress test rounds 4 through 10, the recursive-descent parser was pushed against increasingly exotic C++17/20 constructs until it either passed or was fixed. The result is substantially broader syntax coverage with fewer silent misparsings.
Critical Bug Fix
peek() was mutating pos as a side effect. peek() called skipCommentsAt() which advanced pos past comment tokens. This meant that when a comment appeared between two tokens, checkKeyword("template") would see the keyword correctly, but the immediately following checkOp("<") would see the keyword again instead of <, because pos had already moved. This caused template<Numeric T> to be misidentified as an explicit template instantiation, silently swallowing entire function definitions. Fixed by making peek() scan forward without mutating pos.
Parser
constevalandconstinitadded to the keyword set and all qualifier loops- Explicit template instantiation (
template class std::vector<int>;) consumed verbatim before namespace wrapping - Concept-constrained template parameters (
template<Numeric T>whereNumericis a concept name) - Global structured binding (
auto [a, b] = MyPair{...};at file scope) hoisted to namespace scope - Bit field declarations (
unsigned int x : 1;in struct members) __attribute__((...))in trailing and inline positions after function declarations and variable names- Variadic pack expansion in params (
Args&&... args) now setsisVariadicfrom the type-level... - Pack expansion in call arguments (
f(args...)) emits correctly - Local struct definitions inside function bodies now emit the struct before the following variable declaration
- Local struct forward declarations (
struct Foo;inside a function) consumed silently - Variable template specialization (
zero<float> = 0.0f) parsed correctly inparseFunctionOrVariableName extern "C"andextern "C++"linkage specifications parsed; block form recurses into itemsexplicit(...)conditional explicit specifier (C++20) consumed before constructor dispatchfrienddeclarations and definitions consumed verbatim in class bodies, including templated friends with bodiesalignas(...)before struct/class names (struct alignas(64) CacheLine)[[attributes]]before struct/class names consumed inparseTypeDef- Constructor name matching for specializations (
Grid<T, N, false>matches constructorGrid(...)by base name) parseTemplateDefaultValuenow tracks{}depth so<inside lambda bodies does not abort angle bracket parsinglooksLikeTemplateArgListnow tracks()and{}depth so{insidedecltype(T{})does not cause the lookahead to bail- Brace initialization in constructor initializer lists (
m{{1,0},{0,1}}) - Specialization args in
parseTypeDefuse a manual depth-tracked token scan rather thanparseTemplateArgList, which handles cases likeGrid<T, N, false> - System header filtering in
preprocessMacros:g++ -Eoutput is now filtered to only keep tokens from the sketch file itself, preventing STL internals from reaching the parser
AST
FunctionDecl.isDefaultandFunctionDecl.isDeletestore and emit= defaultand= delete, fixing linker errors fromvirtual ~Base() = defaultLambdaExpr.isMutablestores themutablekeyword
CodeGen
= defaultand= deleteemitted for function declarationsmutableemitted after the lambda parameter list, before the->return type- Trailing
decltype(...)return types emitted asauto name(params) -> decltype(...)
CppBuild
TopLevelStatementitems like structured bindings hoisted to namespace scope rather than emitted asstruct Sketchmembers- Explicit template instantiations emitted before
namespace Processing { preprocessMacrosfilters system header content out ofg++ -Eoutput
Stress Test Coverage
Rounds 4 through 10 cover: nested namespaces, constexpr virtual, designated initializers, pack expansion, operator new/delete overloads, placement new, partial template specialization, variadic templates, template template parameters, requires clauses, the spaceship operator, constexpr if, multiple inheritance, user-defined literals, CRTP, policy-based design, concept constraints, variable templates, lambda default template arguments, structured bindings, three-way comparison, __builtin_* functions, enum class with bitwise operators, nested initializer lists, and complex SFINAE patterns.