-
Notifications
You must be signed in to change notification settings - Fork 0
Advanced
This page explores advanced topics in CDTk, including multi-target compilation, error handling, models, and writing custom validation rules. These features enhance the flexibility, robustness, and usability of your compilers.
Multi-target compilation allows you to generate output for multiple target languages or formats in a single compilation pass.
- You want the same source language to transpile into multiple output formats (e.g., C, Python, JavaScript).
- You want code generation and related tasks (such as linting or debugging comments) to happen simultaneously for multiple outputs.
In CDTk, you define a MapSet for each target language:
// Mapping for C
class CMapping : MapSet
{
public Map AssignmentNode = "int {variable} = {value};";
}
// Mapping for Python
class PythonMapping : MapSet
{
public Map AssignmentNode = "{variable} = {value}";
}
// Mapping for JavaScript
class JavaScriptMapping : MapSet
{
public Map AssignmentNode = "let {variable} = {value};";
}Use .WithTargets() to specify all the mappings for your targets:
var compiler = new Compiler()
.WithTokens(new Tokens())
.WithRules(new Rules())
.WithTargets(
("C", new CMapping()),
("Python", new PythonMapping()),
("JavaScript", new JavaScriptMapping())
)
.Build();After compilation, you can access each target's generated output via result.Outputs:
var result = compiler.Compile(sourceCode);
if (result.Success)
{
Console.WriteLine("// C Output:");
Console.WriteLine(result.Outputs["C"]);
Console.WriteLine("// Python Output:");
Console.WriteLine(result.Outputs["Python"]);
Console.WriteLine("// JavaScript Output:");
Console.WriteLine(result.Outputs["JavaScript"]);
}
else
{
Console.WriteLine("Compilation failed.");
}Ensure that:
-
MapSetvariables are named clearly (e.g.,CMapping,JavaScriptMapping). - Target names specified in
.WithTargets()match user expectations (e.g.,"C","Python").
Models in CDTk allow semantic enhancements and transformations to be applied to the Abstract Syntax Tree (AST). This provides a powerful mechanism to perform intermediate processing beyond tokenization, parsing, and code generation.
A model extends the base Model class and explicitly declares the data it requires (e.g., rules, AST, diagnostics).
class MyModel : Model
{
private readonly __Ast _ast;
private readonly __AllRules _rules;
public MyModel(__AllRules rules, __Ast ast)
{
_rules = rules;
_ast = ast;
}
public override object Build(object input)
{
if (input is AstNode astNode)
{
Console.WriteLine($"Processing Node: {astNode.Type}");
return new { TransformedData = astNode.GetString("name") };
}
return input;
}
}Models can be tied directly to your MapSet:
class Maps : MapSet
{
public MyModel Model => new MyModel(__AllRules!, __Ast!);
public Map AssignmentNode = "let {variable} = {value};";
}Assume an AST node for a variable incorrectly includes a reserved prefix. The model can sanitize the name dynamically:
class VariableModel : Model
{
public override object Build(object input)
{
if (input is AstNode node && node.Type == "VariableDecl")
{
var name = node.GetString("name");
return name.StartsWith("_")
? new { ProcessedVariable = name.Substring(1) }
: node;
}
return input;
}
}Benefits of using models:
- Customizable transformations for specific node types.
- Decouples semantic logic from mapping templates.
- Enables dynamic adjustments based on AST structure.
CDTk uses a robust diagnostics system to catch, report, and handle errors during all compilation stages.
-
Tokenization Errors:
- Reported during lexical analysis (e.g., when input text doesn’t match any token).
-
Parsing Errors:
- Occur when tokens violate your grammar rules.
-
Validation Errors:
- Semantic errors detected via custom validation logic.
You can report errors programmatically within models, rules, or validation contexts:
ctx.Report(
DiagnosticLevel.Error,
$"Variable '{variable}' not declared.",
astNode.Span
);- Info: Informational messages.
- Warning: Recoverable issues.
- Error: Prevents further compilation.
diagnostics.Add(Stage.SemanticAnalysis, DiagnosticLevel.Warning, "This is a warning.");
diagnostics.Add(Stage.LexicalAnalysis, DiagnosticLevel.Error, "Critical error encountered.");Custom validation rules are useful for enforcing semantic constraints that grammar alone cannot handle.
Attach custom validation logic to a rule via .Validate():
new Rule("Assignment", "@Identifier '=' Expression")
.Returns("AssignmentNode", "variable", "value")
.Validate((ctx, node, token) =>
{
var variable = node["variable"]?.ToString();
if (!ctx.IsDeclared(variable))
{
ctx.Report(DiagnosticLevel.Error, $"Variable '{variable}' not declared.");
}
});The validation context provides:
- Scoping Information: Check variable and type declarations.
- Diagnostics Reporting: Add warnings or errors programmatically during validation.
These advanced topics unlock the full potential of CDTk:
- Multi-target compilation simplifies producing multiple outputs from a single source.
- Models bring semantic adjustments and transformations into your compilation pipeline.
- Error Handling ensures robust feedback for developers and users.
- Custom validation adds semantic awareness to your compiler.
Explore these features to handle more complex and diverse requirements in your compilers.