A complete source-to-binary compiler pipeline in a single fluent Delphi API. Lexer. Parser. Semantics. C++23 codegen. Native binary via Zig.
A single TParse object drives
all five stages of compilation. There is no hardcoded language knowledge anywhere in the toolkit.
You describe the language. The pipeline runs it.
Register every token your language uses: keywords, operators, string delimiters, comment styles, number prefixes. The lexer has no built-in language knowledge.
Register Pratt parser handlers for prefix, infix-left, infix-right, and statement positions. Binding powers control precedence. Every AST node is yours to shape.
Register an emitter for every AST node kind. The fluent IR API generates well-formed C++23 text. ExprToString converts expression trees to inline C++ strings.
Parse() ships with four sample language implementations. Pascal, Lua, BASIC, and Scheme prove the toolkit handles radically different syntax families without any changes to the framework.
Case-insensitive keywords, := assignment, begin/end blocks, typed variables, typed procedures and functions. The Result return convention. Full C++23 forward declarations emitted to the header file.
var blocksif/then/else, while/do, for/to/downto/dowriteln with multiple comma-separated argumentsprogram HelloWorld; var greeting: string; count: integer; procedure PrintBanner(msg: string); begin writeln('--- ', msg, ' ---'); end; function Add(a: integer; b: integer): integer; begin Result := a + b; end; begin greeting := 'Hello, World!'; count := 5; PrintBanner(greeting); writeln('5 + 3 = ', Add(5, 3)); for i := 1 to count do writeln(' Step ', i); end.
No type annotations anywhere. Literal-based type inference at declaration sites. Call-site pre-scan for parameter type inference. local/global scope, .. string concatenation.
function/end with inferred return typeif/then/elseif/else/end, for/do/end, while/do/end.. string concatenation maps to <<print() variadic output via std::cout-- HelloWorld.lua local greeting = "Hello, World!" local count = 5 function PrintBanner(msg) print("--- " .. msg .. " ---") end function Add(a, b) return a + b end PrintBanner(greeting) print("5 + 3 = " .. Add(5, 3)) for i = 1, count do print(" Step " .. i) end
Implicit program body, no header keyword required. Dim/As typed declarations. The = operator serves dual duty: assignment at statement level, equality inside expressions.
Dim/As typed variable declarationsSub/End Sub and Function/End FunctionIf/Then/Else/End If, For/To/Next, While/Wend& string concatenationAdd = a + bDim greeting As String Dim count As Integer Sub PrintBanner(msg As String) Print "--- " & msg & " ---" End Sub Function Add(a As Integer, b As Integer) As Integer Add = a + b End Function greeting = "Hello, World!" count = 5 PrintBanner(greeting) Print "5 + 3 = " & Add(5, 3) For i = 1 To count Print " Step " & i Next i
A single ( handler drives all parsing, with no infix operators, no block keywords, and no statement terminator. Everything is an S-expression. Kebab-case identifiers are mangled to snake_case for C++.
(define var expr) and (define (f args) body)(if cond then else), (begin expr...)#t / #f boolean literals; HelloWorld.scm (define greeting "Hello, World!") (define count 5) (define (print-banner msg) (display "--- ") (display msg) (display " ---") (newline)) (define (add a b) (+ a b)) (print-banner greeting) (display "5 + 3 = ") (display (add 5 3)) (newline)
A single TParse drives every stage. Define it once; the lexer, parser, semantics, and codegen all read from it.
Top-down operator precedence parsing ready to use. Register handlers, set binding powers. No grammar files, no parser generators required.
Every node carries a string-keyed TValue dictionary. Pipeline stages communicate through attributes. No coupling between components.
Built-in scope trees, symbol declaration and lookup, type compatibility checking, and coercion annotation. Register only the handlers you need.
Structured builder API generates well-formed C++23. Functions, control flow, expressions: all fluent. No raw string-formatting.
Generates both a .h header and .cpp source. Language authors control which output receives each statement.
Generated C++ compiles to native binaries via Zig/Clang. exe, lib, dll. Win64 and Linux64. debug, release-safe, release-fast, release-small.
Built-in literal-type mapping and call-site scanning for dynamically-typed languages. Infer variable types from initialisers with no explicit annotations.
After semantic analysis the AST is fully self-sufficient. Every node carries resolved type, symbol, scope, and storage. Ready for language server integration.
Grab parsekit-toolchain.zip from the permanent release entry and unzip it directly into the root of your ParseKit source directory.
Clone or download the ParseKit repo. Open the project group in Delphi 11 or later and build. uses Parse; is the only unit you need.
Register keywords, operators, string styles, and comment styles. Set the statement terminator and block delimiters for your language.
Wire up prefix, infix, and statement handlers to build your AST. Register emitters to turn each node kind into C++23. Add semantic rules as needed.
Set source file, output path, platform, and build mode. Call Compile(True) and Parse() tokenizes, parses, analyses, emits C++, compiles, and optionally runs the result.
var LParse: TParse; begin LParse := TParse.Create(); try // ââ Lexer surface ââââââââââââââââââ LParse.Config() .CaseSensitiveKeywords(False) .AddKeyword('print', 'keyword.print') .AddOperator('(', 'delimiter.lparen') .AddOperator(')', 'delimiter.rparen') .AddStringStyle('"', '"', PARSE_KIND_STRING, True) .SetStatementTerminator(''); LParse.Config().RegisterLiteralPrefixes(); // ââ Grammar surface ââââââââââââââââ LParse.Config().RegisterStatement( 'keyword.print', 'stmt.print', function(AParser: TParseParserBase) : TParseASTNodeBase var LNode: TParseASTNode; begin LNode := AParser.CreateNode(); AParser.Consume(); AParser.Expect('delimiter.lparen'); LNode.AddChild(TParseASTNode( AParser.ParseExpression(0))); AParser.Expect('delimiter.rparen'); Result := LNode; end); // ââ Emit surface âââââââââââââââââââ LParse.Config().RegisterEmitter( 'stmt.print', procedure(ANode: TParseASTNodeBase; AGen: TParseIRBase) begin AGen.Include('iostream'); AGen.Stmt('std::cout << ' + LParse.Config().ExprToString( ANode.GetChild(0)) + ' << std::endl;'); end); LParse.SetSourceFile('hello.mylang'); LParse.SetOutputPath('output'); LParse.SetTargetPlatform(tpWin64); LParse.SetBuildMode(bmExe); LParse.SetOptimizeLevel(olDebug); LParse.Compile(True); finally LParse.Free(); end; end;
The toolchain zip contains the Zig compiler and C++ runtime. Unzip it into the root of your ParseKit source directory. The source is on GitHub. Delphi 11 or later required to build.
Permanent release entry: the URL never changes. When the toolchain updates, the same entry is replaced in place. · GitHub · Docs
| Requirement | Minimum | Notes |
|---|---|---|
| Host OS | Windows 10/11 x64 | Supported |
| Delphi | Delphi 11 Alexandria | To build the toolkit from source |
| Linux target | WSL2 + Ubuntu | wsl --install -d Ubuntu · Parse() locates it automatically |