Show / Hide Table of Contents

Getting Started with SynKit

This guide will help you get up and running with the Yoakke SynKit library.

Installation

NuGet Packages

SynKit is distributed through several NuGet packages:

<!-- Core lexer functionality -->
<PackageReference Include="Yoakke.SynKit.Lexer" Version="x.x.x" />

<!-- Core parser functionality -->
<PackageReference Include="Yoakke.SynKit.Parser" Version="x.x.x" />

<!-- Source generators for lexer/parser generation -->
<PackageReference Include="Yoakke.SynKit.Lexer.Generator" Version="x.x.x" />
<PackageReference Include="Yoakke.SynKit.Parser.Generator" Version="x.x.x" />

<!-- Error reporting and diagnostics -->
<PackageReference Include="Yoakke.SynKit.Reporting" Version="x.x.x" />

<!-- Text processing utilities -->
<PackageReference Include="Yoakke.SynKit.Text" Version="x.x.x" />

Your First Lexer

  1. Define your token types:
public enum TokenType
{
    [Error] Error,
    [End] End,
    [Ignore] [Regex(Regexes.Whitespace)] Whitespace,
    
    [Token("+")] Plus,
    [Token("-")] Minus,
    [Token("*")] Multiply,
    [Token("/")] Divide,
    
    [Regex(Regexes.IntLiteral)] IntLiteral,
    [Regex(Regexes.Identifier)] Identifier,
}
  1. Create the lexer:
[Lexer(typeof(TokenType))]
public partial class MyLexer
{
    // The source generator will implement the lexer logic
}
  1. Use the lexer:
var lexer = new MyLexer("10 + 20 * 3");
while (true)
{
    var token = lexer.Next();
    if (token.Kind == TokenType.End) break;
    Console.WriteLine($"{token.Text} [{token.Kind}]");
}

Your First Parser

  1. Define grammar rules:
[Parser(typeof(TokenType))]
public partial class MyParser
{
    [Left("+", "-")]        // Lower precedence
    [Left("*", "/")]        // Higher precedence  
    [Rule("expression")]
    public static int BinaryOp(int left, IToken op, int right)
    {
        return op.Text switch
        {
            "+" => left + right,
            "-" => left - right,
            "*" => left * right,
            "/" => left / right,
            _ => throw new NotSupportedException()
        };
    }
    
    [Rule("expression: IntLiteral")]
    public static int IntLiteral(IToken token) => int.Parse(token.Text);
    
    [Rule("expression: '(' expression ')'")]
    public static int Parentheses(IToken _, int expr, IToken __) => expr;
}
  1. Use the parser:
var lexer = new MyLexer("(10 + 20) * 3");
var parser = new MyParser(lexer);

var result = parser.ParseExpression();
if (result.IsOk)
{
    Console.WriteLine($"Result: {result.Ok.Value}"); // Result: 90
}
else
{
    Console.WriteLine($"Parse error: {result.Error}");
}

Error Handling

SynKit provides comprehensive error handling:

var result = parser.ParseExpression();
if (result.IsError)
{
    var error = result.Error;
    Console.WriteLine($"Parse failed at position {error.Position}");
    
    foreach (var element in error.Elements.Values)
    {
        Console.WriteLine($"Expected: {string.Join(", ", element.Expected)}");
        Console.WriteLine($"Context: {element.Context}");
    }
}

Next Steps

  • Learn about Architecture concepts
  • Check Best Practices
  • Improve this Doc
In This Article
Back to top Generated by DocFX