Skip to content

Advanced

Tristin Porter edited this page Jan 10, 2026 · 2 revisions

Advanced Topics in CDTk

This page explores advanced topics in CDTk, including multi-target compilation, error handling, and writing custom validation rules. These features allow you to enhance the flexibility, robustness, and usability of your compilers.


Table of Contents

  1. Multi-Target Compilation
  2. Error Handling in CDTk
  3. Writing Custom Validation Rules

Multi-Target Compilation

Multi-target compilation allows you to generate output for multiple target languages or formats in a single compilation pass.

When to Use:

  • 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.

Defining Multi-Target Mappings

In CDTk, you define a MapSet for each target language:

// Mapping for C
var cMapping = new MapSet
{
    new Map("AssignmentNode", "int {variable} = {value};")
};

// Mapping for Python
var pythonMapping = new MapSet
{
    new Map("AssignmentNode", "{variable} = {value}")
};

// Mapping for JavaScript
var jsMapping = new MapSet
{
    new Map("AssignmentNode", "let {variable} = {value};")
};

Configuring Multi-Target Compiler

Use .WithTargets() to specify all the mappings for your targets:

var compiler = new Compiler()
    .WithTokens(tokens)
    .WithRules(rules)
    .WithTargets(
        ("C", cMapping),
        ("Python", pythonMapping),
        ("JavaScript", jsMapping)
    )
    .Build();

Accessing Results by Target Name

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.");
}

Best Practice: Consistent Mapping Names

Ensure that:

  1. MapSet variables are named clearly (e.g., cMapping, jsMapping).
  2. Target names specified in .WithTargets() match user expectations (e.g., "C", "Python").

Error Handling in CDTk

CDTk uses a robust diagnostics system to catch, report, and handle errors during all compilation stages.

Stages of Error Handling

  1. Tokenization Errors:
    • Reported during lexical analysis (e.g., when input text doesn’t match any token).
  2. Parsing Errors:
    • Occur when tokens violate your grammar rules.
  3. Validation Errors:
    • Semantic errors detected via custom validation logic.

Adding Errors Manually

You can report errors programmatically:

diagnostics.Add(
    Stage.SyntaxAnalysis,
    DiagnosticLevel.Error,
    "Unexpected token found",
    Token.Span
);

Error Severity Levels

  • 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 Error Messages in Rules

Use .Error() and .ErrorLevel() in grammar rules:

new Rule("Statement", "Assignment ';'")
    .Error("Missing semicolon at the end of the statement.")
    .ErrorLevel(DiagnosticLevel.Error);

Writing Custom Validation Rules

Custom validation rules are useful for enforcing semantic constraints that grammar alone cannot handle, such as:

  • Variable scoping.
  • Checking assigned values for type compatibility.
  • Detecting reused or undeclared variables.

Adding Validation Logic

Use .Validate() to attach custom validation logic to a rule:

new Rule("Assignment", "@Identifier '=' Expression")
    .Returns("AssignmentNode", "variable", "value")
    .Validate((ctx, node, token) =>
    {
        var variable = node["variable"]?.ToString();

        // Ensure variables are declared before use
        if (!ctx.IsDeclared(variable))
        {
            ctx.Report(DiagnosticLevel.Error, $"Variable '{variable}' not declared.");
        }
        
        // Example validation: Ensure type compatibility between 'variable' and 'value'
        if (node["value"].Type == "StringLiteral" && variable.StartsWith("_"))
        {
            ctx.Report(DiagnosticLevel.Warning, "Avoid assigning strings to reserved variables.");
        }
    });

Validation Context (ctx)

The validation context (ctx) provides access to:

  1. Scoping Information: Check declared variables, types, or rules.
  2. Reporting Diagnostics: Add warnings or errors.
ctx.IsDeclared(variable);  // Checks if the variable is declared
ctx.Report(DiagnosticLevel.Error, "Custom error message");

Example of Validation for Scoping

new Rule("Block", "'{' Statement* '}'")
    .Returns("BlockNode", "statements")
    .Validate((ctx, node, token) =>
    {
        // Example: Ensure no variable has multiple declarations in the same block.
        var declaredVars = new HashSet<string>();
        foreach (var stmt in node["statements"] as List<AstNode>)
        {
            if (stmt.Type == "VarDecl")
            {
                var variableName = stmt["name"]?.ToString();
                if (!declaredVars.Add(variableName))
                {
                    ctx.Report(DiagnosticLevel.Error, $"Variable '{variableName}' already declared in this block.");
                }
            }
        }
    });

Conclusion

These advanced topics unlock the full potential of CDTk:

  • Multi-target compilation simplifies producing multiple outputs from a single source.
  • Error handling ensures robust feedback for users and developers.
  • Custom validation adds semantic awareness to your compiler.

Explore these features to handle more complex and diverse requirements in your compilers.

Clone this wiki locally