diff --git a/.build/assets/icon.ico b/.build/assets/icon.ico
index 60e22b4..fe7b1ff 100644
Binary files a/.build/assets/icon.ico and b/.build/assets/icon.ico differ
diff --git a/.build/assets/icon.png b/.build/assets/icon.png
index 3605d76..6b6b1ae 100644
Binary files a/.build/assets/icon.png and b/.build/assets/icon.png differ
diff --git a/.build/targets.cs b/.build/targets.cs
index 1d9a4dd..653fa34 100644
--- a/.build/targets.cs
+++ b/.build/targets.cs
@@ -37,7 +37,7 @@
{
const string configuration = "Release";
const string solution = "Kuddle.slnx";
- const string packProject = "src/Kuddle/Kuddle.csproj";
+ const string packProject = "src/Kuddle.Net/Kuddle.Net.csproj";
var root = Directory.GetCurrentDirectory();
diff --git a/AGENTS.md b/AGENTS.md
index 1514a95..67bdef9 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,4 +1,4 @@
-# Agent Guidelines for Kuddle
+# Agent Guidelines for Kuddle.Net
## Build Commands
diff --git a/Kuddle.slnx b/Kuddle.slnx
index d6f6259..af84070 100644
--- a/Kuddle.slnx
+++ b/Kuddle.slnx
@@ -4,10 +4,8 @@
-
-
-
-
+
+
+
-
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..a56c6b1
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 jamesshenry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/docs/serialization-attributes.md b/docs/serialization-attributes.md
new file mode 100644
index 0000000..9b9a544
--- /dev/null
+++ b/docs/serialization-attributes.md
@@ -0,0 +1,453 @@
+# Attribute Usage
+
+This document describes how to use Kuddle's serialization attributes to map between KDL documents and C# types.
+
+## Quick Reference
+
+| Attribute | Target | Purpose |
+| ---------------------- | -------- | ------------------------------- |
+| `[KdlType]` | Class | Override the expected node name |
+| `[KdlArgument(index)]` | Property | Map to a positional argument |
+| `[KdlProperty(key?)]` | Property | Map to a named property |
+| `[KdlNode(name?)]` | Property | Map to child nodes |
+| `[KdlIgnore]` | Property | Exclude from serialization |
+
+---
+
+## Node Name Matching
+
+### Default Convention
+
+By default, the class name (lowercased) must match the KDL node name:
+
+```csharp
+// Matches: package "my-lib"
+public class Package { ... }
+```
+
+### Custom Node Name with `[KdlType]`
+
+Override the expected node name:
+
+```csharp
+// Matches: db "primary" (not "database")
+[KdlType("db")]
+public class Database { ... }
+```
+
+---
+
+## `[KdlArgument(index)]` — Positional Arguments
+
+Maps a property to a **positional argument** by zero-based index.
+
+### KDL
+
+```kdl
+point 10 20 30 label="origin"
+```
+
+### C# Model
+
+```csharp
+public class Point
+{
+ [KdlArgument(0)]
+ public int X { get; set; }
+
+ [KdlArgument(1)]
+ public int Y { get; set; }
+
+ [KdlArgument(2)]
+ public int Z { get; set; }
+
+ [KdlProperty("label")]
+ public string? Label { get; set; }
+}
+```
+
+### Rules
+
+1. **Index is required** — Each `[KdlArgument]` must specify its position
+2. **Indices should be contiguous** — Gaps (0, 2 without 1) may cause errors
+3. **Order matters** — During serialization, arguments are written in index order
+4. **Scalar types only** — Arguments cannot be complex objects
+
+### Supported Types
+
+- `string`
+- `int`, `long`, `double`, `decimal`
+- `bool`
+- `Guid` (with `(uuid)` type annotation)
+- `DateTimeOffset` (with `(date-time)` type annotation)
+- Nullable variants of all above
+
+---
+
+## `[KdlProperty(key?)]` — Named Properties
+
+Maps a property to a **KDL property** (key=value pair).
+
+### KDL
+
+```kdl
+dependency lodash version="4.17.21" optional=#false
+```
+
+### C# Model
+
+```csharp
+public class Dependency
+{
+ [KdlArgument(0)]
+ public string Package { get; set; } = "";
+
+ [KdlProperty("version")]
+ public string Version { get; set; } = "*";
+
+ [KdlProperty("optional")]
+ public bool Optional { get; set; }
+}
+```
+
+### Key Name Resolution
+
+1. **Explicit key**: `[KdlProperty("my-key")]` → matches `my-key=...`
+2. **Implicit key**: `[KdlProperty]` → uses property name lowercased
+
+```csharp
+[KdlProperty] // Matches "timeout=..."
+public int Timeout { get; set; }
+
+[KdlProperty("max-retries")] // Matches "max-retries=..."
+public int MaxRetries { get; set; }
+```
+
+### Rules
+
+1. **Last value wins** — Per KDL spec, if `key=1 key=2`, the value is `2`
+2. **Missing properties use defaults** — No error if property absent in KDL
+3. **Scalar types only** — Properties cannot be complex objects
+
+---
+
+## `[KdlNode(name?)]` — Child Nodes
+
+Maps a property to **child nodes** within the parent's `{ }` block.
+
+### Basic Usage — Collection of Child Nodes
+
+#### KDL
+
+```kdl
+project web-app version="1.0.0" {
+ dependency lodash version="4.17.21"
+ dependency react version="18.2.0"
+ devDependency jest version="29.0.0"
+}
+```
+
+#### C# Model
+
+```csharp
+public class Project
+{
+ [KdlArgument(0)]
+ public string Name { get; set; } = "";
+
+ [KdlProperty("version")]
+ public string Version { get; set; } = "1.0.0";
+
+ [KdlNode("dependency")]
+ public List Dependencies { get; set; } = [];
+
+ [KdlNode("devDependency")]
+ public List DevDependencies { get; set; } = [];
+}
+```
+
+### Single Complex Child
+
+When the property type is a **non-collection complex type**, it maps to a single child node:
+
+#### KDL
+
+```kdl
+application myapp {
+ database {
+ host "localhost"
+ port 5432
+ }
+}
+```
+
+#### C# Model
+
+```csharp
+public class Application
+{
+ [KdlArgument(0)]
+ public string Name { get; set; } = "";
+
+ [KdlNode("database")]
+ public DatabaseConfig? Database { get; set; }
+}
+
+public class DatabaseConfig
+{
+ [KdlNode("host")] // Maps child node's Arg(0)
+ public string Host { get; set; } = "";
+
+ [KdlNode("port")] // Maps child node's Arg(0)
+ public int Port { get; set; }
+}
+```
+
+### Scalar Child Node
+
+When the property type is a **scalar type**, it extracts `Arg(0)` from the child node:
+
+#### KDL
+
+```kdl
+config {
+ timeout 5000
+ enabled #true
+}
+```
+
+#### C# Model
+
+```csharp
+public class Config
+{
+ [KdlNode("timeout")]
+ public int Timeout { get; set; }
+
+ [KdlNode("enabled")]
+ public bool Enabled { get; set; }
+}
+```
+
+### Node Name Resolution
+
+1. **Explicit name**: `[KdlNode("my-items")]` → matches child nodes named `my-items`
+2. **Implicit name**: `[KdlNode]` → uses property name lowercased
+
+### Rules
+
+1. **Collection types** → Collects all matching child nodes into the list/array
+2. **Complex types** → Expects exactly one matching child node (throws if multiple)
+3. **Scalar types** → Extracts `Arg(0)` from the single matching child node
+4. **Supported collection types**: `List`, `T[]`, `IEnumerable`, `IList`
+
+---
+
+## `[KdlIgnore]` — Exclude Properties
+
+Excludes a property from both serialization and deserialization:
+
+```csharp
+public class User
+{
+ [KdlArgument(0)]
+ public string Username { get; set; } = "";
+
+ [KdlIgnore]
+ public string ComputedDisplayName => Username.ToUpperInvariant();
+
+ [KdlIgnore]
+ public DateTime LoadedAt { get; set; } = DateTime.UtcNow;
+}
+```
+
+---
+
+## Type Conversion
+
+### Automatic Type Mapping
+
+| C# Type | KDL Representation |
+| ------------------- | ----------------------------------- |
+| `string` | `"value"` or `bare-string` |
+| `int`, `long` | `123`, `0xFF`, `0o77`, `0b1010` |
+| `double`, `decimal` | `3.14`, `1.5e-10` |
+| `bool` | `#true`, `#false` |
+| `Guid` | `(uuid)"550e8400-..."` |
+| `DateTimeOffset` | `(date-time)"2024-01-15T10:30:00Z"` |
+| Nullable `T?` | Value or `#null` |
+
+### Type Annotations
+
+Type annotations in KDL provide parsing hints. The serializer recognizes:
+
+- `(uuid)` → `Guid`
+- `(date-time)` → `DateTimeOffset`
+
+```kdl
+user alice {
+ id (uuid)"550e8400-e29b-41d4-a716-446655440000"
+ createdAt (date-time)"2024-01-15T10:30:00Z"
+}
+```
+
+---
+
+## Document-Level vs Node-Level Deserialization
+
+### Single Node → Object
+
+When your type has `[KdlArgument]` or `[KdlProperty]` attributes, the deserializer expects **exactly one root node**:
+
+```csharp
+var kdl = "package my-lib version=\"1.0\"";
+var pkg = KdlSerializer.Deserialize(kdl);
+```
+
+### Multiple Nodes → Collection
+
+Use `DeserializeMany` for documents with multiple top-level nodes:
+
+```kdl
+server web-1 host="10.0.0.1"
+server web-2 host="10.0.0.2"
+server api-1 host="10.0.1.1"
+```
+
+```csharp
+var servers = KdlSerializer.DeserializeMany(kdl);
+// Returns IEnumerable with 3 items
+```
+
+### Document as Container
+
+For a document where each node type maps to a different property:
+
+```kdl
+name "my-project"
+version "1.0.0"
+author "Alice"
+```
+
+```csharp
+public class Manifest
+{
+ [KdlNode("name")]
+ public string Name { get; set; } = "";
+
+ [KdlNode("version")]
+ public string Version { get; set; } = "";
+
+ [KdlNode("author")]
+ public string Author { get; set; } = "";
+}
+```
+
+---
+
+## Complete Example
+
+### KDL Document
+
+```kdl
+project web-app version="2.0.0" {
+ dependency lodash version="4.17.21" optional=#false
+ dependency react version="18.2.0" optional=#false
+
+ devDependency jest version="29.0.0"
+ devDependency typescript version="5.0.0"
+
+ author "Alice" {
+ email "alice@example.com"
+ url "https://github.com/alice"
+ }
+
+ repository type="git" url="https://github.com/alice/web-app"
+}
+```
+
+### C# Models
+
+```csharp
+public class Project
+{
+ [KdlArgument(0)]
+ public string Name { get; set; } = "";
+
+ [KdlProperty("version")]
+ public string Version { get; set; } = "1.0.0";
+
+ [KdlNode("dependency")]
+ public List Dependencies { get; set; } = [];
+
+ [KdlNode("devDependency")]
+ public List DevDependencies { get; set; } = [];
+
+ [KdlNode("author")]
+ public Author? Author { get; set; }
+
+ [KdlNode("repository")]
+ public Repository? Repository { get; set; }
+}
+
+public class Dependency
+{
+ [KdlArgument(0)]
+ public string Package { get; set; } = "";
+
+ [KdlProperty("version")]
+ public string Version { get; set; } = "*";
+
+ [KdlProperty("optional")]
+ public bool Optional { get; set; }
+}
+
+public class Author
+{
+ [KdlArgument(0)]
+ public string Name { get; set; } = "";
+
+ [KdlNode("email")]
+ public string? Email { get; set; }
+
+ [KdlNode("url")]
+ public string? Url { get; set; }
+}
+
+public class Repository
+{
+ [KdlProperty("type")]
+ public string Type { get; set; } = "";
+
+ [KdlProperty("url")]
+ public string Url { get; set; } = "";
+}
+```
+
+---
+
+## Decision Tree: Which Attribute to Use?
+
+```
+Is the data a positional value after the node name?
+├─ YES → [KdlArgument(index)]
+└─ NO
+ │
+ Is the data a key=value pair on the same line?
+ ├─ YES → [KdlProperty("key")]
+ └─ NO
+ │
+ Is the data inside a { } children block?
+ ├─ YES → [KdlNode("childNodeName")]
+ └─ NO → Not mappable with current attributes
+```
+
+---
+
+## Limitations & Notes
+
+1. **No dictionary support** — `Dictionary` types are not currently supported
+2. **No polymorphism** — Cannot deserialize to derived types based on discriminator
+3. **Case sensitivity** — Node/property name matching is case-insensitive by default
+4. **Argument gaps** — Missing argument indices will throw; ensure contiguous indices
+5. **Round-trip fidelity** — Comments, formatting, and slashdash elements are not preserved
diff --git a/readme.md b/readme.md
index d85a754..98a21f3 100644
--- a/readme.md
+++ b/readme.md
@@ -1,188 +1,29 @@
-```text
-document := bom? version? nodes
-
-// Nodes
-nodes := (line-space* node)* line-space*
-
-base-node := slashdash? type? node-space* string
- (node-space+ slashdash? node-prop-or-arg)*
- // slashdashed node-children must always be after props and args.
- (node-space+ slashdash node-children)*
- (node-space+ node-children)?
- (node-space+ slashdash node-children)*
- node-space*
-node := base-node node-terminator
-final-node := base-node node-terminator?
-
-// Entries
-node-prop-or-arg := prop | value
-node-children := '{' nodes final-node? '}'
-node-terminator := single-line-comment | newline | ';' | eof
-
-prop := string node-space* '=' node-space* value
-value := type? node-space* (string | number | keyword)
-type := '(' node-space* string node-space* ')'
-
-// Strings
-string := identifier-string | quoted-string | raw-string ¶
-
-identifier-string := unambiguous-ident | signed-ident | dotted-ident
-unambiguous-ident :=
- ((identifier-char - digit - sign - '.') identifier-char*)
- - disallowed-keyword-strings
-signed-ident :=
- sign ((identifier-char - digit - '.') identifier-char*)?
-dotted-ident :=
- sign? '.' ((identifier-char - digit) identifier-char*)?
-identifier-char :=
- unicode - unicode-space - newline - [\\/(){};\[\]"#=]
- - disallowed-literal-code-points
-disallowed-keyword-identifiers :=
- 'true' | 'false' | 'null' | 'inf' | '-inf' | 'nan'
-
-quoted-string :=
- '"' single-line-string-body '"' |
- '"""' newline
- (multi-line-string-body newline)?
- (unicode-space | ws-escape)* '"""'
-single-line-string-body := (string-character - newline)*
-multi-line-string-body := (('"' | '""')? string-character)*
-string-character :=
- '\\' (["\\bfnrts] |
- 'u{' hex-unicode '}') |
- ws-escape |
- [^\\"] - disallowed-literal-code-points
-ws-escape := '\\' (unicode-space | newline)+
-hex-digit := [0-9a-fA-F]
-hex-unicode := hex-digit{1, 6} - surrogates
-surrogates := [dD][8-9a-fA-F]hex-digit{2}
-// U+D800-DFFF: D 8 00
-// D F FF
-
-raw-string := '#' raw-string-quotes '#' | '#' raw-string '#'
-raw-string-quotes :=
- '"' single-line-raw-string-body '"' |
- '"""' newline
- (multi-line-raw-string-body newline)?
- unicode-space* '"""'
-single-line-raw-string-body :=
- '' |
- (single-line-raw-string-char - '"')
- single-line-raw-string-char*? |
- '"' (single-line-raw-string-char - '"')
- single-line-raw-string-char*?
-single-line-raw-string-char :=
- unicode - newline - disallowed-literal-code-points
-multi-line-raw-string-body :=
- (unicode - disallowed-literal-code-points)*?
-
-// Numbers
-number := keyword-number | hex | octal | binary | decimal
+# Kuddle.Net
-decimal := sign? integer ('.' integer)? exponent?
-exponent := ('e' | 'E') sign? integer
-integer := digit (digit | '_')*
-digit := [0-9]
-sign := '+' | '-'
+Kuddle.Net is a .NET implementation of a [KDL](https://kdl.dev) parser/serializer targeting [v2](https://kdl.dev/spec/) of the spec.
+KDL is concise, human-readable language built for configuration and data exchange. Head to for more specifics on the KDL document language itself.
-hex := sign? '0x' hex-digit (hex-digit | '_')*
-octal := sign? '0o' [0-7] [0-7_]*
-binary := sign? '0b' ('0' | '1') ('0' | '1' | '_')*
+## Installation
-// Keywords and booleans.
-keyword := boolean | '#null'
-keyword-number := '#inf' | '#-inf' | '#nan'
-boolean := '#true' | '#false'
-
-// Specific code points
-bom := '\u{FEFF}'
-disallowed-literal-code-points :=
- See Table (Disallowed Literal Code Points)
-unicode := Any Unicode Scalar Value
-unicode-space := See Table
- (All White_Space unicode characters which are not `newline`)
-
-// Comments
-single-line-comment := '//' ^newline* (newline | eof)
-multi-line-comment := '/*' commented-block
-commented-block :=
- '*/' | (multi-line-comment | '*' | '/' | [^*/]+) commented-block
-slashdash := '/-' line-space*
-
-// Whitespace
-ws := unicode-space | multi-line-comment
-escline := '\\' ws* (single-line-comment | newline | eof)
-newline := See Table (All Newline White_Space)
-// Whitespace where newlines are allowed.
-line-space := node-space | newline | single-line-comment
-// Whitespace within nodes,
-// where newline-ish things must be esclined.
-node-space := ws* escline ws* | ws+
-
-// Version marker
-version :=
- '/-' unicode-space* 'kdl-version' unicode-space+ ('1' | '2')
- unicode-space* newline
+```text
+dotnet add package Kuddle.Net
```
-## Whitespace
+## Usage
-The following characters should be treated as non-Newline ({{newline}}) [white
-space](https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt):
+There are a few ways of using the library, the lower level `KdlReader` and `KdlWriter` classes, and the utility `KdlSerializer` class. For most use cases `KdlSerializer.Serialize`/`KdlSerializer.Deserialize` will be sufficient.
-| Name | Code Pt |
-| ------------------------- | -------- |
-| Character Tabulation | `U+0009` |
-| Space | `U+0020` |
-| No-Break Space | `U+00A0` |
-| Ogham Space Mark | `U+1680` |
-| En Quad | `U+2000` |
-| Em Quad | `U+2001` |
-| En Space | `U+2002` |
-| Em Space | `U+2003` |
-| Three-Per-Em Space | `U+2004` |
-| Four-Per-Em Space | `U+2005` |
-| Six-Per-Em Space | `U+2006` |
-| Figure Space | `U+2007` |
-| Punctuation Space | `U+2008` |
-| Thin Space | `U+2009` |
-| Hair Space | `U+200A` |
-| Narrow No-Break Space | `U+202F` |
-| Medium Mathematical Space | `U+205F` |
-| Ideographic Space | `U+3000` |
+```cs
+var dbKdl = """
+database main port=5432
+""";
-## Newline
-
-The following character sequences [should be treated as new
-lines](https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-5/#G41643):
-
-| Acronym | Name | Code Pt |
-| ------- | ----------------------------- | ------------------- |
-| CRLF | Carriage Return and Line Feed | `U+000D` + `U+000A` |
-| CR | Carriage Return | `U+000D` |
-| LF | Line Feed | `U+000A` |
-| NEL | Next Line | `U+0085` |
-| VT | Vertical tab | `U+000B` |
-| FF | Form Feed | `U+000C` |
-| LS | Line Separator | `U+2028` |
-| PS | Paragraph Separator | `U+2029` |
-
-Note that for the purpose of new lines, the specific sequence `CRLF` is
-considered _a single newline_.
+var dbConfig = KdlSerializer.Deserialize(dbKdl);
+```
-## Disallowed Literal Code Points
+KDL differs from other configuration languages like
+yaml or toml in that it is node-based. The top-level document can consist of a collection of nodes, not args (e.g. `#true`, `#false`, `0xAF`) or properties (`key=#false`). To adhere to this, the serialization API depends on the use of several provided attributes to facilitate mapping `KDL` constructs to user defined types:
-The following code points may not appear literally anywhere in the document.
-They may be represented in Strings (but not Raw Strings) using Unicode Escapes ({{escapes}}) (`\u{...}`,
-except for non Unicode Scalar Value, which can't be represented even as escapes).
+### Attributes
-- The codepoints `U+0000-0008` or the codepoints `U+000E-001F` (various
- control characters).
-- `U+007F` (the Delete control character).
-- Any codepoint that is not a [Unicode Scalar
- Value](https://unicode.org/glossary/#unicode_scalar_value) (`U+D800-DFFF`).
-- `U+200E-200F`, `U+202A-202E`, and `U+2066-2069`, the [unicode
- "direction control"
- characters](https://www.w3.org/International/questions/qa-bidi-unicode-controls)
-- `U+FEFF`, aka Zero-width Non-breaking Space (ZWNBSP)/Byte Order Mark (BOM),
- except as the first code point in a document.
+[how to use Kdl attributes](docs/serialization-attributes.md)
diff --git a/sampleApp/Program.cs b/sampleApp/Program.cs
deleted file mode 100644
index 3751555..0000000
--- a/sampleApp/Program.cs
+++ /dev/null
@@ -1,2 +0,0 @@
-// See https://aka.ms/new-console-template for more information
-Console.WriteLine("Hello, World!");
diff --git a/sampleApp/sampleApp.csproj b/sampleApp/sampleApp.csproj
deleted file mode 100644
index ed9781c..0000000
--- a/sampleApp/sampleApp.csproj
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
- Exe
- net10.0
- enable
- enable
-
-
-
diff --git a/samples/01-simple-node.kdl b/samples/01-simple-node.kdl
new file mode 100644
index 0000000..9ee78ec
--- /dev/null
+++ b/samples/01-simple-node.kdl
@@ -0,0 +1,4 @@
+// Simple node with arguments and properties
+// Maps to a single object with scalar values
+
+package "my-awesome-lib" version="2.1.0" description="A really cool library"
diff --git a/samples/02-multiple-arguments.kdl b/samples/02-multiple-arguments.kdl
new file mode 100644
index 0000000..99e7d19
--- /dev/null
+++ b/samples/02-multiple-arguments.kdl
@@ -0,0 +1,7 @@
+// Node with multiple positional arguments
+// Arguments are ordered and indexed (0, 1, 2...)
+
+command git commit -m Initial commit
+
+// Another example: coordinates
+point 10 20 30 label="origin"
diff --git a/samples/03-nested-children.kdl b/samples/03-nested-children.kdl
new file mode 100644
index 0000000..ddce116
--- /dev/null
+++ b/samples/03-nested-children.kdl
@@ -0,0 +1,11 @@
+// Node with child nodes (children block)
+// Children are nodes inside { }
+
+project web-app version="1.0.0" {
+ dependency lodash version="4.17.21" optional=#false
+ dependency react version="18.2.0" optional=#false
+ dependency typescript version="5.0.0" optional=#true
+
+ devDependency jest version="29.0.0"
+ devDependency eslint version="8.0.0"
+}
diff --git a/samples/04-numeric-types.kdl b/samples/04-numeric-types.kdl
new file mode 100644
index 0000000..81b14c4
--- /dev/null
+++ b/samples/04-numeric-types.kdl
@@ -0,0 +1,31 @@
+// Various numeric types and formats
+// KDL supports integers, floats, hex, octal, binary
+
+config {
+ // Integer properties
+ timeout 5000
+ maxRetries 3
+ port 8080
+
+ // Large numbers (long)
+ maxFileSize 9223372036854775807
+
+ // Floating point
+ ratio 0.75
+ pi 3.14159265358979
+
+ // Scientific notation
+ precision 1.5e-10
+
+ // Different bases (all represent the same value: 255)
+ hexValue 0xFF
+ octalValue 0o377
+ binaryValue 0b11111111
+
+ // Negative numbers
+ offset -100
+ temperature -273.15
+
+ // Underscores for readability
+ population 7_900_000_000
+}
diff --git a/samples/05-type-annotations.kdl b/samples/05-type-annotations.kdl
new file mode 100644
index 0000000..3cdf365
--- /dev/null
+++ b/samples/05-type-annotations.kdl
@@ -0,0 +1,30 @@
+// Type annotations provide hints about value interpretation
+// Format: (type)value
+
+user alice {
+ id (uuid)"550e8400-e29b-41d4-a716-446655440000"
+ createdAt (date-time)"2024-01-15T10:30:00Z"
+ lastLogin (date-time)"2024-12-17T14:22:33.123Z"
+
+ // Numeric type annotations
+ age (u8)28
+ balance (decimal)"1234567.89"
+ score (f64)98.5
+}
+
+// Type annotation on node name (context/role annotation)
+(admin)user "superuser" {
+ permissions "all"
+}
+
+// Various string type annotations from the spec
+metadata {
+ email (email)"user@example.com"
+ website (url)"https://example.com"
+ ip (ipv4)"192.168.1.1"
+ ipv6 (ipv6)"2001:0db8:85a3:0000:0000:8a2e:0370:7334"
+ country (country-2)"US"
+ duration (duration)"P1Y2M3DT4H5M6S"
+ pattern (regex)"^[a-z]+$"
+ binary (base64)"SGVsbG8gV29ybGQh"
+}
diff --git a/samples/06-booleans-and-null.kdl b/samples/06-booleans-and-null.kdl
new file mode 100644
index 0000000..5b5ca71
--- /dev/null
+++ b/samples/06-booleans-and-null.kdl
@@ -0,0 +1,19 @@
+// Boolean and null values use # prefix in KDL 2.0
+
+feature dark-mode {
+ enabled #true
+ beta #false
+ deprecatedAt #null
+}
+
+settings {
+ // All the keyword values
+ debug #true
+ production #false
+ overrideConfig #null
+
+ // Special float keywords
+ infiniteTimeout #inf
+ negativeInfinity #-inf
+ undefinedValue #nan
+}
diff --git a/samples/07-string-varieties.kdl b/samples/07-string-varieties.kdl
new file mode 100644
index 0000000..c671b6b
--- /dev/null
+++ b/samples/07-string-varieties.kdl
@@ -0,0 +1,33 @@
+// KDL supports multiple string syntaxes
+
+strings {
+ // Bare/identifier strings (no quotes needed for simple values)
+ simple hello-world
+ kebab my-kebab-case
+
+ // Quoted strings (required for whitespace, special chars)
+ withSpaces "hello world"
+ withQuote "say \"hello\""
+ withNewline "line1\nline2"
+ withTab "col1\tcol2"
+ unicode "emoji: \u{1F600}"
+
+ // Raw strings (no escape processing)
+ rawPath #"C:\Users\name\file.txt"#
+ rawRegex #"^\d+\.\d+\.\d+$"#
+ rawWithQuotes ##"She said "hello""##
+
+ // Multi-line strings
+ multiLine """
+ This is a multi-line string.
+ The indentation of the closing quotes
+ determines the base indentation.
+ All lines are dedented accordingly.
+ """
+
+ // Raw multi-line
+ rawMultiLine #"""
+ No escapes here: \n \t \u{1234}
+ All literal backslashes.
+ """#
+}
diff --git a/samples/08-deeply-nested.kdl b/samples/08-deeply-nested.kdl
new file mode 100644
index 0000000..99f2bf7
--- /dev/null
+++ b/samples/08-deeply-nested.kdl
@@ -0,0 +1,62 @@
+// Deeply nested structure - common in config files
+
+application "enterprise-app" version="3.0.0" {
+ database "primary" {
+ connection {
+ host "db.example.com"
+ port 5432
+ ssl #true
+
+ pool {
+ minSize 5
+ maxSize 50
+ idleTimeout 30000
+ }
+
+ credentials {
+ username "app_user"
+ // In real config, this would be a reference
+ passwordEnvVar "DB_PASSWORD"
+ }
+ }
+
+ replica "read-replica-1" {
+ host "replica1.example.com"
+ port 5432
+ readOnly #true
+ }
+
+ replica "read-replica-2" {
+ host "replica2.example.com"
+ port 5432
+ readOnly #true
+ }
+ }
+
+ cache "redis" {
+ host "cache.example.com"
+ port 6379
+ ttl 3600
+
+ cluster {
+ enabled #true
+ nodes 3
+ }
+ }
+
+ logging {
+ level "info"
+ format "json"
+
+ output "console" {
+ colorize #true
+ }
+
+ output "file" {
+ path "/var/log/app.log"
+ maxSize 10485760
+ maxFiles 5
+ compress #true
+ }
+ }
+}
diff --git a/samples/09-mixed-entries.kdl b/samples/09-mixed-entries.kdl
new file mode 100644
index 0000000..94b07da
--- /dev/null
+++ b/samples/09-mixed-entries.kdl
@@ -0,0 +1,25 @@
+// Arguments and properties can be freely intermixed
+// This is valid KDL - order of args is preserved, props can appear anywhere
+
+// Properties between arguments
+node 1 key=value 2 another=prop 3
+
+// Real-world example: CLI-like syntax
+run "npm" "install" --save=#true "lodash" --dev=#false
+
+// Build configuration with mixed entries
+task "build" priority=high "src/**/*.ts" output="dist" "!src/**/*.test.ts" {
+ compiler "tsc"
+ watch #false
+}
+
+// HTTP request definition
+request "POST" "/api/users" content-type="application/json" {
+ header "Authorization" "Bearer token123"
+ header "X-Request-Id" (uuid)"550e8400-e29b-41d4-a716-446655440000"
+
+ body {
+ name "John Doe"
+ email "john@example.com"
+ }
+}
diff --git a/samples/10-document-vs-node.kdl b/samples/10-document-vs-node.kdl
new file mode 100644
index 0000000..7d77f6e
--- /dev/null
+++ b/samples/10-document-vs-node.kdl
@@ -0,0 +1,24 @@
+// Document with multiple top-level nodes
+// This tests DeserializeMany and document-level mapping
+
+// When deserializing as a document, each top-level node maps to a list item
+// When deserializing as a single node, you'd wrap in a container
+
+server "web-1" host="10.0.0.1" port=80 {
+ role "frontend"
+ role "load-balancer"
+}
+
+server "web-2" host="10.0.0.2" port=80 {
+ role "frontend"
+}
+
+server "api-1" host="10.0.1.1" port=8080 {
+ role "backend"
+ role "api"
+}
+
+server "db-1" host="10.0.2.1" port=5432 {
+ role "database"
+ role "primary"
+}
diff --git a/samples/11-slashdash-comments.kdl b/samples/11-slashdash-comments.kdl
new file mode 100644
index 0000000..de7c4a5
--- /dev/null
+++ b/samples/11-slashdash-comments.kdl
@@ -0,0 +1,31 @@
+// Slashdash comments out entire elements
+// The serializer should NOT see these in the parsed AST
+
+config {
+ // Regular comment - ignored
+ enabled #true
+
+ /- disabled #true // This entire node is commented out
+
+ database {
+ host "localhost"
+ /- port 5432 // Commented out argument
+ port 3306 // This is the actual port
+
+ credentials user="admin" /- password="secret" // password prop commented out
+ }
+
+ /- slashdashed-node {
+ // Entire children block commented out
+ this "is" ignored=#true
+ }
+
+ // Slashdash can span multiple lines
+ /-
+ experimental {
+ feature1 #true
+ feature2 #true
+ }
+
+ production #true
+}
diff --git a/samples/12-edge-cases.kdl b/samples/12-edge-cases.kdl
new file mode 100644
index 0000000..cb0669b
--- /dev/null
+++ b/samples/12-edge-cases.kdl
@@ -0,0 +1,53 @@
+// Edge cases and tricky scenarios
+
+// Empty nodes (valid - just a name)
+empty-node
+
+// Node with only children, no args/props
+container {
+ child1
+ child2
+}
+
+// Same property multiple times - rightmost wins (per spec)
+settings priority=1 priority=2 priority=3 // priority should be 3
+
+// Unicode identifiers (bare strings)
+日本語ノード value="Japanese node name"
+émoji-🎉 value="Emoji in identifier"
+
+// Very long numbers
+bignum 999999999999999999999999999999
+
+// Numbers with many underscores
+formatted 1_000_000_000
+
+// Semicolon-separated nodes on one line
+a; b; c
+
+// Children on same line
+parent { child1; child2; child3 }
+
+// Line continuation
+very-long-node \
+ arg1 \
+ arg2 \
+ prop1="value1" \
+ prop2="value2" \
+ {
+ child
+ }
+
+// Property with same name as argument value (no conflict)
+node "key" key="different-value"
+
+// Nested type annotations
+typed-node (container)data {
+ item (u8)255
+ item (i8)-128
+}
+
+// Null in various positions
+nullable arg1=#null prop=#null {
+ child #null
+}
diff --git a/samples/13-real-world-package.kdl b/samples/13-real-world-package.kdl
new file mode 100644
index 0000000..dd1a440
--- /dev/null
+++ b/samples/13-real-world-package.kdl
@@ -0,0 +1,47 @@
+// Real-world example: Package manifest (like package.json in KDL)
+
+package "kuddle" version="1.0.0" {
+ description "A KDL parser and serializer for .NET"
+ license "MIT"
+
+ author "Henry" email="henry@example.com" {
+ url "https://github.com/henry"
+ }
+
+ repository type="git" url="https://github.com/henry/kuddle"
+
+ keywords "kdl" "parser" "serializer" "configuration" "dotnet"
+
+ engines {
+ dotnet ">=8.0.0"
+ }
+
+ scripts {
+ build "dotnet build"
+ test "dotnet test"
+ pack "dotnet pack"
+ publish "dotnet nuget push"
+ }
+
+ dependency "Parlot" version="^1.0.0" {
+ optional #false
+ }
+
+ devDependency "TUnit" version="^1.0.0"
+ devDependency "BenchmarkDotNet" version="^0.14.0"
+
+ // Conditional dependencies
+ dependency "System.Text.Json" version=">=8.0.0" {
+ condition "net8.0"
+ }
+
+ files "src/**/*.cs" "!src/**/*.Tests.cs" {
+ include "LICENSE"
+ include "README.md"
+ }
+
+ exports {
+ main "./src/Kuddle/Kuddle.csproj"
+ types "./src/Kuddle/Kuddle.csproj"
+ }
+}
diff --git a/samples/14-real-world-ci.kdl b/samples/14-real-world-ci.kdl
new file mode 100644
index 0000000..e8bc03e
--- /dev/null
+++ b/samples/14-real-world-ci.kdl
@@ -0,0 +1,87 @@
+// Real-world example: CI/CD pipeline configuration
+
+pipeline "main" {
+ trigger {
+ branch "main" "develop" "release/*"
+ path "src/**" "tests/**" ".github/**"
+
+ // Exclude paths
+ exclude "**/*.md" "docs/**"
+ }
+
+ variables {
+ variable "DOTNET_VERSION" "8.0.x"
+ variable "BUILD_CONFIGURATION" "Release"
+ variable "NUGET_FEED" "https://api.nuget.org/v3/index.json" secret=#false
+ }
+
+ stage "build" {
+ displayName "Build and Test"
+
+ job "build-windows" {
+ pool "windows-latest"
+
+ step "checkout" {
+ uses "actions/checkout@v4"
+ with {
+ fetch-depth 0
+ }
+ }
+
+ step "setup-dotnet" {
+ uses "actions/setup-dotnet@v4"
+ with {
+ dotnet-version "${{ variables.DOTNET_VERSION }}"
+ }
+ }
+
+ step "restore" {
+ run "dotnet restore"
+ }
+
+ step "build" {
+ run "dotnet build --configuration ${{ variables.BUILD_CONFIGURATION }} --no-restore"
+ }
+
+ step "test" {
+ run "dotnet test --configuration ${{ variables.BUILD_CONFIGURATION }} --no-build --logger trx"
+ continueOnError #false
+ }
+ }
+
+ job "build-linux" {
+ pool "ubuntu-latest"
+ dependsOn #null // Runs in parallel
+
+ step "checkout" uses="actions/checkout@v4"
+ step "setup-dotnet" uses="actions/setup-dotnet@v4"
+ step "restore" run="dotnet restore"
+ step "build" run="dotnet build -c Release"
+ step "test" run="dotnet test -c Release"
+ }
+ }
+
+ stage "publish" {
+ displayName "Publish Package"
+ dependsOn "build"
+ condition "eq(variables['Build.SourceBranch'], 'refs/heads/main')"
+
+ job "publish-nuget" {
+ pool "ubuntu-latest"
+
+ step "download-artifact" {
+ uses "actions/download-artifact@v4"
+ with {
+ name "nuget-package"
+ }
+ }
+
+ step "push-nuget" {
+ run "dotnet nuget push **/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source ${{ variables.NUGET_FEED }}"
+ env {
+ NUGET_API_KEY "${{ secrets.NUGET_API_KEY }}"
+ }
+ }
+ }
+ }
+}
diff --git a/src/Kuddle.Benchmarks/ParserBenchmarks.cs b/src/Kuddle.Benchmarks/ParserBenchmarks.cs
deleted file mode 100644
index d3ba66f..0000000
--- a/src/Kuddle.Benchmarks/ParserBenchmarks.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using System;
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Jobs;
-using Kuddle.AST;
-using Kuddle.Parser;
-using Parlot;
-using Parlot.Fluent;
-
-namespace Kuddle.Benchmarks;
-
-[SimpleJob(RuntimeMoniker.Net10_0)]
-[MemoryDiagnoser]
-public class ParserBenchmarks
-{
- private string _simpleDocument = string.Empty;
- private string _complexDocument = string.Empty;
- private string _largeDocument = string.Empty;
-
- private Parser _compiledParser = null!;
- private Parser _nonCompiledParser = null!;
-
- [GlobalSetup]
- public void Setup()
- {
- _simpleDocument = """
- node1 "value1"
- node2 123
- node3 #true
- """;
-
- _complexDocument = """
- package {
- name "my-package"
- version "1.0.0"
- dependencies {
- dep1 "^2.0.0"
- dep2 "~1.5.0"
- }
- }
-
- config (type)"production" {
- host "example.com"
- port 8080
- ssl #true
- features enabled=#true timeout=30
- }
-
- users {
- user id=1 name="Alice" active=#true
- user id=2 name="Bob" active=#false
- user id=3 name="Charlie" active=#true
- }
- """;
-
- var largeDocBuilder = new System.Text.StringBuilder();
- for (int i = 0; i < 100; i++)
- {
- largeDocBuilder.AppendLine($"node{i} {{");
- for (int j = 0; j < 10; j++)
- {
- largeDocBuilder.AppendLine($" child{j} \"value{j}\" prop{j}={j}");
- }
- largeDocBuilder.AppendLine("}");
- }
- _largeDocument = largeDocBuilder.ToString();
-
- _compiledParser = KuddleGrammar.Document.Compile();
- _nonCompiledParser = KuddleGrammar.Document;
- }
-
- [Benchmark]
- public KdlDocument? SimpleDocument_NonCompiled()
- {
- return _nonCompiledParser.Parse(_simpleDocument);
- }
-
- [Benchmark]
- public KdlDocument? SimpleDocument_Compiled()
- {
- return _compiledParser.Parse(_simpleDocument);
- }
-
- [Benchmark]
- public KdlDocument? ComplexDocument_NonCompiled()
- {
- return _nonCompiledParser.Parse(_complexDocument);
- }
-
- [Benchmark]
- public KdlDocument? ComplexDocument_Compiled()
- {
- return _compiledParser.Parse(_complexDocument);
- }
-
- [Benchmark]
- public KdlDocument? LargeDocument_NonCompiled()
- {
- return _nonCompiledParser.Parse(_largeDocument);
- }
-
- [Benchmark]
- public KdlDocument? LargeDocument_Compiled()
- {
- return _compiledParser.Parse(_largeDocument);
- }
-}
diff --git a/src/Kuddle.Generators/Kuddle.Generators.csproj b/src/Kuddle.Generators/Kuddle.Generators.csproj
deleted file mode 100644
index f86a614..0000000
--- a/src/Kuddle.Generators/Kuddle.Generators.csproj
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
- netstandard2.0
- latest
- enable
- enable
- true
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
-
-
diff --git a/src/Kuddle.Generators/TheGenerator.cs b/src/Kuddle.Generators/TheGenerator.cs
deleted file mode 100644
index 45aee6f..0000000
--- a/src/Kuddle.Generators/TheGenerator.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System.Collections.Immutable;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-
-namespace Kuddle.Generators;
-
-[Generator]
-public class TheGenerator : IIncrementalGenerator
-{
- public void Initialize(IncrementalGeneratorInitializationContext context)
- {
- var provider = context
- .SyntaxProvider.CreateSyntaxProvider(
- predicate: static (node, _) => node is ClassDeclarationSyntax,
- transform: static (ctx, _) => ctx.Node as ClassDeclarationSyntax
- )
- .Where(m => m is not null);
-
- var compilation = context.CompilationProvider.Combine(provider.Collect());
-
- context.RegisterSourceOutput(compilation, Execute);
- }
-
- private void Execute(
- SourceProductionContext context,
- (Compilation Left, ImmutableArray Right) tuple
- )
- {
- var (compilation, list) = tuple;
-
- var theCode = """
-namespace ClassListGenerator;
-
-public static class ClassNames
-{
- public static List Names = new()
- {
- "SomeClass"
- };
-}
-""";
-
- context.AddSource("YourClassList.g.cs", theCode);
- }
-}
diff --git a/src/Kuddle.Benchmarks/Kuddle.Benchmarks.csproj b/src/Kuddle.Net.Benchmarks/Kuddle.Net.Benchmarks.csproj
similarity index 71%
rename from src/Kuddle.Benchmarks/Kuddle.Benchmarks.csproj
rename to src/Kuddle.Net.Benchmarks/Kuddle.Net.Benchmarks.csproj
index 8998760..9cec005 100644
--- a/src/Kuddle.Benchmarks/Kuddle.Benchmarks.csproj
+++ b/src/Kuddle.Net.Benchmarks/Kuddle.Net.Benchmarks.csproj
@@ -1,16 +1,17 @@
+ Kuddle.Benchmarks
Exe
net10.0
preview
enable
- disable
+ enable
true
-
+
diff --git a/src/Kuddle.Benchmarks/Program.cs b/src/Kuddle.Net.Benchmarks/Program.cs
similarity index 55%
rename from src/Kuddle.Benchmarks/Program.cs
rename to src/Kuddle.Net.Benchmarks/Program.cs
index c1ac613..181057c 100644
--- a/src/Kuddle.Benchmarks/Program.cs
+++ b/src/Kuddle.Net.Benchmarks/Program.cs
@@ -1,4 +1,4 @@
using BenchmarkDotNet.Running;
using Kuddle.Benchmarks;
-BenchmarkRunner.Run();
+BenchmarkRunner.Run();
diff --git a/src/Kuddle.Net.Benchmarks/SerializerBenchmarks.cs b/src/Kuddle.Net.Benchmarks/SerializerBenchmarks.cs
new file mode 100644
index 0000000..5752f38
--- /dev/null
+++ b/src/Kuddle.Net.Benchmarks/SerializerBenchmarks.cs
@@ -0,0 +1,234 @@
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Jobs;
+using Kuddle.AST;
+using Kuddle.Parser;
+using Kuddle.Serialization;
+using Parlot.Fluent;
+
+namespace Kuddle.Benchmarks;
+
+[SimpleJob(RuntimeMoniker.Net10_0)]
+[MemoryDiagnoser]
+public class SerializerBenchmarks
+{
+ private string _simpleDocument = string.Empty;
+ private string _complexDocument = string.Empty;
+ private string _largeDocument = string.Empty;
+
+ private Parser _compiledParser = null!;
+ private Parser _nonCompiledParser = null!;
+
+ // Serialization benchmarks
+ private Package _simplePackage = null!;
+ private string _simplePackageKdl = string.Empty;
+
+ private Project _complexProject = null!;
+ private string _complexProjectKdl = string.Empty;
+
+ private List _largePackageList = null!;
+ private string _largePackageListKdl = string.Empty;
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ _simpleDocument = """
+ node1 "value1"
+ node2 123
+ node3 #true
+ """;
+
+ _complexDocument = """
+ package {
+ name "my-package"
+ version "1.0.0"
+ dependencies {
+ dep1 "^2.0.0"
+ dep2 "~1.5.0"
+ }
+ }
+
+ config (type)"production" {
+ host "example.com"
+ port 8080
+ ssl #true
+ features enabled=#true timeout=30
+ }
+
+ users {
+ user id=1 name="Alice" active=#true
+ user id=2 name="Bob" active=#false
+ user id=3 name="Charlie" active=#true
+ }
+ """;
+
+ var largeDocBuilder = new System.Text.StringBuilder();
+ for (int i = 0; i < 100; i++)
+ {
+ largeDocBuilder.AppendLine($"node{i} {{");
+ for (int j = 0; j < 10; j++)
+ {
+ largeDocBuilder.AppendLine($" child{j} \"value{j}\" prop{j}={j}");
+ }
+ largeDocBuilder.AppendLine("}");
+ }
+ _largeDocument = largeDocBuilder.ToString();
+
+ _compiledParser = KdlGrammar.Document.Compile();
+ _nonCompiledParser = KdlGrammar.Document;
+
+ // Setup serialization objects
+ _simplePackage = new Package
+ {
+ Name = "my-lib",
+ Version = "1.0.0",
+ Description = "A library",
+ };
+ _simplePackageKdl = KdlSerializer.Serialize(_simplePackage);
+
+ _complexProject = new Project
+ {
+ Name = "my-app",
+ Version = "2.0.0",
+ Dependencies =
+ [
+ new Dependency { Package = "lodash", Version = "4.17.21" },
+ new Dependency { Package = "react", Version = "18.0.0" },
+ new Dependency { Package = "typescript", Version = "4.5.0" },
+ ],
+ DevDependencies =
+ [
+ new Dependency { Package = "jest", Version = "27.0.0" },
+ new Dependency { Package = "eslint", Version = "8.0.0" },
+ ],
+ };
+ _complexProjectKdl = KdlSerializer.Serialize(_complexProject);
+
+ _largePackageList = [];
+ for (int i = 0; i < 100; i++)
+ {
+ _largePackageList.Add(
+ new Package
+ {
+ Name = $"package{i}",
+ Version = $"1.{i}.0",
+ Description = $"Description for package {i}",
+ }
+ );
+ }
+ _largePackageListKdl = KdlSerializer.SerializeMany(_largePackageList);
+ }
+
+ [Benchmark]
+ public KdlDocument? SimpleDocument_NonCompiled()
+ {
+ return _nonCompiledParser.Parse(_simpleDocument);
+ }
+
+ [Benchmark]
+ public KdlDocument? SimpleDocument_Compiled()
+ {
+ return _compiledParser.Parse(_simpleDocument);
+ }
+
+ [Benchmark]
+ public KdlDocument? ComplexDocument_NonCompiled()
+ {
+ return _nonCompiledParser.Parse(_complexDocument);
+ }
+
+ [Benchmark]
+ public KdlDocument? ComplexDocument_Compiled()
+ {
+ return _compiledParser.Parse(_complexDocument);
+ }
+
+ [Benchmark]
+ public KdlDocument? LargeDocument_NonCompiled()
+ {
+ return _nonCompiledParser.Parse(_largeDocument);
+ }
+
+ [Benchmark]
+ public KdlDocument? LargeDocument_Compiled()
+ {
+ return _compiledParser.Parse(_largeDocument);
+ }
+
+ // Serialization benchmarks
+ [Benchmark]
+ public string SerializeSimplePackage()
+ {
+ return KdlSerializer.Serialize(_simplePackage);
+ }
+
+ [Benchmark]
+ public string SerializeComplexProject()
+ {
+ return KdlSerializer.Serialize(_complexProject);
+ }
+
+ [Benchmark]
+ public string SerializeLargePackageList()
+ {
+ return KdlSerializer.SerializeMany(_largePackageList);
+ }
+
+ // Deserialization benchmarks
+ [Benchmark]
+ public Package? DeserializeSimplePackage()
+ {
+ return KdlSerializer.Deserialize(_simplePackageKdl);
+ }
+
+ [Benchmark]
+ public Project? DeserializeComplexProject()
+ {
+ return KdlSerializer.Deserialize(_complexProjectKdl);
+ }
+
+ [Benchmark]
+ public List? DeserializeLargePackageList()
+ {
+ return KdlSerializer.DeserializeMany(_largePackageListKdl).ToList();
+ }
+
+ // Test models
+ public class Package
+ {
+ [KdlArgument(0)]
+ public string Name { get; set; } = string.Empty;
+
+ [KdlProperty("version")]
+ public string? Version { get; set; }
+
+ [KdlProperty("description")]
+ public string? Description { get; set; }
+ }
+
+ public class Project
+ {
+ [KdlArgument(0)]
+ public string Name { get; set; } = string.Empty;
+
+ [KdlProperty("version")]
+ public string Version { get; set; } = "1.0.0";
+
+ [KdlNode("dependency")]
+ public List Dependencies { get; set; } = [];
+
+ [KdlNode("devDependency")]
+ public List DevDependencies { get; set; } = [];
+ }
+
+ public class Dependency
+ {
+ [KdlArgument(0)]
+ public string Package { get; set; } = string.Empty;
+
+ [KdlProperty("version")]
+ public string Version { get; set; } = "*";
+
+ [KdlProperty("optional")]
+ public bool Optional { get; set; }
+ }
+}
diff --git a/src/Kuddle.Tests/AST/KdlNumberTests.cs b/src/Kuddle.Net.Tests/AST/KdlNumberTests.cs
similarity index 100%
rename from src/Kuddle.Tests/AST/KdlNumberTests.cs
rename to src/Kuddle.Net.Tests/AST/KdlNumberTests.cs
diff --git a/src/Kuddle.Tests/AST/KdlStringTests.cs b/src/Kuddle.Net.Tests/AST/KdlStringTests.cs
similarity index 100%
rename from src/Kuddle.Tests/AST/KdlStringTests.cs
rename to src/Kuddle.Net.Tests/AST/KdlStringTests.cs
diff --git a/src/Kuddle.Tests/Errors/ErrorHandlingTests.cs b/src/Kuddle.Net.Tests/Errors/ErrorHandlingTests.cs
similarity index 98%
rename from src/Kuddle.Tests/Errors/ErrorHandlingTests.cs
rename to src/Kuddle.Net.Tests/Errors/ErrorHandlingTests.cs
index 0c4a7bb..84c6ec0 100644
--- a/src/Kuddle.Tests/Errors/ErrorHandlingTests.cs
+++ b/src/Kuddle.Net.Tests/Errors/ErrorHandlingTests.cs
@@ -1,4 +1,5 @@
using Kuddle.Exceptions;
+using Kuddle.Serialization;
namespace Kuddle.Tests.Errors;
@@ -12,7 +13,7 @@ private static async Task AssertParseFails(
int? expectedLine = null
)
{
- var ex = await Assert.ThrowsAsync(async () => KuddleReader.Parse(kdl));
+ var ex = await Assert.ThrowsAsync(async () => KdlReader.Read(kdl));
await Assert
.That(ex.Message)
diff --git a/src/Kuddle.Tests/Errors/test.kdl b/src/Kuddle.Net.Tests/Errors/test.kdl
similarity index 100%
rename from src/Kuddle.Tests/Errors/test.kdl
rename to src/Kuddle.Net.Tests/Errors/test.kdl
diff --git a/src/Kuddle.Tests/Extensions/DxTests.cs b/src/Kuddle.Net.Tests/Extensions/DxTests.cs
similarity index 89%
rename from src/Kuddle.Tests/Extensions/DxTests.cs
rename to src/Kuddle.Net.Tests/Extensions/DxTests.cs
index a15c293..aa230db 100644
--- a/src/Kuddle.Tests/Extensions/DxTests.cs
+++ b/src/Kuddle.Net.Tests/Extensions/DxTests.cs
@@ -1,6 +1,7 @@
using Kuddle.AST;
using Kuddle.Extensions;
using Kuddle.Parser;
+using Kuddle.Serialization;
namespace Kuddle.Tests.Extensions;
@@ -9,7 +10,7 @@ public class DxTests
[Test]
public async Task TryGet_Int_Success()
{
- var doc = KuddleReader.Parse("node 123");
+ var doc = KdlReader.Read("node 123");
var val = doc.Nodes[0].Arg(0)!;
bool success = val.TryGetInt(out int result);
@@ -21,7 +22,7 @@ public async Task TryGet_Int_Success()
[Test]
public async Task TryGet_Int_Failure_WrongType()
{
- var doc = KuddleReader.Parse("node \"hello\"");
+ var doc = KdlReader.Read("node \"hello\"");
var val = doc.Nodes[0].Arg(0)!;
bool success = val.TryGetInt(out int result);
@@ -34,7 +35,7 @@ public async Task TryGet_Int_Failure_WrongType()
public async Task TryGet_Int_Failure_Overflow()
{
// Value larger than Int32
- var doc = KuddleReader.Parse("node 9999999999");
+ var doc = KdlReader.Read("node 9999999999");
var val = doc.Nodes[0].Arg(0)!;
bool success = val.TryGetInt(out int result);
@@ -45,7 +46,7 @@ public async Task TryGet_Int_Failure_Overflow()
[Test]
public async Task TryGet_Prop_Navigation_Success()
{
- var doc = KuddleReader.Parse("server port=8080");
+ var doc = KdlReader.Read("server port=8080");
var node = doc.Nodes[0];
// Combine finding the prop and converting it
@@ -64,7 +65,7 @@ public async Task TryGet_Prop_Navigation_Success()
[Test]
public async Task TryGet_Prop_Navigation_Missing()
{
- var doc = KuddleReader.Parse("server host=\"localhost\"");
+ var doc = KdlReader.Read("server host=\"localhost\"");
var node = doc.Nodes[0];
var propVal = node.Prop("port")!; // Returns KdlNull
@@ -78,7 +79,7 @@ public async Task TryGetUuid_ValidGuidString_ReturnsTrue()
{
var expected = Guid.NewGuid();
var kdl = $"node \"{expected}\""; // e.g. "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
- var doc = KuddleReader.Parse(kdl);
+ var doc = KdlReader.Read(kdl);
var val = doc.Nodes[0].Arg(0)!;
bool success = val.TryGetUuid(out var result);
@@ -90,7 +91,7 @@ public async Task TryGetUuid_ValidGuidString_ReturnsTrue()
[Test]
public async Task TryGetUuid_InvalidString_ReturnsFalse()
{
- var doc = KuddleReader.Parse("node \"not-a-guid\"");
+ var doc = KdlReader.Read("node \"not-a-guid\"");
var val = doc.Nodes[0].Arg(0)!;
bool success = val.TryGetUuid(out var result);
@@ -104,7 +105,7 @@ public async Task TryGetUuid_FromAnnotatedValue_ReturnsTrue()
{
var expected = Guid.NewGuid();
var kdl = $"node (uuid)\"{expected}\"";
- var doc = KuddleReader.Parse(kdl);
+ var doc = KdlReader.Read(kdl);
var val = doc.Nodes[0].Arg(0)!;
bool success = val.TryGetUuid(out var result);
@@ -138,7 +139,7 @@ public async Task TryGetDateTime_ValidIso8601_ReturnsTrue()
var now = DateTimeOffset.UtcNow;
// Round-trip format "O" is standard for KDL/JSON
var kdl = $"node \"{now:O}\"";
- var doc = KuddleReader.Parse(kdl);
+ var doc = KdlReader.Read(kdl);
var val = doc.Nodes[0].Arg(0)!;
bool success = val.TryGetDateTime(out var result);
@@ -153,7 +154,7 @@ public async Task TryGetDateTime_DateOnly_ReturnsTrue()
{
// YYYY-MM-DD
var kdl = "node \"2023-10-25\"";
- var doc = KuddleReader.Parse(kdl);
+ var doc = KdlReader.Read(kdl);
var val = doc.Nodes[0].Arg(0)!;
bool success = val.TryGetDateTime(out var result);
@@ -167,7 +168,7 @@ public async Task TryGetDateTime_DateOnly_ReturnsTrue()
[Test]
public async Task TryGetDateTime_InvalidString_ReturnsFalse()
{
- var doc = KuddleReader.Parse("node \"tomorrow\"");
+ var doc = KdlReader.Read("node \"tomorrow\"");
var val = doc.Nodes[0].Arg(0)!;
bool success = val.TryGetDateTime(out var result);
diff --git a/src/Kuddle.Tests/Grammar/CommentParserTests.cs b/src/Kuddle.Net.Tests/Grammar/CommentParserTests.cs
similarity index 87%
rename from src/Kuddle.Tests/Grammar/CommentParserTests.cs
rename to src/Kuddle.Net.Tests/Grammar/CommentParserTests.cs
index 6448ef5..29b7750 100644
--- a/src/Kuddle.Tests/Grammar/CommentParserTests.cs
+++ b/src/Kuddle.Net.Tests/Grammar/CommentParserTests.cs
@@ -7,7 +7,7 @@ public class CommentParserTests
[Test]
public async Task CanParseSimpleSingleLineComment()
{
- var sut = KuddleGrammar.SingleLineComment;
+ var sut = KdlGrammar.SingleLineComment;
var comment = """// I am a single line comment""";
@@ -20,7 +20,7 @@ public async Task CanParseSimpleSingleLineComment()
[Test]
public async Task CanParseSimpleMultiLineComment()
{
- var sut = KuddleGrammar.MultiLineComment;
+ var sut = KdlGrammar.MultiLineComment;
var comment = """
/*
@@ -38,7 +38,7 @@ public async Task CanParseSimpleMultiLineComment()
[Test]
public async Task CanParseNestedMultiLineComment()
{
- var sut = KuddleGrammar.MultiLineComment;
+ var sut = KdlGrammar.MultiLineComment;
var comment = """
/*
diff --git a/src/Kuddle.Tests/Grammar/NodeParserTests.cs b/src/Kuddle.Net.Tests/Grammar/NodeParserTests.cs
similarity index 93%
rename from src/Kuddle.Tests/Grammar/NodeParserTests.cs
rename to src/Kuddle.Net.Tests/Grammar/NodeParserTests.cs
index b9745fb..a8f59d7 100644
--- a/src/Kuddle.Tests/Grammar/NodeParserTests.cs
+++ b/src/Kuddle.Net.Tests/Grammar/NodeParserTests.cs
@@ -10,7 +10,7 @@ public class NodeParsersTests
[Test]
public async Task Type_ParsesSimpleType()
{
- var sut = KuddleGrammar.Type;
+ var sut = KdlGrammar.Type;
var input = "(string)";
bool success = sut.TryParse(input, out var result);
@@ -22,7 +22,7 @@ public async Task Type_ParsesSimpleType()
[Test]
public async Task Prop_ParsesSimpleProperty()
{
- var sut = KuddleGrammar.Node;
+ var sut = KdlGrammar.Node;
var input = "node key=value";
bool success = sut.TryParse(input, out var node);
@@ -39,7 +39,7 @@ public async Task Prop_ParsesSimpleProperty()
[Test]
public async Task Node_ParsesComplexLine()
{
- var sut = KuddleGrammar.Node;
+ var sut = KdlGrammar.Node;
// Test: Name, Arg, Prop, Type Annotation
var input = "(my-type)node 123 key=\"value\";";
@@ -69,7 +69,7 @@ public async Task Node_ParsesComplexLine()
[Test]
public async Task Node_ParsesChildren()
{
- var sut = KuddleGrammar.Node;
+ var sut = KdlGrammar.Node;
var input = "parent { child; }";
bool success = sut.TryParse(input, out var node, out var error);
@@ -84,7 +84,7 @@ public async Task Node_ParsesChildren()
[Test]
public async Task Node_ParsesMixedContent()
{
- var sut = KuddleGrammar.Node;
+ var sut = KdlGrammar.Node;
var input = "(type)node 10 prop=#true { child; }";
bool success = sut.TryParse(input, out var node);
@@ -111,7 +111,7 @@ await Assert
public async Task Node_SlashDash_SkipsNode()
{
// This tests the logic in 'Nodes' (plural) parser usually
- var sut = KuddleGrammar.Document;
+ var sut = KdlGrammar.Document;
var input = "node1; /- node2; node3;";
bool success = sut.TryParse(input, out var doc);
@@ -125,7 +125,7 @@ public async Task Node_SlashDash_SkipsNode()
[Test]
public async Task Node_SlashDash_SkipsArg()
{
- var sut = KuddleGrammar.Node;
+ var sut = KdlGrammar.Node;
var input = "node 1 /- 2 3";
bool success = sut.TryParse(input, out var node);
@@ -145,7 +145,7 @@ public async Task Node_SlashDash_SkipsArg()
[Test]
public async Task SlashDash_SkipsProperty()
{
- var sut = KuddleGrammar.Node;
+ var sut = KdlGrammar.Node;
var input = "node key=1 /- skipped=2 valid=3";
bool success = sut.TryParse(input, out var node);
@@ -163,7 +163,7 @@ public async Task SlashDash_SkipsProperty()
[Test]
public async Task Node_SlashDash_SkipsChildrenBlock()
{
- var sut = KuddleGrammar.Node;
+ var sut = KdlGrammar.Node;
// Parsing a node that has a slash-dashed children block
var input = "node /- { child; }";
@@ -178,7 +178,7 @@ public async Task Node_SlashDash_SkipsChildrenBlock()
[Test]
public async Task Nodes_ParsesNodesWithWhitespace()
{
- var sut = KuddleGrammar.Nodes;
+ var sut = KdlGrammar.Nodes;
var input =
@"
node1;
diff --git a/src/Kuddle.Tests/Grammar/NumberParsersTests.cs b/src/Kuddle.Net.Tests/Grammar/NumberParsersTests.cs
similarity index 87%
rename from src/Kuddle.Tests/Grammar/NumberParsersTests.cs
rename to src/Kuddle.Net.Tests/Grammar/NumberParsersTests.cs
index e9ea2c8..6edcdef 100644
--- a/src/Kuddle.Tests/Grammar/NumberParsersTests.cs
+++ b/src/Kuddle.Net.Tests/Grammar/NumberParsersTests.cs
@@ -7,7 +7,7 @@ public class NumberParsersTests
[Test]
public async Task Decimal_ParsesPositiveInteger()
{
- var sut = KuddleGrammar.Decimal;
+ var sut = KdlGrammar.Decimal;
var input = "42";
bool success = sut.TryParse(input, out var value);
@@ -19,7 +19,7 @@ public async Task Decimal_ParsesPositiveInteger()
[Test]
public async Task Decimal_ParsesNegativeInteger()
{
- var sut = KuddleGrammar.Decimal;
+ var sut = KdlGrammar.Decimal;
var input = "-42";
bool success = sut.TryParse(input, out var value);
@@ -31,7 +31,7 @@ public async Task Decimal_ParsesNegativeInteger()
[Test]
public async Task Decimal_ParsesFractionalNumber()
{
- var sut = KuddleGrammar.Decimal;
+ var sut = KdlGrammar.Decimal;
var input = "3.14159";
bool success = sut.TryParse(input, out var value);
@@ -43,7 +43,7 @@ public async Task Decimal_ParsesFractionalNumber()
[Test]
public async Task Decimal_ParsesScientificNotation()
{
- var sut = KuddleGrammar.Decimal;
+ var sut = KdlGrammar.Decimal;
var input = "1.23e-4";
bool success = sut.TryParse(input, out var value);
@@ -55,7 +55,7 @@ public async Task Decimal_ParsesScientificNotation()
[Test]
public async Task Decimal_ParsesScientificNotationUppercase()
{
- var sut = KuddleGrammar.Decimal;
+ var sut = KdlGrammar.Decimal;
var input = "6.02E23";
bool success = sut.TryParse(input, out var value);
@@ -67,7 +67,7 @@ public async Task Decimal_ParsesScientificNotationUppercase()
[Test]
public async Task Decimal_ParsesWithUnderscoreSeparators()
{
- var sut = KuddleGrammar.Decimal;
+ var sut = KdlGrammar.Decimal;
var input = "1_000_000";
bool success = sut.TryParse(input, out var value);
@@ -79,7 +79,7 @@ public async Task Decimal_ParsesWithUnderscoreSeparators()
[Test]
public async Task Decimal_ParsesFractionalWithUnderscores()
{
- var sut = KuddleGrammar.Decimal;
+ var sut = KdlGrammar.Decimal;
var input = "12_34.56_78";
bool success = sut.TryParse(input, out var value);
@@ -91,7 +91,7 @@ public async Task Decimal_ParsesFractionalWithUnderscores()
[Test]
public async Task Hex_ParsesHexNumbers()
{
- var sut = KuddleGrammar.Hex;
+ var sut = KdlGrammar.Hex;
var input = "0xFF";
bool success = sut.TryParse(input, out var value);
@@ -103,7 +103,7 @@ public async Task Hex_ParsesHexNumbers()
[Test]
public async Task Hex_ParsesHexWithUnderscores()
{
- var sut = KuddleGrammar.Hex;
+ var sut = KdlGrammar.Hex;
var input = "0x123_ABC";
bool success = sut.TryParse(input, out var value);
@@ -115,7 +115,7 @@ public async Task Hex_ParsesHexWithUnderscores()
[Test]
public async Task Hex_ParsesNegativeHex()
{
- var sut = KuddleGrammar.Hex;
+ var sut = KdlGrammar.Hex;
var input = "-0x42";
bool success = sut.TryParse(input, out var value);
@@ -127,7 +127,7 @@ public async Task Hex_ParsesNegativeHex()
[Test]
public async Task Octal_ParsesOctalNumbers()
{
- var sut = KuddleGrammar.Octal;
+ var sut = KdlGrammar.Octal;
var input = "0o777";
bool success = sut.TryParse(input, out var value);
@@ -139,7 +139,7 @@ public async Task Octal_ParsesOctalNumbers()
[Test]
public async Task Octal_ParsesOctalWithUnderscores()
{
- var sut = KuddleGrammar.Octal;
+ var sut = KdlGrammar.Octal;
var input = "0o123_456";
bool success = sut.TryParse(input, out var value);
@@ -151,7 +151,7 @@ public async Task Octal_ParsesOctalWithUnderscores()
[Test]
public async Task Octal_ParsesNegativeOctal()
{
- var sut = KuddleGrammar.Octal;
+ var sut = KdlGrammar.Octal;
var input = "-0o42";
bool success = sut.TryParse(input, out var value);
@@ -163,7 +163,7 @@ public async Task Octal_ParsesNegativeOctal()
[Test]
public async Task Binary_ParsesBinaryNumbers()
{
- var sut = KuddleGrammar.Binary;
+ var sut = KdlGrammar.Binary;
var input = "0b1010";
bool success = sut.TryParse(input, out var value);
@@ -175,7 +175,7 @@ public async Task Binary_ParsesBinaryNumbers()
[Test]
public async Task Binary_ParsesBinaryWithUnderscores()
{
- var sut = KuddleGrammar.Binary;
+ var sut = KdlGrammar.Binary;
var input = "0b1111_0000";
bool success = sut.TryParse(input, out var value);
@@ -187,7 +187,7 @@ public async Task Binary_ParsesBinaryWithUnderscores()
[Test]
public async Task Binary_ParsesNegativeBinary()
{
- var sut = KuddleGrammar.Binary;
+ var sut = KdlGrammar.Binary;
var input = "-0b101";
bool success = sut.TryParse(input, out var value);
@@ -199,7 +199,7 @@ public async Task Binary_ParsesNegativeBinary()
[Test]
public async Task KeywordNumber_ParsesInfinity()
{
- var sut = KuddleGrammar.KeywordNumber;
+ var sut = KdlGrammar.KeywordNumber;
var input = "#inf";
bool success = sut.TryParse(input, out var value);
@@ -211,7 +211,7 @@ public async Task KeywordNumber_ParsesInfinity()
[Test]
public async Task KeywordNumber_ParsesNegativeInfinity()
{
- var sut = KuddleGrammar.KeywordNumber;
+ var sut = KdlGrammar.KeywordNumber;
var input = "#-inf";
bool success = sut.TryParse(input, out var value);
@@ -223,7 +223,7 @@ public async Task KeywordNumber_ParsesNegativeInfinity()
[Test]
public async Task KeywordNumber_ParsesNaN()
{
- var sut = KuddleGrammar.KeywordNumber;
+ var sut = KdlGrammar.KeywordNumber;
var input = "#nan";
bool success = sut.TryParse(input, out var value);
@@ -235,7 +235,7 @@ public async Task KeywordNumber_ParsesNaN()
[Test]
public async Task Number_ParsesDecimal()
{
- var sut = KuddleGrammar.Decimal;
+ var sut = KdlGrammar.Decimal;
var input = "42";
bool success = sut.TryParse(input, out var value);
@@ -247,7 +247,7 @@ public async Task Number_ParsesDecimal()
[Test]
public async Task Number_ParsesHex()
{
- var sut = KuddleGrammar.Hex;
+ var sut = KdlGrammar.Hex;
var input = "0xFF";
bool success = sut.TryParse(input, out var value);
@@ -259,7 +259,7 @@ public async Task Number_ParsesHex()
[Test]
public async Task Number_ParsesKeywordNumber()
{
- var sut = KuddleGrammar.KeywordNumber;
+ var sut = KdlGrammar.KeywordNumber;
var input = "#inf";
bool success = sut.TryParse(input, out var value);
@@ -271,7 +271,7 @@ public async Task Number_ParsesKeywordNumber()
[Test]
public async Task Decimal_RejectsDoubleDots()
{
- var sut = KuddleGrammar.Decimal.Eof();
+ var sut = KdlGrammar.Decimal.Eof();
var input = "12.34.56";
bool success = sut.TryParse(input, out var value);
diff --git a/src/Kuddle.Tests/Grammar/StringParserTests.cs b/src/Kuddle.Net.Tests/Grammar/StringParserTests.cs
similarity index 91%
rename from src/Kuddle.Tests/Grammar/StringParserTests.cs
rename to src/Kuddle.Net.Tests/Grammar/StringParserTests.cs
index 88050cc..622221f 100644
--- a/src/Kuddle.Tests/Grammar/StringParserTests.cs
+++ b/src/Kuddle.Net.Tests/Grammar/StringParserTests.cs
@@ -20,7 +20,7 @@ public class StringParserTests
[Arguments("-negative")]
public async Task SignedIdent_ParsesSignedIdentifier(string input)
{
- var sut = KuddleGrammar.SignedIdent;
+ var sut = KdlGrammar.SignedIdent;
bool success = sut.TryParse(input, out var value);
@@ -34,7 +34,7 @@ public async Task SignedIdent_ParsesSignedIdentifier(string input)
[Arguments(".three")]
public async Task DottedIdent_ParsesDottedIdentifier(string input)
{
- var sut = KuddleGrammar.DottedIdent;
+ var sut = KdlGrammar.DottedIdent;
bool success = sut.TryParse(input, out var value);
@@ -47,7 +47,7 @@ public async Task DottedIdent_ParsesDottedIdentifier(string input)
[Arguments(".01")]
public async Task DottedIdent_DoesNotParseNumberDottedNumber(string input)
{
- var sut = KuddleGrammar.DottedIdent;
+ var sut = KdlGrammar.DottedIdent;
bool success = sut.TryParse(input, out var value);
@@ -62,7 +62,7 @@ public async Task DottedIdent_DoesNotParseNumberDottedNumber(string input)
[Arguments("test_case")]
public async Task UnambiguousIdent_ParsesUnambiguousIdentifier(string input)
{
- var sut = KuddleGrammar.UnambiguousIdent;
+ var sut = KdlGrammar.UnambiguousIdent;
bool success = sut.TryParse(input, out var value);
@@ -76,7 +76,7 @@ public async Task UnambiguousIdent_ParsesUnambiguousIdentifier(string input)
[Arguments(".one")]
public async Task UnambiguousIdent_DoesNotParseInvalidIdentifier(string input)
{
- var sut = KuddleGrammar.UnambiguousIdent;
+ var sut = KdlGrammar.UnambiguousIdent;
bool success = sut.TryParse(input, out var value);
@@ -92,7 +92,7 @@ public async Task UnambiguousIdent_DoesNotParseInvalidIdentifier(string input)
[Arguments("nan")]
public async Task UnambiguousIdent_DoesNotParseDisallowedKeywordString(string input)
{
- var sut = KuddleGrammar.UnambiguousIdent;
+ var sut = KdlGrammar.UnambiguousIdent;
bool success = sut.TryParse(input, out var value);
@@ -112,7 +112,7 @@ public async Task UnambiguousIdent_DoesNotParseDisallowedKeywordString(string in
[Arguments("-negative")]
public async Task IdentifierString_ParsesIdentifierString(string input)
{
- var sut = KuddleGrammar.IdentifierString;
+ var sut = KdlGrammar.IdentifierString;
bool success = sut.TryParse(input, out var value);
@@ -124,7 +124,7 @@ public async Task IdentifierString_ParsesIdentifierString(string input)
[Arguments("\"\\ \"")]
public async Task WsEscape_ParsesWhiteSpace(string input)
{
- var sut = KuddleGrammar.QuotedString;
+ var sut = KdlGrammar.QuotedString;
bool success = sut.TryParse(input, out var value, out var error);
@@ -135,7 +135,7 @@ public async Task WsEscape_ParsesWhiteSpace(string input)
[Test]
public async Task QuotedString_ParsesSingleLineString()
{
- var sut = KuddleGrammar.QuotedString;
+ var sut = KdlGrammar.QuotedString;
const string input = """
"hello world"
@@ -149,7 +149,7 @@ public async Task QuotedString_ParsesSingleLineString()
[Test]
public async Task QuotedString_ParsesEmptyString()
{
- var sut = KuddleGrammar.QuotedString;
+ var sut = KdlGrammar.QuotedString;
const string input = """
""
@@ -163,7 +163,7 @@ public async Task QuotedString_ParsesEmptyString()
[Test]
public async Task QuotedString_ParsesEmptyMultilineString()
{
- var sut = KuddleGrammar.QuotedString;
+ var sut = KdlGrammar.QuotedString;
const string input = """"
"""
@@ -206,7 +206,7 @@ This is the base indentation
)]
public async Task MultiLineStringBody_HandlesVarious(string input, string expected)
{
- var sut = KuddleGrammar.MultiLineQuoted;
+ var sut = KdlGrammar.MultiLineQuoted;
bool success = sut.TryParse(input, out var value);
Debug.WriteLine(input);
@@ -234,7 +234,7 @@ canis canem edit
)]
public async Task MultiLineQuotedString_CanParseMultiLine(string input, string expected)
{
- var sut = KuddleGrammar.MultiLineQuoted;
+ var sut = KdlGrammar.MultiLineQuoted;
bool success = sut.TryParse(input, out var value, out var error);
await Assert.That(success).IsTrue();
await Assert.That(value.ToString()).IsEqualTo(expected);
@@ -249,7 +249,7 @@ public async Task MultiLineQuotedString_CanParseMultiLine(string input, string e
)]
public async Task QuotedString_HandlesUnicodeEscapes(string input, string expected)
{
- var sut = KuddleGrammar.QuotedString;
+ var sut = KdlGrammar.QuotedString;
bool success = sut.TryParse(input, out var value);
@@ -271,7 +271,7 @@ public async Task QuotedString_HandlesUnicodeEscapes(string input, string expect
)]
public async Task QuotedString_HandlesWhitespaceEscapes(string input)
{
- var sut = KuddleGrammar.QuotedString;
+ var sut = KdlGrammar.QuotedString;
bool success = sut.TryParse(input, out var value, out var error);
@@ -283,7 +283,7 @@ public async Task QuotedString_HandlesWhitespaceEscapes(string input)
[Test]
public async Task RawString_ParsesSimpleRawString()
{
- var sut = KuddleGrammar.RawString;
+ var sut = KdlGrammar.RawString;
var input = """
#"\n will be literal"#
@@ -297,7 +297,7 @@ public async Task RawString_ParsesSimpleRawString()
[Test]
public async Task RawString_ParsesRawStringWithQuotes()
{
- var sut = KuddleGrammar.RawString;
+ var sut = KdlGrammar.RawString;
var input = "#\"content with \"quotes\"\"#";
bool success = sut.TryParse(input, out var value);
@@ -309,7 +309,7 @@ public async Task RawString_ParsesRawStringWithQuotes()
[Test]
public async Task RawString_HandlesMultipleHashDelimiters()
{
- var sut = KuddleGrammar.RawString;
+ var sut = KdlGrammar.RawString;
var input = """
##"hello\n\r\asd"#world"##
@@ -329,7 +329,7 @@ await Assert
[Test]
public async Task RawString_ParsesMultiLineRawString()
{
- var sut = KuddleGrammar.RawString;
+ var sut = KdlGrammar.RawString;
var input = """""
#"""
@@ -354,7 +354,7 @@ without escapes.
[Test]
public async Task IdentifierString_SetsStyleToBare()
{
- var sut = KuddleGrammar.IdentifierString;
+ var sut = KdlGrammar.IdentifierString;
var input = "bare_identifier";
bool success = sut.TryParse(input, out var value);
@@ -367,7 +367,7 @@ public async Task IdentifierString_SetsStyleToBare()
[Test]
public async Task QuotedString_SetsStyleToQuoted()
{
- var sut = KuddleGrammar.QuotedString;
+ var sut = KdlGrammar.QuotedString;
var input = "\"quoted value\"";
bool success = sut.TryParse(input, out var value);
@@ -381,7 +381,7 @@ public async Task QuotedString_SetsStyleToQuoted()
[Test]
public async Task MultiLineString_SetsStyleToMultiline()
{
- var sut = KuddleGrammar.MultiLineQuoted;
+ var sut = KdlGrammar.MultiLineQuoted;
var input = """"
"""
content
@@ -399,7 +399,7 @@ public async Task MultiLineString_SetsStyleToMultiline()
[Test]
public async Task RawString_SingleLine_SetsStyleToRawAndQuoted()
{
- var sut = KuddleGrammar.RawString;
+ var sut = KdlGrammar.RawString;
var input = "#\"\"raw content\"\"#";
bool success = sut.TryParse(input, out var value);
@@ -416,7 +416,7 @@ public async Task RawString_SingleLine_SetsStyleToRawAndQuoted()
[Test]
public async Task RawString_MultiLine_SetsStyleToRawAndMultiline()
{
- var sut = KuddleGrammar.RawString;
+ var sut = KdlGrammar.RawString;
var input = """"
#"""
multi
@@ -438,7 +438,7 @@ public async Task RawString_MultiLine_SetsStyleToRawAndMultiline()
[Test]
public async Task String_UnifiedParser_DetectsBare()
{
- var sut = KuddleGrammar.String;
+ var sut = KdlGrammar.String;
var input = "node_name";
bool success = sut.TryParse(input, out var value);
@@ -450,7 +450,7 @@ public async Task String_UnifiedParser_DetectsBare()
[Test]
public async Task String_UnifiedParser_DetectsQuoted()
{
- var sut = KuddleGrammar.String;
+ var sut = KdlGrammar.String;
var input = "\"node name\"";
bool success = sut.TryParse(input, out var value);
@@ -462,7 +462,7 @@ public async Task String_UnifiedParser_DetectsQuoted()
[Test]
public async Task String_UnifiedParser_DetectsRaw()
{
- var sut = KuddleGrammar.String;
+ var sut = KdlGrammar.String;
var input = @"#""node name""#";
bool success = sut.TryParse(input, out var value);
diff --git a/src/Kuddle.Tests/Grammar/WhiteSpaceParsersTests.cs b/src/Kuddle.Net.Tests/Grammar/WhiteSpaceParsersTests.cs
similarity index 91%
rename from src/Kuddle.Tests/Grammar/WhiteSpaceParsersTests.cs
rename to src/Kuddle.Net.Tests/Grammar/WhiteSpaceParsersTests.cs
index 2613baa..4dd9a40 100644
--- a/src/Kuddle.Tests/Grammar/WhiteSpaceParsersTests.cs
+++ b/src/Kuddle.Net.Tests/Grammar/WhiteSpaceParsersTests.cs
@@ -33,7 +33,7 @@ public class WhiteSpaceParsersTests
[Arguments('\u3000')]
public async Task Ws_ParsesUnicodeSpace(char input)
{
- var sut = KuddleGrammar.Ws;
+ var sut = KdlGrammar.Ws;
bool success = sut.TryParse(input.ToString(), out var value);
@@ -44,7 +44,7 @@ public async Task Ws_ParsesUnicodeSpace(char input)
[Test]
public async Task Ws_ParsesMultiLineComment()
{
- var sut = KuddleGrammar.Ws;
+ var sut = KdlGrammar.Ws;
var input = "/* comment */";
bool success = sut.TryParse(input, out var value);
@@ -56,7 +56,7 @@ public async Task Ws_ParsesMultiLineComment()
[Test]
public async Task EscLine_ParsesBackslashContinuation()
{
- var sut = KuddleGrammar.EscLine;
+ var sut = KdlGrammar.EscLine;
var input =
@"\
@@ -69,7 +69,7 @@ public async Task EscLine_ParsesBackslashContinuation()
[Test]
public async Task EscLine_ParsesBackslashWithComment()
{
- var sut = KuddleGrammar.EscLine;
+ var sut = KdlGrammar.EscLine;
var input = @"\ // comment";
bool success = sut.TryParse(input, out var value);
@@ -81,7 +81,7 @@ public async Task EscLine_ParsesBackslashWithComment()
[Test]
public async Task LineSpace_ParsesWhitespace()
{
- var sut = KuddleGrammar.LineSpace;
+ var sut = KdlGrammar.LineSpace;
var input = " ";
bool success = sut.TryParse(input, out var value);
@@ -93,7 +93,7 @@ public async Task LineSpace_ParsesWhitespace()
[Test]
public async Task LineSpace_ParsesNewLine()
{
- var sut = KuddleGrammar.LineSpace;
+ var sut = KdlGrammar.LineSpace;
var input = "\n";
bool success = sut.TryParse(input, out var value);
@@ -105,7 +105,7 @@ public async Task LineSpace_ParsesNewLine()
[Test]
public async Task LineSpace_ParsesComment()
{
- var sut = KuddleGrammar.LineSpace;
+ var sut = KdlGrammar.LineSpace;
var input = "// comment";
bool success = sut.TryParse(input, out var value);
@@ -117,7 +117,7 @@ public async Task LineSpace_ParsesComment()
[Test]
public async Task NodeSpace_ParsesSimpleWhitespace()
{
- var sut = KuddleGrammar.NodeSpace;
+ var sut = KdlGrammar.NodeSpace;
var input = " ";
bool success = sut.TryParse(input, out var value);
diff --git a/src/Kuddle.Tests/Kuddle.Tests.csproj b/src/Kuddle.Net.Tests/Kuddle.Net.Tests.csproj
similarity index 78%
rename from src/Kuddle.Tests/Kuddle.Tests.csproj
rename to src/Kuddle.Net.Tests/Kuddle.Net.Tests.csproj
index 765c78f..af186aa 100644
--- a/src/Kuddle.Tests/Kuddle.Tests.csproj
+++ b/src/Kuddle.Net.Tests/Kuddle.Net.Tests.csproj
@@ -1,5 +1,7 @@
+ Kuddle.Tests
+ Kuddle.Net.Tests
enable
enable
Exe
@@ -10,7 +12,7 @@
-
+
Plugins { get; set; } = new();
+
+ [KdlNode("logging")]
+ public LogSettings? Logging { get; set; }
+
+ [KdlNode("experiments")]
+ public Experiments? Experiments { get; set; }
+ }
+
+ class Plugin
+ {
+ [KdlArgument(0)]
+ public string Name { get; set; } = "";
+ }
+
+ class LogSettings
+ {
+ [KdlNode("level")]
+ public string LogLevel { get; set; } = "info";
+ }
+
+ class Experiments
+ {
+ [KdlProperty("enabled")]
+ public bool Enabled { get; set; }
+ }
+
+ // --- Tests ---
+
+ [Test]
+ public async Task Deserialize_Document_MapsListsAndSingleObjects()
+ {
+ var kdl = """
+ plugin "Analytics"
+ plugin "Authentication"
+
+ logging {
+ level "debug"
+ }
+ """;
+
+ var result = KdlSerializer.Deserialize(kdl);
+
+ // Assert
+ await Assert.That(result.Plugins).Count().IsEqualTo(2);
+ await Assert.That(result.Plugins[0].Name).IsEqualTo("Analytics");
+ await Assert.That(result.Plugins[1].Name).IsEqualTo("Authentication");
+
+ await Assert.That(result.Logging).IsNotNull();
+
+ await Assert.That(result.Logging!.LogLevel).IsEqualTo("debug");
+ }
+
+ [Test]
+ public async Task Deserialize_EmptyDocument_ReturnsInitializedObject()
+ {
+ var kdl = "";
+
+ var result = KdlSerializer.Deserialize(kdl);
+
+ await Assert.That(result).IsNotNull();
+ await Assert.That(result.Plugins).IsEmpty();
+ await Assert.That(result.Logging).IsNull();
+ }
+
+ [Test]
+ public async Task Deserialize_PartialMatch_IgnoresUnmappedNodes()
+ {
+ var kdl = """
+ plugin "Core"
+
+ // This node is not in AppConfig
+ garbage_data {
+ ignore me
+ }
+ """;
+
+ var result = KdlSerializer.Deserialize(kdl);
+
+ await Assert.That(result.Plugins).Count().IsEqualTo(1);
+ await Assert.That(result.Plugins[0].Name).IsEqualTo("Core");
+
+ await Assert.That(result.Logging).IsNull();
+ }
+
+ [Test]
+ public async Task Deserialize_NestedStructure_WithProperties()
+ {
+ var kdl =
+ @"
+ experiments enabled=#true
+ ";
+
+ var result = KdlSerializer.Deserialize(kdl);
+
+ await Assert.That(result.Experiments).IsNotNull();
+ await Assert.That(result.Experiments!.Enabled).IsTrue();
+ }
+
+ [Test]
+ public async Task Deserialize_AmbiguousSingleNode_ThrowsOrHandles()
+ {
+ var kdl =
+ @"
+ logging { level ""info"" }
+ logging { level ""error"" }
+ ";
+
+ await Assert.ThrowsAsync(async () =>
+ {
+ KdlSerializer.Deserialize(kdl);
+ });
+ }
+}
diff --git a/src/Kuddle.Tests/Serialization/KuddleParsingTests.cs b/src/Kuddle.Net.Tests/Serialization/KuddleParsingTests.cs
similarity index 77%
rename from src/Kuddle.Tests/Serialization/KuddleParsingTests.cs
rename to src/Kuddle.Net.Tests/Serialization/KuddleParsingTests.cs
index 9cdc429..57ad418 100644
--- a/src/Kuddle.Tests/Serialization/KuddleParsingTests.cs
+++ b/src/Kuddle.Net.Tests/Serialization/KuddleParsingTests.cs
@@ -4,7 +4,7 @@ namespace Kuddle.Tests.Serialization;
public class KuddleParsingTests
{
- readonly KuddleWriterOptions _options = new KuddleWriterOptions() with { RoundTrip = false };
+ readonly KdlWriterOptions _options = new KdlWriterOptions() with { RoundTrip = false };
[Test]
[MethodDataSource(
@@ -16,7 +16,7 @@ public async Task TestBlockComment(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -24,7 +24,7 @@ public async Task TestBlockComment(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -38,7 +38,7 @@ public async Task TestEscline(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -46,7 +46,7 @@ public async Task TestEscline(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -60,7 +60,7 @@ public async Task TestMultilineRawString(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -68,7 +68,7 @@ public async Task TestMultilineRawString(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -82,7 +82,7 @@ public async Task TestMultilineString(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -90,18 +90,21 @@ public async Task TestMultilineString(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.ArgTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.ArgTestData)
+ )]
public async Task TestArg(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options); // Assumes KdlDocument has ToString() for serialization
@@ -109,7 +112,7 @@ public async Task TestArg(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -123,7 +126,7 @@ public async Task TestBareIdent(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -131,7 +134,7 @@ public async Task TestBareIdent(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -145,7 +148,7 @@ public async Task TestBinary(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -153,18 +156,21 @@ public async Task TestBinary(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.BlankTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.BlankTestData)
+ )]
public async Task TestBlank(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -172,7 +178,7 @@ public async Task TestBlank(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -186,7 +192,7 @@ public async Task TestBoolean(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -194,18 +200,21 @@ public async Task TestBoolean(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.BomTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.BomTestData)
+ )]
public async Task TestBom(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -213,7 +222,7 @@ public async Task TestBom(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -227,7 +236,7 @@ public async Task TestComment(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -235,7 +244,7 @@ public async Task TestComment(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -249,7 +258,7 @@ public async Task TestCommented(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -257,18 +266,21 @@ public async Task TestCommented(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.EmptyTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.EmptyTestData)
+ )]
public async Task TestEmpty(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -276,18 +288,21 @@ public async Task TestEmpty(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.EscTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.EscTestData)
+ )]
public async Task TestEsc(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -295,18 +310,21 @@ public async Task TestEsc(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.FalseTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.FalseTestData)
+ )]
public async Task TestFalse(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -314,7 +332,7 @@ public async Task TestFalse(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -328,7 +346,7 @@ public async Task TestIllegal(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -336,7 +354,7 @@ public async Task TestIllegal(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -350,7 +368,7 @@ public async Task TestBareEmoji(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -358,18 +376,21 @@ public async Task TestBareEmoji(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.AllTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.AllTestData)
+ )]
public async Task TestAll(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -377,7 +398,7 @@ public async Task TestAll(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -391,7 +412,7 @@ public async Task TestAsterisk(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -399,7 +420,7 @@ public async Task TestAsterisk(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -413,7 +434,7 @@ public async Task TestBraces(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -421,7 +442,7 @@ public async Task TestBraces(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -435,7 +456,7 @@ public async Task TestChevrons(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -443,18 +464,21 @@ public async Task TestChevrons(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.CommaTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.CommaTestData)
+ )]
public async Task TestComma(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -462,18 +486,21 @@ public async Task TestComma(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.CrlfTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.CrlfTestData)
+ )]
public async Task TestCrlf(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -481,18 +508,21 @@ public async Task TestCrlf(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.DashTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.DashTestData)
+ )]
public async Task TestDash(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -500,18 +530,21 @@ public async Task TestDash(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.DotTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.DotTestData)
+ )]
public async Task TestDot(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -519,18 +552,21 @@ public async Task TestDot(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.EmojiTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.EmojiTestData)
+ )]
public async Task TestEmoji(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -538,18 +574,21 @@ public async Task TestEmoji(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.EofTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.EofTestData)
+ )]
public async Task TestEof(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -557,18 +596,21 @@ public async Task TestEof(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.ErrTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.ErrTestData)
+ )]
public async Task TestErr(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -576,7 +618,7 @@ public async Task TestErr(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -590,7 +632,7 @@ public async Task TestEscaped(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -598,18 +640,21 @@ public async Task TestEscaped(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.HexTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.HexTestData)
+ )]
public async Task TestHex(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -617,7 +662,7 @@ public async Task TestHex(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
@@ -631,7 +676,7 @@ public async Task TestInitial(ParsingTestData testData)
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -639,18 +684,21 @@ public async Task TestInitial(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.IntTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.IntTestData)
+ )]
public async Task TestInt(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -658,18 +706,21 @@ public async Task TestInt(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
[Test]
- [MethodDataSource(typeof(KuddleParsingTestDataSources), nameof(KuddleParsingTestDataSources.JustTestData))]
+ [MethodDataSource(
+ typeof(KuddleParsingTestDataSources),
+ nameof(KuddleParsingTestDataSources.JustTestData)
+ )]
public async Task TestJust(ParsingTestData testData)
{
if (File.Exists(testData.ExpectedFile))
{
var inputKdl = await File.ReadAllTextAsync(testData.InputFile);
- var doc = KuddleReader.Parse(inputKdl);
+ var doc = KdlReader.Read(inputKdl);
var expected = await File.ReadAllTextAsync(testData.ExpectedFile);
expected = expected.Replace("\r\n", "\n");
var serialized = doc.ToString(_options);
@@ -677,7 +728,7 @@ public async Task TestJust(ParsingTestData testData)
}
else
{
- Assert.Throws(() => KuddleReader.Parse(testData.InputFile));
+ Assert.Throws(() => KdlReader.Read(testData.InputFile));
}
}
}
diff --git a/src/Kuddle.Tests/Serialization/KuddleWriterTests.cs b/src/Kuddle.Net.Tests/Serialization/KuddleWriterTests.cs
similarity index 76%
rename from src/Kuddle.Tests/Serialization/KuddleWriterTests.cs
rename to src/Kuddle.Net.Tests/Serialization/KuddleWriterTests.cs
index 357858c..ed5bb09 100644
--- a/src/Kuddle.Tests/Serialization/KuddleWriterTests.cs
+++ b/src/Kuddle.Net.Tests/Serialization/KuddleWriterTests.cs
@@ -10,9 +10,9 @@ public class KuddleWriterTests
public async Task Write_SimpleNode_FormatsCorrectly()
{
var kdl = "node 1 2 key=\"val\"";
- var doc = KuddleReader.Parse(kdl);
+ var doc = KdlReader.Read(kdl);
- var output = KuddleWriter.Write(doc, KuddleWriterOptions.Default);
+ var output = KdlWriter.Write(doc, KdlWriterOptions.Default);
await Assert.That(output.Trim()).IsEqualTo("node 1 2 key=\"val\"");
}
@@ -21,9 +21,9 @@ public async Task Write_SimpleNode_FormatsCorrectly()
public async Task Write_NestedStructure_IndentsCorrectly()
{
var kdl = "parent { child; }";
- var doc = KuddleReader.Parse(kdl);
+ var doc = KdlReader.Read(kdl);
- var output = KuddleWriter.Write(doc);
+ var output = KdlWriter.Write(doc);
var expected = @"parent {
child;
@@ -36,9 +36,9 @@ public async Task Write_NestedStructure_IndentsCorrectly()
public async Task Write_ComplexString_EscapesCorrectly()
{
var kdl = "node \"line1\\nline2\"";
- var doc = KuddleReader.Parse(kdl);
+ var doc = KdlReader.Read(kdl);
- var output = KuddleWriter.Write(doc);
+ var output = KdlWriter.Write(doc);
await Assert.That(output.Trim()).IsEqualTo("node \"line1\\nline2\"");
}
@@ -51,7 +51,7 @@ public async Task Write_BareIdentifier_QuotesIfInvalid()
Nodes = [new KdlNode(new KdlString("node name", StringKind.Quoted))],
};
- var output = KuddleWriter.Write(doc);
+ var output = KdlWriter.Write(doc);
await Assert.That(output.Trim()).IsEqualTo("\"node name\"");
}
diff --git a/src/Kuddle.Net.Tests/Serialization/NodeToObjectTests.cs b/src/Kuddle.Net.Tests/Serialization/NodeToObjectTests.cs
new file mode 100644
index 0000000..62933b1
--- /dev/null
+++ b/src/Kuddle.Net.Tests/Serialization/NodeToObjectTests.cs
@@ -0,0 +1,107 @@
+using Kuddle.Exceptions;
+using Kuddle.Serialization;
+
+namespace Kuddle.Tests.Serialization;
+
+public class NodeToObjectTests
+{
+ [KdlType("database")]
+ class DbConfig
+ {
+ [KdlArgument(0)]
+ public string Name { get; set; } = "";
+
+ [KdlProperty("port")]
+ public int Port { get; set; }
+
+ [KdlProperty("enabled")]
+ public bool Enabled { get; set; } = true;
+ }
+
+ public class Server
+ {
+ [KdlArgument(0)]
+ public string Host { get; set; } = "";
+ }
+
+ [Test]
+ public async Task Deserialize_ExplicitName_MapsArgumentsAndProperties()
+ {
+ var kdl = "database production port=5432 enabled=#false";
+
+ var result = KdlSerializer.Deserialize(kdl);
+
+ await Assert.That(result).IsNotNull();
+ await Assert.That(result.Name).IsEqualTo("production");
+ await Assert.That(result.Port).IsEqualTo(5432);
+ await Assert.That(result.Enabled).IsFalse();
+ }
+
+ [Test]
+ public async Task Deserialize_ImplicitName_UsesClassName()
+ {
+ var kdl = "Server \"localhost\"";
+
+ var result = KdlSerializer.Deserialize(kdl);
+
+ await Assert.That(result).IsNotNull();
+ await Assert.That(result.Host).IsEqualTo("localhost");
+ }
+
+ [Test]
+ public async Task Deserialize_MissingProperty_UsesDefault()
+ {
+ var kdl = "database \"local\" port=3000";
+
+ var result = KdlSerializer.Deserialize(kdl);
+
+ await Assert.That(result.Name).IsEqualTo("local");
+ await Assert.That(result.Enabled).IsTrue();
+ }
+
+ [Test]
+ public async Task Deserialize_MismatchNodeName_Throws()
+ {
+ var kdl = "table \"production\" port=5432";
+
+ await Assert.ThrowsAsync(async () =>
+ {
+ KdlSerializer.Deserialize(kdl);
+ });
+ }
+
+ [Test]
+ public async Task Deserialize_MultipleRootNodes_Throws()
+ {
+ var kdl =
+ @"
+ database ""primary"" port=5432
+ database ""replica"" port=5433
+ ";
+
+ await Assert.ThrowsAsync(async () =>
+ {
+ KdlSerializer.Deserialize(kdl);
+ });
+ }
+
+ [Test]
+ public async Task Deserialize_TypeMismatch_Throws()
+ {
+ var kdl = "database \"db\" port=\"not-a-number\"";
+
+ await Assert.ThrowsAsync(async () =>
+ {
+ KdlSerializer.Deserialize(kdl);
+ });
+ }
+
+ [Test]
+ public async Task Deserialize_DocumentRoot_RejectsProperties()
+ {
+ var kdl = "database \"db\" port=5432 unknown_prop=123";
+
+ var result = KdlSerializer.Deserialize(kdl);
+ await Assert.That(result.Port).IsEqualTo(5432);
+ }
+}
diff --git a/src/Kuddle.Tests/Serialization/ObjectMapperTests.cs b/src/Kuddle.Net.Tests/Serialization/ObjectMapperTests.cs
similarity index 86%
rename from src/Kuddle.Tests/Serialization/ObjectMapperTests.cs
rename to src/Kuddle.Net.Tests/Serialization/ObjectMapperTests.cs
index 27dd4a8..718408c 100644
--- a/src/Kuddle.Tests/Serialization/ObjectMapperTests.cs
+++ b/src/Kuddle.Net.Tests/Serialization/ObjectMapperTests.cs
@@ -1,11 +1,10 @@
using Kuddle.AST;
-using Kuddle.Exceptions;
using Kuddle.Serialization;
namespace Kuddle.Tests.Serialization;
///
-/// Tests for await KdlSerializer.Deserialize() and KdlSerializer.Serialize()
+/// Tests for KdlSerializer.Deserialize() and KdlSerializer.Serialize()
/// which map between KDL documents and strongly-typed C# objects.
///
public class ObjectMapperTests
@@ -21,7 +20,7 @@ public async Task DeserializeSimpleObject_WithArgument_MapsCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Name).IsEqualTo("my-lib");
@@ -36,7 +35,7 @@ public async Task DeserializeSimpleObject_WithProperties_MapsCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Name).IsEqualTo("my-lib");
@@ -53,7 +52,7 @@ public async Task DeserializeObject_WithMissingOptionalProperty_UsesDefault()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Description).IsNull();
@@ -77,7 +76,7 @@ public async Task DeserializeObject_WithChildren_MapsChildListCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Name).IsEqualTo("my-app");
@@ -101,7 +100,7 @@ public async Task DeserializeObject_WithMultipleChildTypes_MapsEachTypeToCorrect
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Dependencies).Count().IsEqualTo(2);
@@ -119,7 +118,7 @@ public async Task DeserializeObject_WithNoChildren_InitializesEmptyLists()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Dependencies).IsEmpty();
@@ -139,7 +138,7 @@ public async Task DeserializeObject_WithIntProperty_MapsCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Timeout).IsEqualTo(5000);
@@ -154,7 +153,7 @@ public async Task DeserializeObject_WithLongProperty_MapsCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Retries).IsEqualTo(long.MaxValue);
@@ -169,7 +168,7 @@ public async Task DeserializeObject_WithDoubleProperty_MapsCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Ratio).IsEqualTo(3.14159).Within(0.00001);
@@ -184,7 +183,7 @@ public async Task DeserializeObject_WithBoolProperty_MapsCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Enabled).IsTrue();
@@ -199,7 +198,7 @@ public async Task DeserializeObject_WithAllNumericTypes_MapsAllCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Timeout).IsEqualTo(500);
@@ -222,7 +221,7 @@ public async Task DeserializeObject_WithGuidProperty_ParsesUuidTypeAnnotation()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Username).IsEqualTo("alice");
@@ -239,7 +238,7 @@ public async Task DeserializeObject_WithDateTimeProperty_ParsesDateTimeTypeAnnot
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.CreatedAt).IsEqualTo(now);
@@ -309,7 +308,7 @@ public async Task RoundTrip_SimpleObject_PreservesData()
// Act
var kdl = KdlSerializer.Serialize(original);
- var deserialized = await KdlSerializer.Deserialize(kdl);
+ var deserialized = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(deserialized.Name).IsEqualTo(original.Name);
@@ -344,7 +343,7 @@ public async Task RoundTrip_NestedObject_PreservesData()
// Act
var kdl = KdlSerializer.Serialize(original);
- var deserialized = await KdlSerializer.Deserialize(kdl);
+ var deserialized = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(deserialized.Name).IsEqualTo(original.Name);
@@ -366,7 +365,7 @@ public async Task RoundTrip_NestedObject_PreservesData()
// """;
// // Act
- // var result = await KdlSerializer.Deserialize(kdl);
+ // var result = KdlSerializer.Deserialize(kdl);
// // Assert
// await Assert.That(result).IsOfType(typeof(FileResource));
@@ -383,7 +382,7 @@ public async Task RoundTrip_NestedObject_PreservesData()
// """;
// // Act
- // var result = await KdlSerializer.Deserialize(kdl);
+ // var result = KdlSerializer.Deserialize(kdl);
// // Assert
// await Assert.That(result).IsOfType(typeof(UrlResource));
@@ -404,7 +403,7 @@ public async Task DeserializeObject_WithEmptyString_MapsCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Name).IsEqualTo("");
@@ -420,7 +419,7 @@ public async Task DeserializeObject_WithSpecialCharactersInString_MapsCorrectly(
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Name).IsEqualTo("my-lib@1.0");
@@ -436,7 +435,7 @@ public async Task DeserializeObject_WithNegativeNumbers_MapsCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Timeout).IsEqualTo(-1000);
@@ -452,7 +451,7 @@ public async Task DeserializeObject_WithHexNumbers_MapsCorrectly()
""";
// Act
- var result = await KdlSerializer.Deserialize(kdl);
+ var result = KdlSerializer.Deserialize(kdl);
// Assert
await Assert.That(result.Timeout).IsEqualTo(255);
@@ -473,7 +472,7 @@ public async Task DeserializeObject_WithWrongNodeName_ThrowsException()
// Act & Assert
await Assert
- .That(async () => await KdlSerializer.Deserialize(kdl))
+ .That(async () => KdlSerializer.Deserialize(kdl))
.Throws();
}
@@ -489,7 +488,7 @@ public async Task DeserializeToScalar_WithMultipleRootNodes_ThrowsException()
// Act & Assert
await Assert
- .That(async () => await KdlSerializer.Deserialize(kdl))
+ .That(async () => KdlSerializer.Deserialize(kdl))
.Throws();
}
@@ -505,7 +504,7 @@ public async Task DeserializeToDictionary_ThrowsException()
// Act & Assert
await Assert
- .That(async () => await KdlSerializer.Deserialize>(kdl))
+ .That(() => KdlSerializer.Deserialize>(kdl))
.Throws()
.WithMessageContaining("not supported");
}
@@ -522,7 +521,7 @@ public async Task DeserializeToEnumerable_WithDifferentNodeNames_ThrowsException
// Act & Assert
await Assert
- .That(async () => await KdlSerializer.Deserialize>(kdl))
+ .That(async () => KdlSerializer.Deserialize>(kdl))
.Throws();
}
@@ -536,7 +535,7 @@ public async Task DeserializeObject_WithInvalidNumericValue_ThrowsException()
// Act & Assert
await Assert
- .That(async () => await KdlSerializer.Deserialize(kdl))
+ .That(async () => KdlSerializer.Deserialize(kdl))
.Throws();
}
@@ -550,24 +549,24 @@ public async Task DeserializeObject_WithMissingRequiredArgument_ThrowsException(
// Act & Assert
await Assert
- .That(async () => await KdlSerializer.Deserialize(kdl))
+ .That(async () => KdlSerializer.Deserialize(kdl))
.Throws();
}
- [Test]
- public async Task DeserializeObject_WhenTargetIsSimpleValue_ThrowsException()
- {
- // Arrange
- var kdl = """
- package
- """;
+ // [Test]
+ // public async Task DeserializeObject_WhenTargetIsSimpleValue_ThrowsException()
+ // {
+ // // Arrange
+ // var kdl = """
+ // package
+ // """;
- // Act & Assert
- await Assert
- .That(async () => await KdlSerializer.Deserialize(kdl))
- .Throws()
- .WithMessageContaining("Cannot deserialize type");
- }
+ // // Act & Assert
+ // await Assert
+ // .That(async () => KdlSerializer.Deserialize(kdl))
+ // .Throws()
+ // .WithMessageContaining("Cannot deserialize type");
+ // }
#endregion
#region Test Models
@@ -594,10 +593,10 @@ public class Project
[KdlProperty("version")]
public string Version { get; set; } = "1.0.0";
- [KdlChildren("dependency")]
+ [KdlNode("dependency")]
public List Dependencies { get; set; } = [];
- [KdlChildren("devDependency")]
+ [KdlNode("devDependency")]
public List DevDependencies { get; set; } = [];
}
diff --git a/src/Kuddle.Net.Tests/Serialization/TypeAnnotationTests.cs b/src/Kuddle.Net.Tests/Serialization/TypeAnnotationTests.cs
new file mode 100644
index 0000000..20a3c6f
--- /dev/null
+++ b/src/Kuddle.Net.Tests/Serialization/TypeAnnotationTests.cs
@@ -0,0 +1,227 @@
+using System;
+using Kuddle.Serialization;
+
+namespace Kuddle.Tests.Serialization;
+
+public class TypeAnnotationTests
+{
+ #region Test Models
+
+ public class PersonWithAnnotations
+ {
+ [KdlArgument(0, "uuid")]
+ public Guid Id { get; set; }
+
+ [KdlProperty("name")]
+ public string Name { get; set; } = "";
+
+ [KdlProperty("created", "date-time")]
+ public DateTimeOffset CreatedAt { get; set; }
+
+ [KdlProperty("age", "i32")]
+ public int Age { get; set; }
+ }
+
+ public class ProductWithTypeAnnotations
+ {
+ [KdlArgument(0)]
+ public string Name { get; set; } = "";
+
+ [KdlProperty("sku", "uuid")]
+ public Guid Sku { get; set; }
+
+ [KdlProperty("price", "decimal64")]
+ public decimal Price { get; set; }
+
+ [KdlProperty("stock", "u32")]
+ public uint StockCount { get; set; }
+ }
+
+ public class EventWithChildAnnotations
+ {
+ [KdlArgument(0)]
+ public string Name { get; set; } = "";
+
+ [KdlNode("timestamp", "date-time")]
+ public DateTimeOffset Timestamp { get; set; }
+
+ [KdlNode("correlation-id", "uuid")]
+ public Guid CorrelationId { get; set; }
+ }
+
+ #endregion
+
+ [Test]
+ public async Task Serialize_WithUuidTypeAnnotation_WritesAnnotation()
+ {
+ // Arrange
+ var person = new PersonWithAnnotations
+ {
+ Id = Guid.Parse("123e4567-e89b-12d3-a456-426614174000"),
+ Name = "Alice",
+ CreatedAt = new DateTimeOffset(2024, 1, 1, 0, 0, 0, TimeSpan.Zero),
+ Age = 30,
+ };
+
+ // Act
+ var kdl = KdlSerializer.Serialize(person);
+
+ // Assert
+ await Assert.That(kdl).Contains("(uuid)\"123e4567-e89b-12d3-a456-426614174000\"");
+ await Assert.That(kdl).Contains("(date-time)\"2024-01-01T00:00:00.0000000+00:00\"");
+ await Assert.That(kdl).Contains("(i32)30");
+ }
+
+ [Test]
+ public async Task Deserialize_WithUuidTypeAnnotation_ParsesCorrectly()
+ {
+ // Arrange
+ var kdl = """
+ personwithannotations (uuid)"123e4567-e89b-12d3-a456-426614174000" name="Alice" created=(date-time)"2024-01-01T00:00:00.0000000+00:00" age=(i32)30
+ """;
+
+ // Act
+ var person = KdlSerializer.Deserialize(kdl);
+
+ // Assert
+ await Assert.That(person.Id).IsEqualTo(Guid.Parse("123e4567-e89b-12d3-a456-426614174000"));
+ await Assert.That(person.Name).IsEqualTo("Alice");
+ await Assert
+ .That(person.CreatedAt)
+ .IsEqualTo(new DateTimeOffset(2024, 1, 1, 0, 0, 0, TimeSpan.Zero));
+ await Assert.That(person.Age).IsEqualTo(30);
+ }
+
+ [Test]
+ public async Task Serialize_WithMixedTypeAnnotations_WritesAllAnnotations()
+ {
+ // Arrange
+ var product = new ProductWithTypeAnnotations
+ {
+ Name = "Widget",
+ Sku = Guid.Parse("a1b2c3d4-e5f6-7890-abcd-ef1234567890"),
+ Price = 99.99m,
+ StockCount = 42,
+ };
+
+ // Act
+ var kdl = KdlSerializer.Serialize(product);
+
+ // Assert
+ await Assert.That(kdl).Contains("Widget");
+ await Assert.That(kdl).Contains("(uuid)\"a1b2c3d4-e5f6-7890-abcd-ef1234567890\"");
+ await Assert.That(kdl).Contains("(decimal64)99.99");
+ await Assert.That(kdl).Contains("(u32)42");
+ }
+
+ [Test]
+ public async Task Deserialize_WithMixedTypeAnnotations_ParsesAllValues()
+ {
+ // Arrange
+ var kdl = """
+ productwithtypeannotations "Widget" sku=(uuid)"a1b2c3d4-e5f6-7890-abcd-ef1234567890" price=(decimal64)99.99 stock=(u32)42
+ """;
+
+ // Act
+ var product = KdlSerializer.Deserialize(kdl);
+
+ // Assert
+ await Assert.That(product.Name).IsEqualTo("Widget");
+ await Assert
+ .That(product.Sku)
+ .IsEqualTo(Guid.Parse("a1b2c3d4-e5f6-7890-abcd-ef1234567890"));
+ await Assert.That(product.Price).IsEqualTo(99.99m);
+ await Assert.That(product.StockCount).IsEqualTo(42u);
+ }
+
+ [Test]
+ public async Task Serialize_WithChildNodeAnnotations_WritesAnnotationsOnChildren()
+ {
+ // Arrange
+ var evt = new EventWithChildAnnotations
+ {
+ Name = "UserLoggedIn",
+ Timestamp = new DateTimeOffset(2024, 12, 17, 10, 30, 0, TimeSpan.Zero),
+ CorrelationId = Guid.Parse("11111111-2222-3333-4444-555555555555"),
+ };
+
+ // Act
+ var kdl = KdlSerializer.Serialize(evt);
+
+ // Assert
+ await Assert
+ .That(kdl)
+ .Contains("timestamp (date-time)\"2024-12-17T10:30:00.0000000+00:00\"");
+ await Assert
+ .That(kdl)
+ .Contains("correlation-id (uuid)\"11111111-2222-3333-4444-555555555555\"");
+ }
+
+ [Test]
+ public async Task Deserialize_WithChildNodeAnnotations_ParsesChildValues()
+ {
+ // Arrange
+ var kdl = """
+ eventwithchildannotations "UserLoggedIn" {
+ timestamp (date-time)"2024-12-17T10:30:00.0000000+00:00"
+ correlation-id (uuid)"11111111-2222-3333-4444-555555555555"
+ }
+ """;
+
+ // Act
+ var evt = KdlSerializer.Deserialize(kdl);
+
+ // Assert
+ await Assert.That(evt.Name).IsEqualTo("UserLoggedIn");
+ await Assert
+ .That(evt.Timestamp)
+ .IsEqualTo(new DateTimeOffset(2024, 12, 17, 10, 30, 0, TimeSpan.Zero));
+ await Assert
+ .That(evt.CorrelationId)
+ .IsEqualTo(Guid.Parse("11111111-2222-3333-4444-555555555555"));
+ }
+
+ [Test]
+ public async Task RoundTrip_WithTypeAnnotations_PreservesValues()
+ {
+ // Arrange
+ var original = new PersonWithAnnotations
+ {
+ Id = Guid.NewGuid(),
+ Name = "Bob",
+ CreatedAt = DateTimeOffset.UtcNow,
+ Age = 25,
+ };
+
+ // Act
+ var kdl = KdlSerializer.Serialize(original);
+ var deserialized = KdlSerializer.Deserialize(kdl);
+
+ // Assert
+ await Assert.That(deserialized.Id).IsEqualTo(original.Id);
+ await Assert.That(deserialized.Name).IsEqualTo(original.Name);
+ await Assert.That(deserialized.CreatedAt).IsEqualTo(original.CreatedAt);
+ await Assert.That(deserialized.Age).IsEqualTo(original.Age);
+ }
+
+ [Test]
+ public async Task Deserialize_WithoutTypeAnnotationInKdl_StillWorks()
+ {
+ // Arrange - KDL without type annotation, but C# model has [KdlTypeAnnotation]
+ // The deserializer should still work because Guid/DateTimeOffset have their own parsing logic
+ var kdl = """
+ personwithannotations "123e4567-e89b-12d3-a456-426614174000" name="Alice" created="2024-01-01T00:00:00.0000000+00:00" age=30
+ """;
+
+ // Act
+ var person = KdlSerializer.Deserialize(kdl);
+
+ // Assert - should parse without type annotations in the KDL
+ await Assert.That(person.Id).IsEqualTo(Guid.Parse("123e4567-e89b-12d3-a456-426614174000"));
+ await Assert.That(person.Name).IsEqualTo("Alice");
+ await Assert
+ .That(person.CreatedAt)
+ .IsEqualTo(new DateTimeOffset(2024, 1, 1, 0, 0, 0, TimeSpan.Zero));
+ await Assert.That(person.Age).IsEqualTo(30);
+ }
+}
diff --git a/src/Kuddle.Tests/Validation/ReservedTypeValidatorTests.cs b/src/Kuddle.Net.Tests/Validation/ReservedTypeValidatorTests.cs
similarity index 82%
rename from src/Kuddle.Tests/Validation/ReservedTypeValidatorTests.cs
rename to src/Kuddle.Net.Tests/Validation/ReservedTypeValidatorTests.cs
index 22deb82..6f4c310 100644
--- a/src/Kuddle.Tests/Validation/ReservedTypeValidatorTests.cs
+++ b/src/Kuddle.Net.Tests/Validation/ReservedTypeValidatorTests.cs
@@ -1,5 +1,6 @@
using Kuddle.AST;
using Kuddle.Exceptions;
+using Kuddle.Serialization;
using Kuddle.Validation;
namespace Kuddle.Tests.Validation;
@@ -15,7 +16,7 @@ public async Task Given_ValidU8_When_Validated_Then_NoExceptionThrown()
var doc = Parse("node 255");
// Act & Assert
- await Assert.That(() => KuddleReservedTypeValidator.Validate(doc)).ThrowsNothing();
+ await Assert.That(() => KdlReservedTypeValidator.Validate(doc)).ThrowsNothing();
}
[Test]
@@ -26,7 +27,7 @@ public async Task Given_OverflowingU8_When_Validated_Then_ThrowsValidationExcept
// Act
var exception = await Assert
- .That(() => KuddleReservedTypeValidator.Validate(doc))
+ .That(() => KdlReservedTypeValidator.Validate(doc))
.Throws();
// Assert
@@ -42,7 +43,7 @@ public async Task Given_StringForIntType_When_Validated_Then_ThrowsMismatchError
// Act
var exception = Assert.Throws(() =>
- KuddleReservedTypeValidator.Validate(doc)
+ KdlReservedTypeValidator.Validate(doc)
);
// Assert
@@ -57,7 +58,7 @@ public async Task Given_InvalidUuid_When_Validated_Then_ThrowsError()
// Act
var exception = Assert.Throws(() =>
- KuddleReservedTypeValidator.Validate(doc)
+ KdlReservedTypeValidator.Validate(doc)
);
// Assert
@@ -71,14 +72,14 @@ public async Task Given_NodeNameWithReservedType_When_Validated_Then_IgnoresIt()
var doc = Parse("node (u8)123");
// Act & Assert
- await Assert.That(() => KuddleReservedTypeValidator.Validate(doc)).ThrowsNothing();
+ await Assert.That(() => KdlReservedTypeValidator.Validate(doc)).ThrowsNothing();
}
private static KdlDocument Parse(string input)
{
- return KuddleReader.Parse(
+ return KdlReader.Read(
input,
- KuddleReaderOptions.Default with
+ KdlReaderOptions.Default with
{
ValidateReservedTypes = false,
}
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/all_escapes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/all_escapes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/all_escapes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/all_escapes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/all_node_fields.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/all_node_fields.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/all_node_fields.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/all_node_fields.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_and_prop_same_name.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_and_prop_same_name.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_and_prop_same_name.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_and_prop_same_name.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_bare.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_bare.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_bare.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_bare.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_false_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_false_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_false_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_false_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_float_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_float_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_float_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_float_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_hex_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_hex_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_hex_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_hex_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_null_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_null_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_null_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_null_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_raw_string_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_raw_string_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_raw_string_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_raw_string_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_string_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_string_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_string_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_string_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_true_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_true_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_true_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_true_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/arg_zero_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_zero_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/arg_zero_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/arg_zero_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/asterisk_in_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/asterisk_in_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/asterisk_in_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/asterisk_in_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/bare_emoji.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/bare_emoji.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/bare_emoji.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/bare_emoji.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/bare_ident_dot.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/bare_ident_dot.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/bare_ident_dot.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/bare_ident_dot.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/bare_ident_sign.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/bare_ident_sign.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/bare_ident_sign.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/bare_ident_sign.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/bare_ident_sign_dot.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/bare_ident_sign_dot.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/bare_ident_sign_dot.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/bare_ident_sign_dot.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/binary.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/binary.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/binary.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/binary.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/binary_trailing_underscore.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/binary_trailing_underscore.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/binary_trailing_underscore.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/binary_trailing_underscore.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/binary_underscore.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/binary_underscore.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/binary_underscore.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/binary_underscore.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/blank_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/blank_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/blank_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/blank_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/blank_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/blank_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/blank_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/blank_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/blank_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/blank_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/blank_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/blank_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/block_comment_after_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment_after_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/block_comment_after_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment_after_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/block_comment_before_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment_before_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/block_comment_before_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment_before_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/block_comment_before_node_no_space.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment_before_node_no_space.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/block_comment_before_node_no_space.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment_before_node_no_space.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/block_comment_newline.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/block_comment_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/block_comment_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/bom_initial.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/bom_initial.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/bom_initial.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/bom_initial.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/boolean_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/boolean_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/boolean_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/boolean_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/boolean_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/boolean_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/boolean_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/boolean_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/braces_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/braces_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/braces_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/braces_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/chevrons_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/chevrons_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/chevrons_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/chevrons_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/comma_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/comma_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/comma_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/comma_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/comment_after_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_after_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/comment_after_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_after_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/comment_after_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_after_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/comment_after_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_after_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/comment_after_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_after_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/comment_after_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_after_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/comment_and_newline.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_and_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/comment_and_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_and_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/comment_in_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_in_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/comment_in_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_in_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/comment_in_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_in_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/comment_in_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_in_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/comment_in_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_in_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/comment_in_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/comment_in_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/commented_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/commented_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/commented_child.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/commented_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/commented_line.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_line.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/commented_line.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_line.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/commented_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/commented_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/commented_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/commented_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/commented_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/crlf_between_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/crlf_between_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/crlf_between_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/crlf_between_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/dash_dash.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/dash_dash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/dash_dash.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/dash_dash.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/emoji.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/emoji.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/emoji.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/emoji.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/empty.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/empty.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/empty.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/empty.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/empty_child.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/empty_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/empty_child_different_lines.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_child_different_lines.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/empty_child_different_lines.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_child_different_lines.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/empty_child_same_line.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_child_same_line.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/empty_child_same_line.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_child_same_line.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/empty_child_whitespace.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_child_whitespace.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/empty_child_whitespace.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_child_whitespace.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/empty_line_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_line_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/empty_line_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_line_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/empty_quoted_node_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_quoted_node_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/empty_quoted_node_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_quoted_node_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/empty_quoted_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_quoted_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/empty_quoted_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_quoted_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/empty_string_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_string_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/empty_string_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/empty_string_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/eof_after_escape.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/eof_after_escape.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/eof_after_escape.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/eof_after_escape.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/esc_multiple_newlines.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/esc_multiple_newlines.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/esc_multiple_newlines.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/esc_multiple_newlines.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/esc_newline_in_string.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/esc_newline_in_string.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/esc_newline_in_string.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/esc_newline_in_string.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/esc_unicode_in_string.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/esc_unicode_in_string.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/esc_unicode_in_string.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/esc_unicode_in_string.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escaped_whitespace.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escaped_whitespace.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escaped_whitespace.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escaped_whitespace.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline_after_semicolon.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_after_semicolon.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline_after_semicolon.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_after_semicolon.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline_alone.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_alone.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline_alone.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_alone.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline_empty_line.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_empty_line.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline_empty_line.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_empty_line.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline_end_of_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_end_of_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline_end_of_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_end_of_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline_in_child_block.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_in_child_block.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline_in_child_block.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_in_child_block.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline_line_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_line_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline_line_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_line_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/escline_slashdash.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_slashdash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/escline_slashdash.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/escline_slashdash.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/false_prefix_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/false_prefix_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/false_prefix_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/false_prefix_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/false_prefix_in_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/false_prefix_in_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/false_prefix_in_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/false_prefix_in_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/floating_point_keywords.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/floating_point_keywords.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/floating_point_keywords.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/floating_point_keywords.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/hex.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/hex.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/hex.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/hex.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/hex_int.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/hex_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/hex_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/hex_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/hex_int_underscores.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/hex_int_underscores.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/hex_int_underscores.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/hex_int_underscores.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/hex_leading_zero.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/hex_leading_zero.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/hex_leading_zero.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/hex_leading_zero.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/initial_slashdash.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/initial_slashdash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/initial_slashdash.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/initial_slashdash.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/int_multiple_underscore.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/int_multiple_underscore.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/int_multiple_underscore.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/int_multiple_underscore.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/just_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/just_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/just_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/just_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/just_child.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/just_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/just_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/just_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/just_newline.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/just_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/just_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/just_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/just_node_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/just_node_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/just_node_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/just_node_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/just_space.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/just_space.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/just_space.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/just_space.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/leading_newline.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/leading_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/leading_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/leading_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/leading_zero_binary.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/leading_zero_binary.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/leading_zero_binary.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/leading_zero_binary.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/leading_zero_int.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/leading_zero_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/leading_zero_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/leading_zero_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/leading_zero_oct.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/leading_zero_oct.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/leading_zero_oct.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/leading_zero_oct.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string_containing_quotes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string_containing_quotes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string_containing_quotes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string_containing_quotes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string_empty.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string_empty.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string_empty.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string_empty.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string_empty_indented.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string_empty_indented.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string_empty_indented.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string_empty_indented.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string_indented.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string_indented.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_raw_string_indented.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_raw_string_indented.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_containing_quotes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_containing_quotes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_containing_quotes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_containing_quotes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_double_backslash.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_double_backslash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_double_backslash.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_double_backslash.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_empty.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_empty.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_empty.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_empty.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_empty_indented.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_empty_indented.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_empty_indented.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_empty_indented.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_escape_delimiter.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_escape_delimiter.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_escape_delimiter.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_escape_delimiter.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line_shallow.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line_shallow.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line_shallow.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line_shallow.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_escape_newline_at_end.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_escape_newline_at_end.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_escape_newline_at_end.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_escape_newline_at_end.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_indented.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_indented.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_indented.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_indented.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_whitespace_only.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_whitespace_only.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_whitespace_only.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_whitespace_only.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_wrapped_binary.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_wrapped_binary.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/multiline_string_wrapped_binary.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/multiline_string_wrapped_binary.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/negative_exponent.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/negative_exponent.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/negative_exponent.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/negative_exponent.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/negative_float.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/negative_float.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/negative_float.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/negative_float.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/negative_int.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/negative_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/negative_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/negative_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/nested_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/nested_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/nested_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/nested_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/nested_children.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/nested_children.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/nested_children.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/nested_children.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/nested_comments.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/nested_comments.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/nested_comments.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/nested_comments.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/nested_multiline_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/nested_multiline_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/nested_multiline_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/nested_multiline_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/newline_between_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/newline_between_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/newline_between_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/newline_between_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/newlines_in_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/newlines_in_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/newlines_in_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/newlines_in_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/no_decimal_exponent.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/no_decimal_exponent.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/no_decimal_exponent.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/no_decimal_exponent.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/node_false.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/node_false.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/node_false.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/node_false.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/node_true.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/node_true.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/node_true.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/node_true.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/node_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/null_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/null_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/null_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/null_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/null_prefix_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/null_prefix_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/null_prefix_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/null_prefix_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/null_prefix_in_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/null_prefix_in_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/null_prefix_in_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/null_prefix_in_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/null_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/null_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/null_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/null_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/numeric_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/numeric_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/numeric_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/numeric_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/numeric_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/numeric_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/numeric_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/numeric_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/octal.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/octal.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/octal.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/octal.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/only_cr.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/only_cr.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/only_cr.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/only_cr.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/only_line_comment.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/only_line_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/only_line_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/only_line_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/only_line_comment_crlf.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/only_line_comment_crlf.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/only_line_comment_crlf.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/only_line_comment_crlf.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/only_line_comment_newline.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/only_line_comment_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/only_line_comment_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/only_line_comment_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/optional_child_semicolon.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/optional_child_semicolon.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/optional_child_semicolon.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/optional_child_semicolon.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/parse_all_arg_types.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/parse_all_arg_types.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/parse_all_arg_types.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/parse_all_arg_types.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/positive_exponent.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/positive_exponent.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/positive_exponent.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/positive_exponent.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/positive_int.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/positive_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/positive_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/positive_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/preserve_duplicate_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/preserve_duplicate_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/preserve_duplicate_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/preserve_duplicate_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/preserve_node_order.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/preserve_node_order.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/preserve_node_order.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/preserve_node_order.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_false_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_false_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_false_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_false_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_float_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_float_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_float_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_float_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_hex_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_hex_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_hex_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_hex_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_identifier_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_identifier_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_identifier_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_identifier_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_null_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_null_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_null_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_null_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_raw_string_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_raw_string_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_raw_string_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_raw_string_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_string_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_string_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_string_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_string_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_true_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_true_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_true_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_true_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/prop_zero_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_zero_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/prop_zero_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/prop_zero_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/question_mark_before_number.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/question_mark_before_number.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/question_mark_before_number.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/question_mark_before_number.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/quoted_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/quoted_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/quoted_node_name.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_node_name.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/quoted_node_name.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_node_name.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/quoted_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/quoted_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/quoted_numeric.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_numeric.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/quoted_numeric.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_numeric.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/quoted_prop_name.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_prop_name.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/quoted_prop_name.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_prop_name.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/quoted_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/quoted_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/quoted_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/r_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/r_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/r_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/r_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_node_name.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_node_name.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_node_name.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_node_name.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_string_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_string_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_string_backslash.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_backslash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_string_backslash.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_backslash.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_string_hash_no_esc.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_hash_no_esc.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_string_hash_no_esc.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_hash_no_esc.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_string_just_backslash.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_just_backslash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_string_just_backslash.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_just_backslash.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_string_multiple_hash.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_multiple_hash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_string_multiple_hash.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_multiple_hash.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_string_newline.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_string_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_string_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_string_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/raw_string_quote.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_quote.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/raw_string_quote.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/raw_string_quote.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/repeated_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/repeated_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/repeated_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/repeated_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/repeated_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/repeated_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/repeated_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/repeated_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/same_name_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/same_name_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/same_name_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/same_name_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/sci_notation_large.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/sci_notation_large.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/sci_notation_large.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/sci_notation_large.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/sci_notation_small.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/sci_notation_small.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/sci_notation_small.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/sci_notation_small.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/semicolon_after_child.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_after_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/semicolon_after_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_after_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/semicolon_in_child.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_in_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/semicolon_in_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_in_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/semicolon_separated.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_separated.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/semicolon_separated.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_separated.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/semicolon_separated_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_separated_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/semicolon_separated_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_separated_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/semicolon_terminated.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_terminated.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/semicolon_terminated.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/semicolon_terminated.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/single_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/single_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/single_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/single_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/single_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/single_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/single_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/single_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_arg_after_newline_esc.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_arg_after_newline_esc.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_arg_after_newline_esc.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_arg_after_newline_esc.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_arg_before_newline_esc.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_arg_before_newline_esc.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_arg_before_newline_esc.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_arg_before_newline_esc.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_child.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_empty_child.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_empty_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_empty_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_empty_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_escline_before_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_escline_before_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_escline_before_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_escline_before_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_escline_before_children.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_escline_before_children.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_escline_before_children.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_escline_before_children.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_escline_before_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_escline_before_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_escline_before_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_escline_before_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_false_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_false_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_false_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_false_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_full_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_full_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_full_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_full_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_in_slashdash.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_in_slashdash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_in_slashdash.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_in_slashdash.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_multi_line_comment_entry.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_multi_line_comment_entry.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_multi_line_comment_entry.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_multi_line_comment_entry.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_multi_line_comment_inline.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_multi_line_comment_inline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_multi_line_comment_inline.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_multi_line_comment_inline.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_multiple_child_blocks.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_multiple_child_blocks.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_multiple_child_blocks.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_multiple_child_blocks.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_negative_number.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_negative_number.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_negative_number.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_negative_number.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_newline_before_children.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_newline_before_children.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_newline_before_children.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_newline_before_children.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_newline_before_entry.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_newline_before_entry.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_newline_before_entry.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_newline_before_entry.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_newline_before_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_newline_before_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_newline_before_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_newline_before_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_node_in_child.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_node_in_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_node_in_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_node_in_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_node_with_child.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_node_with_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_node_with_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_node_with_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_only_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_only_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_only_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_only_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_only_node_with_space.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_only_node_with_space.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_only_node_with_space.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_only_node_with_space.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_raw_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_raw_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_raw_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_raw_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_repeated_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_repeated_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_repeated_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_repeated_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_single_line_comment_entry.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_single_line_comment_entry.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_single_line_comment_entry.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_single_line_comment_entry.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/slashdash_single_line_comment_node.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_single_line_comment_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/slashdash_single_line_comment_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/slashdash_single_line_comment_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/space_after_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/space_after_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/space_after_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/space_after_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/space_after_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/space_after_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/space_after_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/space_after_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/space_after_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/space_after_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/space_after_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/space_after_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/space_around_prop_marker.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/space_around_prop_marker.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/space_around_prop_marker.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/space_around_prop_marker.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/space_in_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/space_in_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/space_in_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/space_in_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/space_in_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/space_in_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/space_in_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/space_in_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/space_in_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/space_in_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/space_in_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/space_in_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/string_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/string_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/string_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/string_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/string_escaped_literal_whitespace.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/string_escaped_literal_whitespace.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/string_escaped_literal_whitespace.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/string_escaped_literal_whitespace.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/string_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/string_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/string_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/string_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/tab_space.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/tab_space.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/tab_space.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/tab_space.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/trailing_crlf.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/trailing_crlf.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/trailing_crlf.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/trailing_crlf.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/trailing_underscore_hex.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/trailing_underscore_hex.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/trailing_underscore_hex.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/trailing_underscore_hex.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/trailing_underscore_octal.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/trailing_underscore_octal.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/trailing_underscore_octal.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/trailing_underscore_octal.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/true_prefix_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/true_prefix_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/true_prefix_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/true_prefix_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/true_prefix_in_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/true_prefix_in_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/true_prefix_in_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/true_prefix_in_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/two_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/two_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/two_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/two_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/underscore_before_number.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_before_number.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/underscore_before_number.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_before_number.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_exponent.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_exponent.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_exponent.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_exponent.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_float.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_float.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_float.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_float.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_fraction.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_fraction.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_fraction.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_fraction.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_int.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_octal.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_octal.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/underscore_in_octal.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/underscore_in_octal.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/unicode_silly.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/unicode_silly.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/unicode_silly.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/unicode_silly.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/unusual_bare_id_chars_in_quoted_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/unusual_bare_id_chars_in_quoted_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/unusual_bare_id_chars_in_quoted_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/unusual_bare_id_chars_in_quoted_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/unusual_chars_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/unusual_chars_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/unusual_chars_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/unusual_chars_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/vertical_tab_whitespace.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/vertical_tab_whitespace.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/vertical_tab_whitespace.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/vertical_tab_whitespace.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/zero_float.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_float.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/zero_float.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_float.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/zero_int.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/zero_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/zero_space_before_slashdash_arg.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_space_before_slashdash_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/zero_space_before_slashdash_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_space_before_slashdash_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/zero_space_before_slashdash_children.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_space_before_slashdash_children.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/zero_space_before_slashdash_children.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_space_before_slashdash_children.kdl
diff --git a/src/Kuddle.Tests/test_cases/expected_kdl/zero_space_before_slashdash_prop.kdl b/src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_space_before_slashdash_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/expected_kdl/zero_space_before_slashdash_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/expected_kdl/zero_space_before_slashdash_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/all_escapes.kdl b/src/Kuddle.Net.Tests/test_cases/input/all_escapes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/all_escapes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/all_escapes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/all_node_fields.kdl b/src/Kuddle.Net.Tests/test_cases/input/all_node_fields.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/all_node_fields.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/all_node_fields.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_and_prop_same_name.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_and_prop_same_name.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_and_prop_same_name.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_and_prop_same_name.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_bare.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_bare.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_bare.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_bare.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_false_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_false_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_false_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_false_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_float_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_float_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_float_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_float_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_hex_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_hex_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_hex_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_hex_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_null_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_null_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_null_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_null_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_raw_string_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_raw_string_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_raw_string_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_raw_string_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_string_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_string_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_string_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_string_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_true_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_true_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_true_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_true_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/arg_zero_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/arg_zero_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/arg_zero_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/arg_zero_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/asterisk_in_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/asterisk_in_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/asterisk_in_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/asterisk_in_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/bare_emoji.kdl b/src/Kuddle.Net.Tests/test_cases/input/bare_emoji.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/bare_emoji.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/bare_emoji.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/bare_ident_dot.kdl b/src/Kuddle.Net.Tests/test_cases/input/bare_ident_dot.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/bare_ident_dot.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/bare_ident_dot.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/bare_ident_numeric_dot_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/bare_ident_numeric_dot_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/bare_ident_numeric_dot_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/bare_ident_numeric_dot_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/bare_ident_numeric_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/bare_ident_numeric_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/bare_ident_numeric_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/bare_ident_numeric_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/bare_ident_numeric_sign_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/bare_ident_numeric_sign_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/bare_ident_numeric_sign_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/bare_ident_numeric_sign_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/bare_ident_sign.kdl b/src/Kuddle.Net.Tests/test_cases/input/bare_ident_sign.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/bare_ident_sign.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/bare_ident_sign.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/bare_ident_sign_dot.kdl b/src/Kuddle.Net.Tests/test_cases/input/bare_ident_sign_dot.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/bare_ident_sign_dot.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/bare_ident_sign_dot.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/binary.kdl b/src/Kuddle.Net.Tests/test_cases/input/binary.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/binary.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/binary.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/binary_trailing_underscore.kdl b/src/Kuddle.Net.Tests/test_cases/input/binary_trailing_underscore.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/binary_trailing_underscore.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/binary_trailing_underscore.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/binary_underscore.kdl b/src/Kuddle.Net.Tests/test_cases/input/binary_underscore.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/binary_underscore.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/binary_underscore.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/blank_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/blank_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/blank_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/blank_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/blank_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/blank_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/blank_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/blank_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/blank_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/blank_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/blank_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/blank_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/block_comment_after_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/block_comment_after_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/block_comment_after_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/block_comment_after_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/block_comment_before_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/block_comment_before_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/block_comment_before_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/block_comment_before_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/block_comment_before_node_no_space.kdl b/src/Kuddle.Net.Tests/test_cases/input/block_comment_before_node_no_space.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/block_comment_before_node_no_space.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/block_comment_before_node_no_space.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/block_comment_newline.kdl b/src/Kuddle.Net.Tests/test_cases/input/block_comment_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/block_comment_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/block_comment_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/bom_initial.kdl b/src/Kuddle.Net.Tests/test_cases/input/bom_initial.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/bom_initial.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/bom_initial.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/bom_later_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/bom_later_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/bom_later_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/bom_later_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/boolean_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/boolean_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/boolean_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/boolean_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/boolean_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/boolean_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/boolean_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/boolean_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/braces_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/braces_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/braces_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/braces_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/chevrons_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/chevrons_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/chevrons_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/chevrons_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/comma_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/comma_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/comma_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/comma_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/comment_after_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/comment_after_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/comment_after_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/comment_after_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/comment_after_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/comment_after_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/comment_after_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/comment_after_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/comment_after_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/comment_after_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/comment_after_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/comment_after_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/comment_and_newline.kdl b/src/Kuddle.Net.Tests/test_cases/input/comment_and_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/comment_and_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/comment_and_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/comment_in_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/comment_in_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/comment_in_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/comment_in_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/comment_in_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/comment_in_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/comment_in_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/comment_in_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/comment_in_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/comment_in_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/comment_in_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/comment_in_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/commented_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/commented_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/commented_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/commented_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/commented_child.kdl b/src/Kuddle.Net.Tests/test_cases/input/commented_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/commented_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/commented_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/commented_line.kdl b/src/Kuddle.Net.Tests/test_cases/input/commented_line.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/commented_line.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/commented_line.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/commented_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/commented_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/commented_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/commented_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/commented_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/commented_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/commented_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/commented_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/crlf_between_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/input/crlf_between_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/crlf_between_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/crlf_between_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/dash_dash.kdl b/src/Kuddle.Net.Tests/test_cases/input/dash_dash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/dash_dash.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/dash_dash.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/dot_but_no_fraction_before_exponent_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/dot_but_no_fraction_before_exponent_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/dot_but_no_fraction_before_exponent_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/dot_but_no_fraction_before_exponent_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/dot_but_no_fraction_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/dot_but_no_fraction_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/dot_but_no_fraction_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/dot_but_no_fraction_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/dot_in_exponent_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/dot_in_exponent_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/dot_in_exponent_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/dot_in_exponent_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/dot_zero_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/dot_zero_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/dot_zero_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/dot_zero_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/emoji.kdl b/src/Kuddle.Net.Tests/test_cases/input/emoji.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/emoji.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/emoji.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_arg_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_arg_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_arg_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_arg_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_child.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_child_different_lines.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_child_different_lines.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_child_different_lines.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_child_different_lines.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_child_same_line.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_child_same_line.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_child_same_line.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_child_same_line.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_child_whitespace.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_child_whitespace.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_child_whitespace.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_child_whitespace.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_line_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_line_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_line_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_line_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_node_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_node_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_node_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_node_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_prop_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_prop_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_prop_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_prop_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_quoted_node_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_quoted_node_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_quoted_node_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_quoted_node_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_quoted_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_quoted_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_quoted_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_quoted_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/empty_string_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/empty_string_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/empty_string_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/empty_string_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/eof_after_escape.kdl b/src/Kuddle.Net.Tests/test_cases/input/eof_after_escape.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/eof_after_escape.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/eof_after_escape.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/err_backslash_in_bare_id_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/err_backslash_in_bare_id_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/err_backslash_in_bare_id_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/err_backslash_in_bare_id_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/esc_multiple_newlines.kdl b/src/Kuddle.Net.Tests/test_cases/input/esc_multiple_newlines.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/esc_multiple_newlines.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/esc_multiple_newlines.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/esc_newline_in_string.kdl b/src/Kuddle.Net.Tests/test_cases/input/esc_newline_in_string.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/esc_newline_in_string.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/esc_newline_in_string.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/esc_unicode_in_string.kdl b/src/Kuddle.Net.Tests/test_cases/input/esc_unicode_in_string.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/esc_unicode_in_string.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/esc_unicode_in_string.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escaped_whitespace.kdl b/src/Kuddle.Net.Tests/test_cases/input/escaped_whitespace.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escaped_whitespace.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escaped_whitespace.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline_after_semicolon.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline_after_semicolon.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline_after_semicolon.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline_after_semicolon.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline_alone.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline_alone.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline_alone.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline_alone.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline_empty_line.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline_empty_line.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline_empty_line.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline_empty_line.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline_end_of_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline_end_of_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline_end_of_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline_end_of_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline_in_child_block.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline_in_child_block.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline_in_child_block.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline_in_child_block.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline_line_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline_line_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline_line_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline_line_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/escline_slashdash.kdl b/src/Kuddle.Net.Tests/test_cases/input/escline_slashdash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/escline_slashdash.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/escline_slashdash.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/false_prefix_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/false_prefix_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/false_prefix_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/false_prefix_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/false_prefix_in_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/input/false_prefix_in_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/false_prefix_in_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/false_prefix_in_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/false_prop_key_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/false_prop_key_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/false_prop_key_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/false_prop_key_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/floating_point_keyword_identifier_strings_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/floating_point_keyword_identifier_strings_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/floating_point_keyword_identifier_strings_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/floating_point_keyword_identifier_strings_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/floating_point_keywords.kdl b/src/Kuddle.Net.Tests/test_cases/input/floating_point_keywords.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/floating_point_keywords.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/floating_point_keywords.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/hash_in_id_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/hash_in_id_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/hash_in_id_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/hash_in_id_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/hex.kdl b/src/Kuddle.Net.Tests/test_cases/input/hex.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/hex.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/hex.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/hex_int.kdl b/src/Kuddle.Net.Tests/test_cases/input/hex_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/hex_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/hex_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/hex_int_underscores.kdl b/src/Kuddle.Net.Tests/test_cases/input/hex_int_underscores.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/hex_int_underscores.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/hex_int_underscores.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/hex_leading_zero.kdl b/src/Kuddle.Net.Tests/test_cases/input/hex_leading_zero.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/hex_leading_zero.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/hex_leading_zero.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/illegal_char_in_binary_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/illegal_char_in_binary_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/illegal_char_in_binary_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/illegal_char_in_binary_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/illegal_char_in_hex_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/illegal_char_in_hex_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/illegal_char_in_hex_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/illegal_char_in_hex_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/illegal_char_in_octal_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/illegal_char_in_octal_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/illegal_char_in_octal_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/illegal_char_in_octal_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/initial_slashdash.kdl b/src/Kuddle.Net.Tests/test_cases/input/initial_slashdash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/initial_slashdash.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/initial_slashdash.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/int_multiple_underscore.kdl b/src/Kuddle.Net.Tests/test_cases/input/int_multiple_underscore.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/int_multiple_underscore.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/int_multiple_underscore.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_child.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_newline.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_node_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_node_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_node_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_node_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_space.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_space.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_space.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_space.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_space_in_arg_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_space_in_arg_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_space_in_arg_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_space_in_arg_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_space_in_node_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_space_in_node_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_space_in_node_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_space_in_node_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_space_in_prop_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_space_in_prop_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_space_in_prop_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_space_in_prop_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_type_no_arg_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_type_no_arg_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_type_no_arg_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_type_no_arg_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_type_no_node_id_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_type_no_node_id_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_type_no_node_id_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_type_no_node_id_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/just_type_no_prop_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/just_type_no_prop_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/just_type_no_prop_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/just_type_no_prop_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/leading_newline.kdl b/src/Kuddle.Net.Tests/test_cases/input/leading_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/leading_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/leading_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/leading_zero_binary.kdl b/src/Kuddle.Net.Tests/test_cases/input/leading_zero_binary.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/leading_zero_binary.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/leading_zero_binary.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/leading_zero_int.kdl b/src/Kuddle.Net.Tests/test_cases/input/leading_zero_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/leading_zero_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/leading_zero_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/leading_zero_oct.kdl b/src/Kuddle.Net.Tests/test_cases/input/leading_zero_oct.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/leading_zero_oct.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/leading_zero_oct.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/legacy_raw_string_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/legacy_raw_string_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/legacy_raw_string_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/legacy_raw_string_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/legacy_raw_string_hash_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/legacy_raw_string_hash_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/legacy_raw_string_hash_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/legacy_raw_string_hash_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_raw_string.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_raw_string.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_raw_string_containing_quotes.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_containing_quotes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_raw_string_containing_quotes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_containing_quotes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_raw_string_empty.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_empty.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_raw_string_empty.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_empty.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_raw_string_empty_indented.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_empty_indented.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_raw_string_empty_indented.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_empty_indented.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_raw_string_indented.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_indented.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_raw_string_indented.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_indented.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_raw_string_non_matching_prefix_character_error_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_non_matching_prefix_character_error_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_raw_string_non_matching_prefix_character_error_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_non_matching_prefix_character_error_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_raw_string_non_matching_prefix_count_error_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_non_matching_prefix_count_error_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_raw_string_non_matching_prefix_count_error_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_non_matching_prefix_count_error_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_raw_string_single_line_err_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_single_line_err_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_raw_string_single_line_err_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_single_line_err_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_raw_string_single_quote_err_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_single_quote_err_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_raw_string_single_quote_err_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_raw_string_single_quote_err_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_containing_quotes.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_containing_quotes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_containing_quotes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_containing_quotes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_double_backslash.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_double_backslash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_double_backslash.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_double_backslash.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_empty.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_empty.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_empty.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_empty.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_empty_indented.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_empty_indented.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_empty_indented.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_empty_indented.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_escape_delimiter.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_delimiter.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_escape_delimiter.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_delimiter.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_escape_in_closing_line.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_in_closing_line.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_escape_in_closing_line.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_in_closing_line.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_escape_in_closing_line_shallow.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_in_closing_line_shallow.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_escape_in_closing_line_shallow.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_in_closing_line_shallow.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_escape_newline_at_end.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_newline_at_end.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_escape_newline_at_end.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_newline_at_end.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_escape_newline_at_end_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_newline_at_end_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_escape_newline_at_end_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_escape_newline_at_end_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_final_whitespace_escape_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_final_whitespace_escape_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_final_whitespace_escape_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_final_whitespace_escape_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_indented.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_indented.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_indented.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_indented.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_non_literal_prefix_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_non_literal_prefix_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_non_literal_prefix_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_non_literal_prefix_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_non_matching_prefix_character_error_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_non_matching_prefix_character_error_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_non_matching_prefix_character_error_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_non_matching_prefix_character_error_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_non_matching_prefix_count_error_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_non_matching_prefix_count_error_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_non_matching_prefix_count_error_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_non_matching_prefix_count_error_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_single_line_err_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_single_line_err_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_single_line_err_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_single_line_err_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_single_quote_err_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_single_quote_err_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_single_quote_err_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_single_quote_err_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_whitespace_only.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_whitespace_only.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_whitespace_only.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_whitespace_only.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiline_string_wrapped_binary.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiline_string_wrapped_binary.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiline_string_wrapped_binary.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiline_string_wrapped_binary.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiple_dots_in_float_before_exponent_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiple_dots_in_float_before_exponent_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiple_dots_in_float_before_exponent_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiple_dots_in_float_before_exponent_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiple_dots_in_float_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiple_dots_in_float_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiple_dots_in_float_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiple_dots_in_float_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiple_es_in_float_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiple_es_in_float_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiple_es_in_float_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiple_es_in_float_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/multiple_x_in_hex_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/multiple_x_in_hex_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/multiple_x_in_hex_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/multiple_x_in_hex_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/negative_exponent.kdl b/src/Kuddle.Net.Tests/test_cases/input/negative_exponent.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/negative_exponent.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/negative_exponent.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/negative_float.kdl b/src/Kuddle.Net.Tests/test_cases/input/negative_float.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/negative_float.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/negative_float.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/negative_int.kdl b/src/Kuddle.Net.Tests/test_cases/input/negative_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/negative_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/negative_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/nested_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/nested_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/nested_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/nested_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/nested_children.kdl b/src/Kuddle.Net.Tests/test_cases/input/nested_children.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/nested_children.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/nested_children.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/nested_comments.kdl b/src/Kuddle.Net.Tests/test_cases/input/nested_comments.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/nested_comments.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/nested_comments.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/nested_multiline_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/nested_multiline_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/nested_multiline_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/nested_multiline_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/newline_between_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/input/newline_between_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/newline_between_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/newline_between_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/newlines_in_block_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/newlines_in_block_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/newlines_in_block_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/newlines_in_block_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/no_decimal_exponent.kdl b/src/Kuddle.Net.Tests/test_cases/input/no_decimal_exponent.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/no_decimal_exponent.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/no_decimal_exponent.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/no_digits_in_hex_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/no_digits_in_hex_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/no_digits_in_hex_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/no_digits_in_hex_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/no_integer_digit_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/no_integer_digit_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/no_integer_digit_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/no_integer_digit_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/no_solidus_escape_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/no_solidus_escape_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/no_solidus_escape_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/no_solidus_escape_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/node_false.kdl b/src/Kuddle.Net.Tests/test_cases/input/node_false.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/node_false.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/node_false.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/node_true.kdl b/src/Kuddle.Net.Tests/test_cases/input/node_true.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/node_true.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/node_true.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/node_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/null_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/null_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/null_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/null_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/null_prefix_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/null_prefix_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/null_prefix_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/null_prefix_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/null_prefix_in_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/input/null_prefix_in_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/null_prefix_in_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/null_prefix_in_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/null_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/null_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/null_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/null_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/null_prop_key_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/null_prop_key_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/null_prop_key_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/null_prop_key_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/numeric_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/numeric_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/numeric_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/numeric_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/numeric_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/numeric_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/numeric_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/numeric_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/octal.kdl b/src/Kuddle.Net.Tests/test_cases/input/octal.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/octal.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/octal.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/only_cr.kdl b/src/Kuddle.Net.Tests/test_cases/input/only_cr.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/only_cr.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/only_cr.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/only_line_comment.kdl b/src/Kuddle.Net.Tests/test_cases/input/only_line_comment.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/only_line_comment.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/only_line_comment.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/only_line_comment_crlf.kdl b/src/Kuddle.Net.Tests/test_cases/input/only_line_comment_crlf.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/only_line_comment_crlf.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/only_line_comment_crlf.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/only_line_comment_newline.kdl b/src/Kuddle.Net.Tests/test_cases/input/only_line_comment_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/only_line_comment_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/only_line_comment_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/optional_child_semicolon.kdl b/src/Kuddle.Net.Tests/test_cases/input/optional_child_semicolon.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/optional_child_semicolon.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/optional_child_semicolon.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/parens_in_bare_id_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/parens_in_bare_id_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/parens_in_bare_id_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/parens_in_bare_id_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/parse_all_arg_types.kdl b/src/Kuddle.Net.Tests/test_cases/input/parse_all_arg_types.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/parse_all_arg_types.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/parse_all_arg_types.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/positive_exponent.kdl b/src/Kuddle.Net.Tests/test_cases/input/positive_exponent.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/positive_exponent.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/positive_exponent.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/positive_int.kdl b/src/Kuddle.Net.Tests/test_cases/input/positive_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/positive_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/positive_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/preserve_duplicate_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/input/preserve_duplicate_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/preserve_duplicate_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/preserve_duplicate_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/preserve_node_order.kdl b/src/Kuddle.Net.Tests/test_cases/input/preserve_node_order.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/preserve_node_order.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/preserve_node_order.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_false_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_false_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_false_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_false_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_float_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_float_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_float_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_float_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_hex_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_hex_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_hex_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_hex_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_identifier_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_identifier_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_identifier_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_identifier_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_null_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_null_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_null_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_null_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_raw_string_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_raw_string_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_raw_string_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_raw_string_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_string_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_string_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_string_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_string_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_true_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_true_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_true_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_true_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/prop_zero_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/prop_zero_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/prop_zero_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/prop_zero_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/question_mark_before_number.kdl b/src/Kuddle.Net.Tests/test_cases/input/question_mark_before_number.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/question_mark_before_number.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/question_mark_before_number.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/quote_in_bare_id_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/quote_in_bare_id_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/quote_in_bare_id_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/quote_in_bare_id_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/quoted_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/quoted_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/quoted_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/quoted_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/quoted_node_name.kdl b/src/Kuddle.Net.Tests/test_cases/input/quoted_node_name.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/quoted_node_name.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/quoted_node_name.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/quoted_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/quoted_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/quoted_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/quoted_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/quoted_numeric.kdl b/src/Kuddle.Net.Tests/test_cases/input/quoted_numeric.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/quoted_numeric.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/quoted_numeric.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/quoted_prop_name.kdl b/src/Kuddle.Net.Tests/test_cases/input/quoted_prop_name.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/quoted_prop_name.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/quoted_prop_name.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/quoted_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/quoted_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/quoted_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/quoted_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/r_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/r_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/r_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/r_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_node_name.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_node_name.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_node_name.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_node_name.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_string_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_string_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_string_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_string_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_string_backslash.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_string_backslash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_string_backslash.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_string_backslash.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_string_hash_no_esc.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_string_hash_no_esc.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_string_hash_no_esc.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_string_hash_no_esc.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_string_just_backslash.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_string_just_backslash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_string_just_backslash.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_string_just_backslash.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_string_just_quote_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_string_just_quote_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_string_just_quote_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_string_just_quote_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_string_multiple_hash.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_string_multiple_hash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_string_multiple_hash.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_string_multiple_hash.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_string_newline.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_string_newline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_string_newline.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_string_newline.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_string_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_string_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_string_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_string_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/raw_string_quote.kdl b/src/Kuddle.Net.Tests/test_cases/input/raw_string_quote.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/raw_string_quote.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/raw_string_quote.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/repeated_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/repeated_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/repeated_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/repeated_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/repeated_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/repeated_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/repeated_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/repeated_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/same_name_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/input/same_name_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/same_name_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/same_name_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/sci_notation_large.kdl b/src/Kuddle.Net.Tests/test_cases/input/sci_notation_large.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/sci_notation_large.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/sci_notation_large.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/sci_notation_small.kdl b/src/Kuddle.Net.Tests/test_cases/input/sci_notation_small.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/sci_notation_small.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/sci_notation_small.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/semicolon_after_child.kdl b/src/Kuddle.Net.Tests/test_cases/input/semicolon_after_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/semicolon_after_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/semicolon_after_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/semicolon_in_child.kdl b/src/Kuddle.Net.Tests/test_cases/input/semicolon_in_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/semicolon_in_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/semicolon_in_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/semicolon_missing_after_children_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/semicolon_missing_after_children_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/semicolon_missing_after_children_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/semicolon_missing_after_children_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/semicolon_separated.kdl b/src/Kuddle.Net.Tests/test_cases/input/semicolon_separated.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/semicolon_separated.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/semicolon_separated.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/semicolon_separated_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/input/semicolon_separated_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/semicolon_separated_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/semicolon_separated_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/semicolon_terminated.kdl b/src/Kuddle.Net.Tests/test_cases/input/semicolon_terminated.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/semicolon_terminated.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/semicolon_terminated.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/single_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/single_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/single_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/single_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/single_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/single_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/single_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/single_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slash_in_bare_id_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slash_in_bare_id_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slash_in_bare_id_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slash_in_bare_id_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_after_arg_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_after_arg_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_after_arg_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_after_arg_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_after_node_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_after_node_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_after_node_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_after_node_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_after_prop_key_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_after_prop_key_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_after_prop_key_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_after_prop_key_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_after_prop_val_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_after_prop_val_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_after_prop_val_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_after_prop_val_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_after_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_after_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_after_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_after_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_arg_after_newline_esc.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_arg_after_newline_esc.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_arg_after_newline_esc.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_arg_after_newline_esc.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_arg_before_newline_esc.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_arg_before_newline_esc.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_arg_before_newline_esc.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_arg_before_newline_esc.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_before_children_end_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_before_children_end_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_before_children_end_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_before_children_end_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_before_eof_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_before_eof_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_before_eof_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_before_eof_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_before_prop_value_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_before_prop_value_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_before_prop_value_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_before_prop_value_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_before_semicolon_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_before_semicolon_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_before_semicolon_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_before_semicolon_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_between_child_blocks_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_between_child_blocks_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_between_child_blocks_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_between_child_blocks_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_child.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_child_block_before_entry_err_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_child_block_before_entry_err_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_child_block_before_entry_err_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_child_block_before_entry_err_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_empty_child.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_empty_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_empty_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_empty_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_escline_before_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_escline_before_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_escline_before_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_escline_before_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_escline_before_children.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_escline_before_children.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_escline_before_children.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_escline_before_children.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_escline_before_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_escline_before_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_escline_before_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_escline_before_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_false_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_false_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_false_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_false_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_full_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_full_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_full_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_full_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_in_slashdash.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_in_slashdash.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_in_slashdash.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_in_slashdash.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_inside_arg_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_inside_arg_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_inside_arg_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_inside_arg_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_inside_node_type_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_inside_node_type_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_inside_node_type_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_inside_node_type_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_multi_line_comment_entry.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_multi_line_comment_entry.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_multi_line_comment_entry.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_multi_line_comment_entry.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_multi_line_comment_inline.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_multi_line_comment_inline.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_multi_line_comment_inline.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_multi_line_comment_inline.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_multiple_child_blocks.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_multiple_child_blocks.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_multiple_child_blocks.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_multiple_child_blocks.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_negative_number.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_negative_number.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_negative_number.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_negative_number.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_newline_before_children.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_newline_before_children.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_newline_before_children.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_newline_before_children.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_newline_before_entry.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_newline_before_entry.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_newline_before_entry.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_newline_before_entry.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_newline_before_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_newline_before_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_newline_before_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_newline_before_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_node_in_child.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_node_in_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_node_in_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_node_in_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_node_with_child.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_node_with_child.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_node_with_child.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_node_with_child.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_only_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_only_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_only_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_only_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_only_node_with_space.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_only_node_with_space.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_only_node_with_space.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_only_node_with_space.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_raw_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_raw_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_raw_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_raw_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_repeated_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_repeated_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_repeated_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_repeated_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_single_line_comment_entry.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_single_line_comment_entry.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_single_line_comment_entry.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_single_line_comment_entry.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/slashdash_single_line_comment_node.kdl b/src/Kuddle.Net.Tests/test_cases/input/slashdash_single_line_comment_node.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/slashdash_single_line_comment_node.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/slashdash_single_line_comment_node.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/space_after_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/space_after_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/space_after_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/space_after_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/space_after_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/space_after_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/space_after_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/space_after_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/space_after_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/space_after_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/space_after_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/space_after_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/space_around_prop_marker.kdl b/src/Kuddle.Net.Tests/test_cases/input/space_around_prop_marker.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/space_around_prop_marker.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/space_around_prop_marker.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/space_in_arg_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/space_in_arg_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/space_in_arg_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/space_in_arg_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/space_in_node_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/space_in_node_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/space_in_node_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/space_in_node_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/space_in_prop_type.kdl b/src/Kuddle.Net.Tests/test_cases/input/space_in_prop_type.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/space_in_prop_type.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/space_in_prop_type.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/square_bracket_in_bare_id_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/square_bracket_in_bare_id_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/square_bracket_in_bare_id_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/square_bracket_in_bare_id_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/string_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/string_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/string_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/string_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/string_escaped_literal_whitespace.kdl b/src/Kuddle.Net.Tests/test_cases/input/string_escaped_literal_whitespace.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/string_escaped_literal_whitespace.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/string_escaped_literal_whitespace.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/string_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/string_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/string_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/string_prop.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/tab_space.kdl b/src/Kuddle.Net.Tests/test_cases/input/tab_space.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/tab_space.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/tab_space.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/trailing_crlf.kdl b/src/Kuddle.Net.Tests/test_cases/input/trailing_crlf.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/trailing_crlf.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/trailing_crlf.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/trailing_underscore_hex.kdl b/src/Kuddle.Net.Tests/test_cases/input/trailing_underscore_hex.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/trailing_underscore_hex.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/trailing_underscore_hex.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/trailing_underscore_octal.kdl b/src/Kuddle.Net.Tests/test_cases/input/trailing_underscore_octal.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/trailing_underscore_octal.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/trailing_underscore_octal.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/true_prefix_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/true_prefix_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/true_prefix_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/true_prefix_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/true_prefix_in_prop_key.kdl b/src/Kuddle.Net.Tests/test_cases/input/true_prefix_in_prop_key.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/true_prefix_in_prop_key.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/true_prefix_in_prop_key.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/true_prop_key_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/true_prop_key_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/true_prop_key_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/true_prop_key_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/two_nodes.kdl b/src/Kuddle.Net.Tests/test_cases/input/two_nodes.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/two_nodes.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/two_nodes.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/type_before_prop_key_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/type_before_prop_key_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/type_before_prop_key_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/type_before_prop_key_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unbalanced_raw_hashes_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unbalanced_raw_hashes_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unbalanced_raw_hashes_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unbalanced_raw_hashes_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/underscore_at_start_of_fraction_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/underscore_at_start_of_fraction_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/underscore_at_start_of_fraction_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/underscore_at_start_of_fraction_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/underscore_at_start_of_hex_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/underscore_at_start_of_hex_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/underscore_at_start_of_hex_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/underscore_at_start_of_hex_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/underscore_before_number.kdl b/src/Kuddle.Net.Tests/test_cases/input/underscore_before_number.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/underscore_before_number.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/underscore_before_number.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/underscore_in_exponent.kdl b/src/Kuddle.Net.Tests/test_cases/input/underscore_in_exponent.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/underscore_in_exponent.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/underscore_in_exponent.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/underscore_in_float.kdl b/src/Kuddle.Net.Tests/test_cases/input/underscore_in_float.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/underscore_in_float.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/underscore_in_float.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/underscore_in_fraction.kdl b/src/Kuddle.Net.Tests/test_cases/input/underscore_in_fraction.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/underscore_in_fraction.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/underscore_in_fraction.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/underscore_in_int.kdl b/src/Kuddle.Net.Tests/test_cases/input/underscore_in_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/underscore_in_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/underscore_in_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/underscore_in_octal.kdl b/src/Kuddle.Net.Tests/test_cases/input/underscore_in_octal.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/underscore_in_octal.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/underscore_in_octal.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_delete_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_delete_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_delete_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_delete_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_escaped_above_max_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_above_max_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_escaped_above_max_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_above_max_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_escaped_h1_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_h1_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_escaped_h1_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_h1_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_escaped_h2_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_h2_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_escaped_h2_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_h2_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_escaped_h3_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_h3_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_escaped_h3_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_h3_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_escaped_h4_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_h4_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_escaped_h4_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_h4_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_escaped_l1_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_l1_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_escaped_l1_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_l1_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_escaped_l2_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_l2_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_escaped_l2_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_l2_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_escaped_l3_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_l3_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_escaped_l3_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_l3_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_escaped_too_long_lead0_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_too_long_lead0_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_escaped_too_long_lead0_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_escaped_too_long_lead0_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_fsi_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_fsi_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_fsi_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_fsi_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_lre_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_lre_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_lre_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_lre_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_lri_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_lri_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_lri_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_lri_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_lrm_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_lrm_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_lrm_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_lrm_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_lro_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_lro_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_lro_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_lro_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_pdf_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_pdf_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_pdf_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_pdf_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_pdi_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_pdi_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_pdi_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_pdi_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_rle_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_rle_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_rle_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_rle_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_rli_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_rli_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_rli_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_rli_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_rlm_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_rlm_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_rlm_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_rlm_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_rlo_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_rlo_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_rlo_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_rlo_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_silly.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_silly.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_silly.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_silly.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unicode_under_0x20_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unicode_under_0x20_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unicode_under_0x20_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unicode_under_0x20_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unterminated_empty_node_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/unterminated_empty_node_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unterminated_empty_node_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unterminated_empty_node_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unusual_bare_id_chars_in_quoted_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/unusual_bare_id_chars_in_quoted_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unusual_bare_id_chars_in_quoted_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unusual_bare_id_chars_in_quoted_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/unusual_chars_in_bare_id.kdl b/src/Kuddle.Net.Tests/test_cases/input/unusual_chars_in_bare_id.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/unusual_chars_in_bare_id.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/unusual_chars_in_bare_id.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/vertical_tab_whitespace.kdl b/src/Kuddle.Net.Tests/test_cases/input/vertical_tab_whitespace.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/vertical_tab_whitespace.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/vertical_tab_whitespace.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/zero_float.kdl b/src/Kuddle.Net.Tests/test_cases/input/zero_float.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/zero_float.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/zero_float.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/zero_int.kdl b/src/Kuddle.Net.Tests/test_cases/input/zero_int.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/zero_int.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/zero_int.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/zero_space_before_first_arg_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/zero_space_before_first_arg_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/zero_space_before_first_arg_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/zero_space_before_first_arg_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/zero_space_before_prop_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/zero_space_before_prop_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/zero_space_before_prop_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/zero_space_before_prop_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/zero_space_before_second_arg_fail.kdl b/src/Kuddle.Net.Tests/test_cases/input/zero_space_before_second_arg_fail.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/zero_space_before_second_arg_fail.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/zero_space_before_second_arg_fail.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/zero_space_before_slashdash_arg.kdl b/src/Kuddle.Net.Tests/test_cases/input/zero_space_before_slashdash_arg.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/zero_space_before_slashdash_arg.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/zero_space_before_slashdash_arg.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/zero_space_before_slashdash_children.kdl b/src/Kuddle.Net.Tests/test_cases/input/zero_space_before_slashdash_children.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/zero_space_before_slashdash_children.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/zero_space_before_slashdash_children.kdl
diff --git a/src/Kuddle.Tests/test_cases/input/zero_space_before_slashdash_prop.kdl b/src/Kuddle.Net.Tests/test_cases/input/zero_space_before_slashdash_prop.kdl
similarity index 100%
rename from src/Kuddle.Tests/test_cases/input/zero_space_before_slashdash_prop.kdl
rename to src/Kuddle.Net.Tests/test_cases/input/zero_space_before_slashdash_prop.kdl
diff --git a/src/Kuddle/AST/KdlArgument.cs b/src/Kuddle.Net/AST/KdlArgument.cs
similarity index 100%
rename from src/Kuddle/AST/KdlArgument.cs
rename to src/Kuddle.Net/AST/KdlArgument.cs
diff --git a/src/Kuddle/AST/KdlBlock.cs b/src/Kuddle.Net/AST/KdlBlock.cs
similarity index 100%
rename from src/Kuddle/AST/KdlBlock.cs
rename to src/Kuddle.Net/AST/KdlBlock.cs
diff --git a/src/Kuddle/AST/KdlBool.cs b/src/Kuddle.Net/AST/KdlBool.cs
similarity index 100%
rename from src/Kuddle/AST/KdlBool.cs
rename to src/Kuddle.Net/AST/KdlBool.cs
diff --git a/src/Kuddle/AST/KdlDocument.cs b/src/Kuddle.Net/AST/KdlDocument.cs
similarity index 61%
rename from src/Kuddle/AST/KdlDocument.cs
rename to src/Kuddle.Net/AST/KdlDocument.cs
index 8a11baf..f87ac17 100644
--- a/src/Kuddle/AST/KdlDocument.cs
+++ b/src/Kuddle.Net/AST/KdlDocument.cs
@@ -7,13 +7,13 @@ public sealed record KdlDocument : KdlObject
{
public List Nodes { get; init; } = [];
- public string ToString(KuddleWriterOptions? options = null)
+ public string ToString(KdlWriterOptions? options = null)
{
- return KuddleWriter.Write(this, options);
+ return KdlWriter.Write(this, options);
}
public override string ToString()
{
- return KuddleWriter.Write(this);
+ return KdlWriter.Write(this);
}
}
diff --git a/src/Kuddle/AST/KdlEntry.cs b/src/Kuddle.Net/AST/KdlEntry.cs
similarity index 100%
rename from src/Kuddle/AST/KdlEntry.cs
rename to src/Kuddle.Net/AST/KdlEntry.cs
diff --git a/src/Kuddle/AST/KdlNode.cs b/src/Kuddle.Net/AST/KdlNode.cs
similarity index 100%
rename from src/Kuddle/AST/KdlNode.cs
rename to src/Kuddle.Net/AST/KdlNode.cs
diff --git a/src/Kuddle/AST/KdlNull.cs b/src/Kuddle.Net/AST/KdlNull.cs
similarity index 100%
rename from src/Kuddle/AST/KdlNull.cs
rename to src/Kuddle.Net/AST/KdlNull.cs
diff --git a/src/Kuddle/AST/KdlNumber.cs b/src/Kuddle.Net/AST/KdlNumber.cs
similarity index 100%
rename from src/Kuddle/AST/KdlNumber.cs
rename to src/Kuddle.Net/AST/KdlNumber.cs
diff --git a/src/Kuddle/AST/KdlObject.cs b/src/Kuddle.Net/AST/KdlObject.cs
similarity index 100%
rename from src/Kuddle/AST/KdlObject.cs
rename to src/Kuddle.Net/AST/KdlObject.cs
diff --git a/src/Kuddle/AST/KdlProperty.cs b/src/Kuddle.Net/AST/KdlProperty.cs
similarity index 100%
rename from src/Kuddle/AST/KdlProperty.cs
rename to src/Kuddle.Net/AST/KdlProperty.cs
diff --git a/src/Kuddle/AST/KdlSkippedEntry.cs b/src/Kuddle.Net/AST/KdlSkippedEntry.cs
similarity index 100%
rename from src/Kuddle/AST/KdlSkippedEntry.cs
rename to src/Kuddle.Net/AST/KdlSkippedEntry.cs
diff --git a/src/Kuddle/AST/KdlString.cs b/src/Kuddle.Net/AST/KdlString.cs
similarity index 100%
rename from src/Kuddle/AST/KdlString.cs
rename to src/Kuddle.Net/AST/KdlString.cs
diff --git a/src/Kuddle/AST/KdlTrivia.cs b/src/Kuddle.Net/AST/KdlTrivia.cs
similarity index 100%
rename from src/Kuddle/AST/KdlTrivia.cs
rename to src/Kuddle.Net/AST/KdlTrivia.cs
diff --git a/src/Kuddle/AST/KdlValue.cs b/src/Kuddle.Net/AST/KdlValue.cs
similarity index 100%
rename from src/Kuddle/AST/KdlValue.cs
rename to src/Kuddle.Net/AST/KdlValue.cs
diff --git a/src/Kuddle/AST/NumberBase.cs b/src/Kuddle.Net/AST/NumberBase.cs
similarity index 100%
rename from src/Kuddle/AST/NumberBase.cs
rename to src/Kuddle.Net/AST/NumberBase.cs
diff --git a/src/Kuddle/AST/StringKind.cs b/src/Kuddle.Net/AST/StringKind.cs
similarity index 100%
rename from src/Kuddle/AST/StringKind.cs
rename to src/Kuddle.Net/AST/StringKind.cs
diff --git a/src/Kuddle/Exceptions/KuddleParseException.cs b/src/Kuddle.Net/Exceptions/KuddleParseException.cs
similarity index 100%
rename from src/Kuddle/Exceptions/KuddleParseException.cs
rename to src/Kuddle.Net/Exceptions/KuddleParseException.cs
diff --git a/src/Kuddle/Exceptions/KuddleSerializationException.cs b/src/Kuddle.Net/Exceptions/KuddleSerializationException.cs
similarity index 100%
rename from src/Kuddle/Exceptions/KuddleSerializationException.cs
rename to src/Kuddle.Net/Exceptions/KuddleSerializationException.cs
diff --git a/src/Kuddle/Exceptions/KuddleValidationException.cs b/src/Kuddle.Net/Exceptions/KuddleValidationException.cs
similarity index 100%
rename from src/Kuddle/Exceptions/KuddleValidationException.cs
rename to src/Kuddle.Net/Exceptions/KuddleValidationException.cs
diff --git a/src/Kuddle/Extensions/KuddleNodeExtensions.cs b/src/Kuddle.Net/Extensions/KdlNodeExtensions.cs
similarity index 97%
rename from src/Kuddle/Extensions/KuddleNodeExtensions.cs
rename to src/Kuddle.Net/Extensions/KdlNodeExtensions.cs
index 7c90031..18a3bb3 100644
--- a/src/Kuddle/Extensions/KuddleNodeExtensions.cs
+++ b/src/Kuddle.Net/Extensions/KdlNodeExtensions.cs
@@ -2,7 +2,7 @@
namespace Kuddle.Extensions;
-public static class KuddleNodeExtensions
+public static class KdlNodeExtensions
{
extension(KdlNode node)
{
diff --git a/src/Kuddle/Extensions/KuddleValueExtensions.cs b/src/Kuddle.Net/Extensions/KdlValueExtensions.cs
similarity index 98%
rename from src/Kuddle/Extensions/KuddleValueExtensions.cs
rename to src/Kuddle.Net/Extensions/KdlValueExtensions.cs
index 662051c..73da3a7 100644
--- a/src/Kuddle/Extensions/KuddleValueExtensions.cs
+++ b/src/Kuddle.Net/Extensions/KdlValueExtensions.cs
@@ -4,7 +4,7 @@
namespace Kuddle.Extensions;
-public static class KuddleValueExtensions
+public static class KdlValueExtensions
{
extension(KdlValue value)
{
diff --git a/src/Kuddle/Extensions/ParserExtensions.cs b/src/Kuddle.Net/Extensions/ParserExtensions.cs
similarity index 100%
rename from src/Kuddle/Extensions/ParserExtensions.cs
rename to src/Kuddle.Net/Extensions/ParserExtensions.cs
diff --git a/src/Kuddle/Extensions/SpanExtensions.cs b/src/Kuddle.Net/Extensions/SpanExtensions.cs
similarity index 76%
rename from src/Kuddle/Extensions/SpanExtensions.cs
rename to src/Kuddle.Net/Extensions/SpanExtensions.cs
index d1791b7..367fe66 100644
--- a/src/Kuddle/Extensions/SpanExtensions.cs
+++ b/src/Kuddle.Net/Extensions/SpanExtensions.cs
@@ -6,16 +6,6 @@ public static class SpanExtensions
{
extension(ReadOnlySpan span)
{
- public bool Any(Func predicate)
- {
- foreach (var item in span)
- {
- if (predicate(item))
- return true;
- }
- return false;
- }
-
public int MaxConsecutive(T target)
{
int max = 0;
diff --git a/src/Kuddle.Net/Extensions/TypeExtensions.cs b/src/Kuddle.Net/Extensions/TypeExtensions.cs
new file mode 100644
index 0000000..5aa58a6
--- /dev/null
+++ b/src/Kuddle.Net/Extensions/TypeExtensions.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Kuddle.Serialization;
+
+internal static class TypeExtensions
+{
+ extension(Type type)
+ {
+ internal bool IsNodeDefinition =>
+ type.GetProperties()
+ .Any(p =>
+ p.GetCustomAttribute() != null
+ || p.GetCustomAttribute() != null
+ );
+ internal bool IsComplexType =>
+ !type.IsValueType
+ && !type.IsPrimitive
+ && type != typeof(string)
+ && type != typeof(object)
+ && !type.IsInterface
+ && !type.IsAbstract;
+
+ internal bool IsDictionary =>
+ type.IsGenericType
+ && type.GetInterfaces()
+ .Any(i =>
+ i.IsGenericType
+ && (
+ i.GetGenericTypeDefinition() == typeof(IDictionary<,>)
+ || i.GetGenericTypeDefinition() == typeof(IReadOnlyDictionary<,>)
+ )
+ );
+
+ internal bool IsIEnumerable =>
+ type != typeof(string)
+ && !type.IsDictionary
+ && type.IsAssignableTo(typeof(IEnumerable));
+
+ internal (PropertyInfo, KdlArgumentAttribute)[] GetKdlArgProps() =>
+ type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
+ .Select(p => new
+ {
+ Property = p,
+ ArgAttr = p.GetCustomAttribute(),
+ })
+ .Where(x => x.ArgAttr is not null)
+ .OrderBy(x => x.ArgAttr!.Index)
+ .Select(x => (x.Property, x.ArgAttr!))
+ .ToArray();
+
+ internal (PropertyInfo, KdlPropertyAttribute)[] GetKdlPropProps() =>
+ type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
+ .Select(p => new
+ {
+ Property = p,
+ PropAttr = p.GetCustomAttribute(),
+ })
+ .Where(x => x.PropAttr is not null)
+ .Select(x => (x.Property, x.PropAttr!))
+ .ToArray();
+
+ internal (PropertyInfo, KdlNodeAttribute)[] GetKdlChildProps() =>
+ type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
+ .Select(p => new
+ {
+ Property = p,
+ ChildAttr = p.GetCustomAttribute(),
+ })
+ .Where(x => x.ChildAttr is not null)
+ .Select(x => (x.Property, x.ChildAttr!))
+ .ToArray();
+
+ public bool IsNullable() => Nullable.GetUnderlyingType(type) != null;
+ }
+}
diff --git a/src/Kuddle/GlobalSuppressions.cs b/src/Kuddle.Net/GlobalSuppressions.cs
similarity index 100%
rename from src/Kuddle/GlobalSuppressions.cs
rename to src/Kuddle.Net/GlobalSuppressions.cs
diff --git a/src/Kuddle.Net/Kuddle.Net.csproj b/src/Kuddle.Net/Kuddle.Net.csproj
new file mode 100644
index 0000000..883fd4c
--- /dev/null
+++ b/src/Kuddle.Net/Kuddle.Net.csproj
@@ -0,0 +1,43 @@
+
+
+ Kuddle
+ Kuddle.Net
+ Kuddle.Net
+ disable
+ enable
+ net10.0
+ preview
+ true
+
+
+ jamesshenry
+ jamesshenry
+ Kuddle.Net is a .NET implementation of a KDL parser/serializer targeting v2 of the spec. KDL is concise, human-readable language built for configuration and data exchange.
+ kdl;parser;serializer;configuration
+ LICENSE.md
+ https://github.com/jamesshenry/Kuddle.Net
+ https://github.com/jamesshenry/Kuddle.Net
+ git
+ readme.md
+ icon.png
+ Initial release of Kuddle.Net KDL parser/serializer.
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Kuddle/Parser/CharacterSets.cs b/src/Kuddle.Net/Parser/CharacterSets.cs
similarity index 51%
rename from src/Kuddle/Parser/CharacterSets.cs
rename to src/Kuddle.Net/Parser/CharacterSets.cs
index b25fa3e..e5a5f5c 100644
--- a/src/Kuddle/Parser/CharacterSets.cs
+++ b/src/Kuddle.Net/Parser/CharacterSets.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace Kuddle.Parser;
@@ -71,18 +72,72 @@ internal static bool IsNewline(char c)
};
}
- // internal static bool IsDisallowedLiteralCodePoint(char c)
- // {
- // return c switch
- // {
- // >= '\u0000' and <= '\u0008' => true, // various control characters
- // '\u007F' => true,
- // >= '\uD800' and <= '\uDFFF' => true, // unicode scalar value
- // (>= '\u200E' and <= '\u200F')
- // or (>= '\u202A' and <= '\u202E')
- // or (>= '\u2066' and <= '\u2069') => true, // unicode 'direction control' characters
- // '\uFEFF' => true, // unicode BOM
- // _ => false,
- // };
- // }
+ public static readonly HashSet ReservedTypes =
+ [
+ "i8",
+ "i16",
+ "i32",
+ "i64",
+ "u8",
+ "u16",
+ "u32",
+ "u64",
+ "f32",
+ "f64",
+ "decimal64",
+ "decimal128",
+ "date-time",
+ "time",
+ "date",
+ "duration",
+ "decimal",
+ "currency",
+ "country-2",
+ "country-3",
+ "ipv4",
+ "ipv6",
+ "url",
+ "uuid",
+ "regex",
+ "base64",
+ ];
+
+ ///
+ /// Maps KDL type annotations to their corresponding CLR types.
+ /// Not all reserved types have CLR equivalents (e.g., country codes, IP addresses as validated strings).
+ ///
+ public static readonly Dictionary TypeAnnotationToClrType = new()
+ {
+ ["i8"] = typeof(sbyte),
+ ["i16"] = typeof(short),
+ ["i32"] = typeof(int),
+ ["i64"] = typeof(long),
+ ["u8"] = typeof(byte),
+ ["u16"] = typeof(ushort),
+ ["u32"] = typeof(uint),
+ ["u64"] = typeof(ulong),
+ ["f32"] = typeof(float),
+ ["f64"] = typeof(double),
+ ["decimal64"] = typeof(decimal),
+ ["decimal128"] = typeof(decimal),
+ ["decimal"] = typeof(decimal),
+ ["date-time"] = typeof(DateTimeOffset),
+ ["time"] = typeof(TimeOnly),
+ ["date"] = typeof(DateOnly),
+ ["duration"] = typeof(TimeSpan),
+ ["uuid"] = typeof(Guid),
+ ["url"] = typeof(Uri),
+ ["base64"] = typeof(byte[]),
+ // These remain as strings with semantic meaning:
+ // "currency", "country-2", "country-3", "ipv4", "ipv6", "regex"
+ };
+
+ ///
+ /// Gets the CLR type for a KDL type annotation, or null if no mapping exists.
+ ///
+ public static Type? GetClrType(string? typeAnnotation) =>
+ typeAnnotation is not null
+ && TypeAnnotationToClrType.TryGetValue(typeAnnotation, out var type)
+ ? type
+ : null;
}
diff --git a/src/Kuddle/Parser/DebugParser.cs b/src/Kuddle.Net/Parser/DebugParser.cs
similarity index 100%
rename from src/Kuddle/Parser/DebugParser.cs
rename to src/Kuddle.Net/Parser/DebugParser.cs
diff --git a/src/Kuddle/Parser/KuddleGrammar.cs b/src/Kuddle.Net/Parser/KdlGrammar.cs
similarity index 95%
rename from src/Kuddle/Parser/KuddleGrammar.cs
rename to src/Kuddle.Net/Parser/KdlGrammar.cs
index 27fd64f..cc260f7 100644
--- a/src/Kuddle/Parser/KuddleGrammar.cs
+++ b/src/Kuddle.Net/Parser/KdlGrammar.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using System.Text.RegularExpressions;
using Kuddle.AST;
using Kuddle.Extensions;
@@ -11,7 +10,7 @@
namespace Kuddle.Parser;
-public static class KuddleGrammar
+public static class KdlGrammar
{
internal static readonly Parser Document;
@@ -68,7 +67,7 @@ public static class KuddleGrammar
IReadOnlyList
>();
- static KuddleGrammar()
+ static KdlGrammar()
{
var nodeSpace = Deferred();
@@ -137,14 +136,13 @@ static KuddleGrammar()
)
.Then(s => new TextSpan(s))
);
- // 1. Define a parser for Surrogate Pairs (valid emojis/symbols outside BMP)
+
var surrogatePair = Capture(
Literals
.Pattern(char.IsHighSurrogate, 1, 1)
.And(Literals.Pattern(char.IsLowSurrogate, 1, 1))
);
- // 2. Define the standard character parser (checks for disallowed chars like lone surrogates)
var singleChar = Literals.Pattern(
c => c != '\\' && c != '"' && !IsDisallowedLiteralCodePoint(c),
1,
@@ -158,20 +156,16 @@ static KuddleGrammar()
var singleLineStringBody = ZeroOrMany(StringCharacter)
.Then(x =>
{
- // Fast path: no characters means empty string
if (x.Count == 0)
return new TextSpan(string.Empty);
- // Fast path: single span can be returned directly
if (x.Count == 1)
return new TextSpan(x[0].Span.ToString());
- // Calculate total length to avoid StringBuilder resizing
int totalLength = 0;
for (int i = 0; i < x.Count; i++)
totalLength += x[i].Length;
- // Use string.Create for efficient concatenation
return new TextSpan(
string.Create(
totalLength,
@@ -266,7 +260,6 @@ static KuddleGrammar()
.Then(
(context, span) =>
{
- // Use span-based comparison to avoid allocation for valid identifiers
return IsReservedKeyword(span.Span)
? throw new ParseException(
$"The keyword '{span}' cannot be used as an unquoted identifier. Wrap it in quotes: \"{span}\".",
@@ -314,9 +307,7 @@ static KuddleGrammar()
.AndSkip(Literals.Text("0b"))
.And(Literals.Char('0').Or(Literals.Char('1')))
.And(ZeroOrMany(Literals.Pattern(c => c == '_' || IsBinaryChar(c))))
- )
- // .When((context, x) => x.Span[^1] != '_')
- ;
+ );
Boolean = Literals
.Text("#true")
.Or(Literals.Text("#false"))
@@ -338,7 +329,6 @@ static KuddleGrammar()
Number = OneOf(KeywordNumber, Hex, Octal, Binary, Decimal)
.Then((context, value) => new KdlNumber(value.Span.ToString()));
- // Comments
var multiLineComment = Deferred();
var openComment = Literals.Text("/*");
@@ -359,7 +349,6 @@ static KuddleGrammar()
var lineSpace = Deferred();
SlashDash = Capture(Literals.Text("/-").And(ZeroOrMany(lineSpace))).Debug("SlashDash");
- // Whitespace
Ws = Literals
.Pattern(c => CharacterSets.IsWhiteSpace(c), minSize: 1, maxSize: 1)
.Or(MultiLineComment)
@@ -380,8 +369,6 @@ static KuddleGrammar()
lineSpace.Parser = NodeSpace.Or(singleNewLine).Or(SingleLineComment);
LineSpace = lineSpace;
- // Entries
-
Type = Between(
Literals.Char('('),
ZeroOrMany(NodeSpace).SkipAnd(String).AndSkip(ZeroOrMany(NodeSpace)),
@@ -469,7 +456,7 @@ static KuddleGrammar()
{
if (result.Item1.HasValue)
return null;
- // Filter skipped entries - use single pass allocation
+
var entries = result.Item4;
var hasSkipped = false;
for (int i = 0; i < entries.Count; i++)
@@ -492,7 +479,6 @@ static KuddleGrammar()
}
else
{
- // No skipped entries - just copy to list
filteredEntries = new List(entries.Count);
for (int i = 0; i < entries.Count; i++)
filteredEntries.Add(entries[i]);
@@ -527,14 +513,12 @@ x.Item1 is null
.AndSkip(ZeroOrMany(LineSpace))
.Then(list =>
{
- // Single-pass filter to avoid Where().Select().ToList() triple allocation
List? filtered = null;
for (int i = 0; i < list.Count; i++)
{
var node = list[i];
if (node is null)
{
- // First null found - need to build filtered list
if (filtered is null)
{
filtered = new List(list.Count);
diff --git a/src/Kuddle/Parser/MultiLineStringParser.cs b/src/Kuddle.Net/Parser/MultiLineStringParser.cs
similarity index 94%
rename from src/Kuddle/Parser/MultiLineStringParser.cs
rename to src/Kuddle.Net/Parser/MultiLineStringParser.cs
index 962723c..8968089 100644
--- a/src/Kuddle/Parser/MultiLineStringParser.cs
+++ b/src/Kuddle.Net/Parser/MultiLineStringParser.cs
@@ -57,7 +57,6 @@ public override bool Parse(ParseContext context, ref ParseResult resu
int matchIndex = searchOffset + relativeIndex;
- // Count preceding backslashes
int backslashCount = 0;
int backScan = matchIndex - 1;
@@ -90,15 +89,12 @@ private static KdlString ProcessMultiLineString(
ParseContext context
)
{
- // Fast path: empty content
if (rawInput.IsEmpty)
return new KdlString(string.Empty, StringKind.MultiLine);
- // Check what processing we need
bool hasCR = rawInput.Contains('\r');
bool hasBackslash = rawInput.Contains('\\');
- // If no special characters, we can take a faster path
ReadOnlySpan normalized;
string? workingString = null;
@@ -112,14 +108,12 @@ ParseContext context
normalized = rawInput;
}
- // Handle whitespace escapes if present
if (hasBackslash)
{
workingString = ResolveWsEscapes(workingString ?? normalized.ToString());
normalized = workingString.AsSpan();
}
- // Find the last newline to extract the prefix (indentation)
int lastNewLine = normalized.LastIndexOf('\n');
ReadOnlySpan prefix;
@@ -136,7 +130,6 @@ ParseContext context
contentBody = ReadOnlySpan.Empty;
}
- // Validate prefix contains only whitespace
foreach (char c in prefix)
{
if (!CharacterSets.IsWhiteSpace(c))
@@ -148,10 +141,8 @@ ParseContext context
}
}
- // Build dedented string
string dedented = BuildDedentedString(contentBody, prefix, context);
- // Unescape if needed
string finalValue = hasBackslash ? UnescapeStandardKdl(dedented) : dedented;
return new KdlString(finalValue, StringKind.MultiLine);
@@ -159,7 +150,6 @@ ParseContext context
private static string NormalizeNewlines(ReadOnlySpan input)
{
- // Count output size first
int outputLength = 0;
for (int i = 0; i < input.Length; i++)
{
@@ -207,12 +197,10 @@ ParseContext context
if (contentBody.IsEmpty)
return string.Empty;
- // Skip leading newline
int startPos = 0;
if (contentBody[0] == '\n')
startPos = 1;
- // Fast path: no prefix means no dedentation needed
if (prefix.IsEmpty)
{
var body = contentBody.Slice(startPos);
@@ -221,7 +209,6 @@ ParseContext context
return body.ToString();
}
- // First pass: calculate output length and validate
int outputLength = 0;
int pos = startPos;
@@ -256,14 +243,12 @@ ParseContext context
pos = nextNewLine + 1;
}
- // Remove trailing newline
if (outputLength > 0)
outputLength--;
if (outputLength <= 0)
return string.Empty;
- // Second pass: build string
string prefixStr = prefix.ToString();
string contentStr = contentBody.ToString();
@@ -326,12 +311,10 @@ private static bool IsWhitespaceOnlyLine(ReadOnlySpan line)
private static string ResolveWsEscapes(string input)
{
- // Fast path: no backslashes
int backslashIdx = input.IndexOf('\\');
if (backslashIdx == -1)
return input;
- // Check if any backslash is followed by whitespace/newline (ws-escape pattern)
bool hasWsEscape = false;
for (int i = backslashIdx; i < input.Length - 1; i++)
{
@@ -349,8 +332,6 @@ private static string ResolveWsEscapes(string input)
if (!hasWsEscape)
return input;
- // Need to process ws-escapes
- // First pass: calculate output length
int outputLength = 0;
for (int i = 0; i < input.Length; i++)
{
@@ -358,15 +339,13 @@ private static string ResolveWsEscapes(string input)
{
int scanIdx = i + 1;
- // Skip whitespace
while (scanIdx < input.Length && (input[scanIdx] == ' ' || input[scanIdx] == '\t'))
scanIdx++;
- // Check for newline
if (scanIdx < input.Length && input[scanIdx] == '\n')
{
scanIdx++;
- // Skip whitespace after newline
+
while (
scanIdx < input.Length && (input[scanIdx] == ' ' || input[scanIdx] == '\t')
)
@@ -377,7 +356,6 @@ private static string ResolveWsEscapes(string input)
}
else if (scanIdx >= input.Length && scanIdx > i + 1)
{
- // Trailing ws-escape
i = scanIdx - 1;
continue;
}
@@ -428,12 +406,10 @@ private static string ResolveWsEscapes(string input)
private static string UnescapeStandardKdl(string input)
{
- // Fast path: no backslashes
int backslashIdx = input.IndexOf('\\');
if (backslashIdx == -1)
return input;
- // First pass: calculate output length
int outputLength = 0;
for (int i = 0; i < input.Length; i++)
{
diff --git a/src/Kuddle/Parser/RawStringParser.cs b/src/Kuddle.Net/Parser/RawStringParser.cs
similarity index 90%
rename from src/Kuddle/Parser/RawStringParser.cs
rename to src/Kuddle.Net/Parser/RawStringParser.cs
index 961b039..3860a54 100644
--- a/src/Kuddle/Parser/RawStringParser.cs
+++ b/src/Kuddle.Net/Parser/RawStringParser.cs
@@ -18,7 +18,6 @@ public override bool Parse(ParseContext context, ref ParseResult resu
var startPos = cursor.Position;
int currentOffset = startPos.Offset;
- // Count opening hashes
int hashCount = 0;
while (currentOffset < bufferSpan.Length && bufferSpan[currentOffset] == '#')
{
@@ -26,7 +25,6 @@ public override bool Parse(ParseContext context, ref ParseResult resu
currentOffset++;
}
- // Count opening quotes
int quoteCount = 0;
while (currentOffset < bufferSpan.Length && bufferSpan[currentOffset] == '"')
{
@@ -48,7 +46,6 @@ public override bool Parse(ParseContext context, ref ParseResult resu
bool isMultiline = quoteCount == 3;
- // Build closing delimiter: quotes followed by hashes
int needleLength = quoteCount + hashCount;
Span needle =
needleLength <= 256 ? stackalloc char[needleLength] : new char[needleLength];
@@ -70,7 +67,6 @@ public override bool Parse(ParseContext context, ref ParseResult resu
var contentSpan = remainingBuffer.Slice(0, matchIndex);
int totalLengthParsed = (currentOffset - startPos.Offset) + matchIndex + needleLength;
- // Advance cursor
for (int i = 0; i < totalLengthParsed; i++)
cursor.Advance();
@@ -84,7 +80,6 @@ public override bool Parse(ParseContext context, ref ParseResult resu
}
else
{
- // Raw single-line strings have no escape processing
content = contentSpan.ToString();
style = StringKind.Quoted | StringKind.Raw;
}
@@ -99,11 +94,9 @@ public override bool Parse(ParseContext context, ref ParseResult resu
///
public static string ProcessMultiLineRawString(ReadOnlySpan rawInput)
{
- // Fast path: empty content
if (rawInput.IsEmpty)
return string.Empty;
- // Check if we need newline normalization
bool hasCR = rawInput.Contains('\r');
ReadOnlySpan normalized;
@@ -111,7 +104,6 @@ public static string ProcessMultiLineRawString(ReadOnlySpan rawInput)
if (hasCR)
{
- // Need to normalize - allocate once
normalizedString = NormalizeNewlines(rawInput);
normalized = normalizedString.AsSpan();
}
@@ -120,7 +112,6 @@ public static string ProcessMultiLineRawString(ReadOnlySpan rawInput)
normalized = rawInput;
}
- // Find the last newline to extract the prefix (indentation)
int lastNewLine = normalized.LastIndexOf('\n');
ReadOnlySpan prefix;
@@ -137,7 +128,6 @@ public static string ProcessMultiLineRawString(ReadOnlySpan rawInput)
contentBody = ReadOnlySpan.Empty;
}
- // Validate prefix contains only whitespace
foreach (char c in prefix)
{
if (c != ' ' && c != '\t')
@@ -149,32 +139,27 @@ public static string ProcessMultiLineRawString(ReadOnlySpan rawInput)
}
}
- // If no content body, return empty
if (contentBody.IsEmpty)
return string.Empty;
- // Skip leading newline
int pos = 0;
if (contentBody[0] == '\n')
pos = 1;
- // Fast path: no prefix means no dedentation needed
if (prefix.IsEmpty)
{
var body = contentBody.Slice(pos);
- // Remove trailing newline if present
+
if (body.Length > 0 && body[^1] == '\n')
body = body.Slice(0, body.Length - 1);
return body.ToString();
}
- // Need to process with dedentation
return BuildDedentedString(contentBody, pos, prefix);
}
private static string NormalizeNewlines(ReadOnlySpan input)
{
- // Count output size to avoid StringBuilder resizing
int outputLength = 0;
for (int i = 0; i < input.Length; i++)
{
@@ -219,7 +204,6 @@ private static string BuildDedentedString(
ReadOnlySpan prefix
)
{
- // First pass: calculate output length and validate
int outputLength = 0;
int pos = startPos;
@@ -254,14 +238,12 @@ ReadOnlySpan prefix
pos = nextNewLine + 1;
}
- // Remove trailing newline
if (outputLength > 0)
outputLength--;
if (outputLength <= 0)
return string.Empty;
- // Second pass: build the string
string prefixStr = prefix.ToString();
string contentStr = contentBody.ToString();
@@ -314,7 +296,6 @@ ReadOnlySpan prefix
private static bool IsWhitespaceOnlyLine(ReadOnlySpan line)
{
- // Check all chars except the trailing newline
for (int i = 0; i < line.Length - 1; i++)
{
if (!char.IsWhiteSpace(line[i]))
diff --git a/src/Kuddle/Serialization/Attributes/KdlArgumentAttribute.cs b/src/Kuddle.Net/Serialization/Attributes/KdlArgumentAttribute.cs
similarity index 59%
rename from src/Kuddle/Serialization/Attributes/KdlArgumentAttribute.cs
rename to src/Kuddle.Net/Serialization/Attributes/KdlArgumentAttribute.cs
index ceda7b6..988719a 100644
--- a/src/Kuddle/Serialization/Attributes/KdlArgumentAttribute.cs
+++ b/src/Kuddle.Net/Serialization/Attributes/KdlArgumentAttribute.cs
@@ -3,7 +3,8 @@
namespace Kuddle.Serialization;
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
-public sealed class KdlArgumentAttribute(int index) : Attribute
+public sealed class KdlArgumentAttribute(int index, string? typeAnnotation = null)
+ : KdlEntryAttribute(typeAnnotation)
{
public int Index { get; } = index;
}
diff --git a/src/Kuddle.Net/Serialization/Attributes/KdlEntryAttribute.cs b/src/Kuddle.Net/Serialization/Attributes/KdlEntryAttribute.cs
new file mode 100644
index 0000000..27f0dba
--- /dev/null
+++ b/src/Kuddle.Net/Serialization/Attributes/KdlEntryAttribute.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Kuddle.Serialization;
+
+///
+/// Base class for KDL entry attributes. Only one entry attribute can be applied per property.
+///
+[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
+public abstract class KdlEntryAttribute : Attribute
+{
+ ///
+ /// Optional KDL type annotation (e.g., "uuid", "date-time", "i32").
+ ///
+ public string? TypeAnnotation { get; }
+
+ protected KdlEntryAttribute(string? typeAnnotation = null)
+ {
+ TypeAnnotation = typeAnnotation;
+ }
+}
diff --git a/src/Kuddle/Serialization/Attributes/KdlIgnoreAttribute.cs b/src/Kuddle.Net/Serialization/Attributes/KdlIgnoreAttribute.cs
similarity index 100%
rename from src/Kuddle/Serialization/Attributes/KdlIgnoreAttribute.cs
rename to src/Kuddle.Net/Serialization/Attributes/KdlIgnoreAttribute.cs
diff --git a/src/Kuddle/Serialization/Attributes/KdlNodeAttribute.cs b/src/Kuddle.Net/Serialization/Attributes/KdlNodeAttribute.cs
similarity index 58%
rename from src/Kuddle/Serialization/Attributes/KdlNodeAttribute.cs
rename to src/Kuddle.Net/Serialization/Attributes/KdlNodeAttribute.cs
index 1ac32ef..23a03cc 100644
--- a/src/Kuddle/Serialization/Attributes/KdlNodeAttribute.cs
+++ b/src/Kuddle.Net/Serialization/Attributes/KdlNodeAttribute.cs
@@ -3,7 +3,8 @@
namespace Kuddle.Serialization;
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
-public sealed class KdlNodeAttribute(string? name = null) : Attribute
+public sealed class KdlNodeAttribute(string? name = null, string? typeAnnotation = null)
+ : KdlEntryAttribute(typeAnnotation)
{
public string? Name { get; } = name;
}
diff --git a/src/Kuddle/Serialization/Attributes/KdlPropertyAttribute.cs b/src/Kuddle.Net/Serialization/Attributes/KdlPropertyAttribute.cs
similarity index 57%
rename from src/Kuddle/Serialization/Attributes/KdlPropertyAttribute.cs
rename to src/Kuddle.Net/Serialization/Attributes/KdlPropertyAttribute.cs
index 202d148..916208e 100644
--- a/src/Kuddle/Serialization/Attributes/KdlPropertyAttribute.cs
+++ b/src/Kuddle.Net/Serialization/Attributes/KdlPropertyAttribute.cs
@@ -3,7 +3,8 @@
namespace Kuddle.Serialization;
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
-public sealed class KdlPropertyAttribute(string? key = null) : Attribute
+public sealed class KdlPropertyAttribute(string? key = null, string? typeAnnotation = null)
+ : KdlEntryAttribute(typeAnnotation)
{
public string? Key { get; } = key;
}
diff --git a/src/Kuddle.Net/Serialization/Attributes/KdlTypeAttribute.cs b/src/Kuddle.Net/Serialization/Attributes/KdlTypeAttribute.cs
new file mode 100644
index 0000000..535030c
--- /dev/null
+++ b/src/Kuddle.Net/Serialization/Attributes/KdlTypeAttribute.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Kuddle.Serialization;
+
+[AttributeUsage(
+ AttributeTargets.Class | AttributeTargets.Property,
+ AllowMultiple = false,
+ Inherited = false
+)]
+public sealed class KdlTypeAttribute(string name) : Attribute
+{
+ public string Name { get; set; } = name;
+}
diff --git a/src/Kuddle/Serialization/KuddleReader.cs b/src/Kuddle.Net/Serialization/KdlReader.cs
similarity index 50%
rename from src/Kuddle/Serialization/KuddleReader.cs
rename to src/Kuddle.Net/Serialization/KdlReader.cs
index fdbb10e..a221251 100644
--- a/src/Kuddle/Serialization/KuddleReader.cs
+++ b/src/Kuddle.Net/Serialization/KdlReader.cs
@@ -1,17 +1,15 @@
using System;
-using System.IO;
-using System.Threading.Tasks;
using Kuddle.AST;
using Kuddle.Exceptions;
using Kuddle.Parser;
using Kuddle.Validation;
using Parlot.Fluent;
-namespace Kuddle;
+namespace Kuddle.Serialization;
-public static class KuddleReader
+public static class KdlReader
{
- private static readonly Parser _parser = KuddleGrammar.Document.Compile();
+ private static readonly Parser _parser = KdlGrammar.Document.Compile();
///
/// Parses a KDL string into a KdlDocument AST.
@@ -20,10 +18,10 @@ public static class KuddleReader
///
///
///
- public static KdlDocument Parse(string text, KuddleReaderOptions? options = null)
+ public static KdlDocument Read(string text, KdlReaderOptions? options = null)
{
ArgumentNullException.ThrowIfNull(text);
- options ??= KuddleReaderOptions.Default;
+ options ??= KdlReaderOptions.Default;
if (!_parser.TryParse(text, out var doc, out var error))
{
@@ -41,30 +39,9 @@ public static KdlDocument Parse(string text, KuddleReaderOptions? options = null
if (options.ValidateReservedTypes)
{
- KuddleReservedTypeValidator.Validate(doc);
+ KdlReservedTypeValidator.Validate(doc);
}
return doc;
}
-
- // ///
- // /// Reads a stream assuming UTF-8 encoding.
- // ///
- // public static async Task ReadAsync(
- // Stream stream,
- // KuddleReaderOptions? options = null
- // )
- // {
- // using var reader = new StreamReader(stream);
- // var text = await reader.ReadToEndAsync();
- // return await ReadASync(text, options);
- // }
-
- public static async Task ReadAsync(
- string text,
- KuddleReaderOptions? options = null
- )
- {
- return Parse(text, options);
- }
}
diff --git a/src/Kuddle.Net/Serialization/KdlReaderOptions.cs b/src/Kuddle.Net/Serialization/KdlReaderOptions.cs
new file mode 100644
index 0000000..b0841d5
--- /dev/null
+++ b/src/Kuddle.Net/Serialization/KdlReaderOptions.cs
@@ -0,0 +1,7 @@
+namespace Kuddle.Serialization;
+
+public record KdlReaderOptions
+{
+ public static KdlReaderOptions Default => new() { ValidateReservedTypes = true };
+ public bool ValidateReservedTypes { get; init; } = true;
+}
diff --git a/src/Kuddle.Net/Serialization/KdlSerializer.cs b/src/Kuddle.Net/Serialization/KdlSerializer.cs
new file mode 100644
index 0000000..388eab8
--- /dev/null
+++ b/src/Kuddle.Net/Serialization/KdlSerializer.cs
@@ -0,0 +1,533 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using Kuddle.AST;
+using Kuddle.Extensions;
+
+namespace Kuddle.Serialization;
+
+///
+/// Serializes and deserializes C# objects to/from KDL format.
+///
+public static class KdlSerializer
+{
+ private const StringComparison NodeNameComparison = StringComparison.OrdinalIgnoreCase;
+
+ #region Deserialization
+
+ ///
+ /// Deserializes a KDL document containing multiple nodes of type T.
+ ///
+ public static IEnumerable DeserializeMany(
+ string text,
+ KdlSerializerOptions? options = null,
+ CancellationToken cancellationToken = default
+ )
+ where T : new()
+ {
+ var doc = KdlReader.Read(text);
+ var metadata = TypeMetadata.For();
+
+ foreach (var node in doc.Nodes)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (!node.Name.Value.Equals(metadata.NodeName, NodeNameComparison))
+ {
+ throw new KuddleSerializationException(
+ $"Expected node '{metadata.NodeName}', found '{node.Name.Value}'."
+ );
+ }
+
+ var item = new T();
+ MapNodeToObject(node, item, metadata);
+ yield return item;
+ }
+ }
+
+ ///
+ /// Deserializes a KDL document to a single object of type T.
+ ///
+ public static T Deserialize(string text, KdlSerializerOptions? options = null)
+ where T : new()
+ {
+ var document = KdlReader.Read(text);
+ var metadata = TypeMetadata.For();
+
+ // Reject dictionary types
+ if (metadata.IsDictionary)
+ {
+ throw new KuddleSerializationException(
+ $"Dictionary deserialization is not supported. Type: {metadata.Type.Name}"
+ );
+ }
+
+ // Reject IEnumerable types (use DeserializeMany instead)
+ if (metadata.IsIEnumerable)
+ {
+ throw new KuddleSerializationException(
+ $"Cannot deserialize to collection type '{metadata.Type.Name}'. Use DeserializeMany() instead."
+ );
+ }
+
+ if (metadata.IsNodeDefinition)
+ {
+ // Type maps to a single KDL node
+ if (document.Nodes.Count != 1)
+ {
+ throw new KuddleSerializationException(
+ $"Expected exactly 1 root node for type '{typeof(T).Name}', found {document.Nodes.Count}."
+ );
+ }
+
+ var rootNode = document.Nodes[0];
+ if (!rootNode.Name.Value.Equals(metadata.NodeName, NodeNameComparison))
+ {
+ throw new KuddleSerializationException(
+ $"Expected node '{metadata.NodeName}', found '{rootNode.Name.Value}'."
+ );
+ }
+
+ var instance = new T();
+ MapNodeToObject(rootNode, instance, metadata);
+ return instance;
+ }
+ else
+ {
+ // Type maps to a document with child nodes as properties
+ var instance = new T();
+ MapChildNodes(document.Nodes, instance, metadata);
+ return instance;
+ }
+ }
+
+ ///
+ /// Maps a KDL node's entries and children to an object instance.
+ ///
+ private static void MapNodeToObject(KdlNode node, object instance, TypeMetadata metadata)
+ {
+ // Map arguments
+ foreach (var mapping in metadata.ArgumentAttributes)
+ {
+ var argValue = node.Arg(mapping.ArgumentIndex);
+ if (argValue is null)
+ {
+ throw new KuddleSerializationException(
+ $"Missing required argument at index {mapping.ArgumentIndex}'."
+ );
+ }
+
+ SetPropertyValue(mapping.Property, instance, argValue, mapping.TypeAnnotation);
+ }
+
+ // Map properties
+ foreach (var mapping in metadata.Properties)
+ {
+ var propKey = mapping.GetPropertyKey();
+ var kdlValue = node.Prop(propKey);
+
+ if (kdlValue is null)
+ {
+ continue; // Optional property, use default
+ }
+
+ SetPropertyValue(mapping.Property, instance, kdlValue, mapping.TypeAnnotation);
+ }
+
+ // Map child nodes
+ MapChildNodes(node.Children?.Nodes, instance, metadata);
+ }
+
+ ///
+ /// Maps child KDL nodes to properties marked with [KdlNode].
+ ///
+ private static void MapChildNodes(
+ IReadOnlyList? nodes,
+ object instance,
+ TypeMetadata metadata
+ )
+ {
+ if (nodes is null || nodes.Count == 0)
+ {
+ return;
+ }
+
+ foreach (var mapping in metadata.Children)
+ {
+ var nodeName = mapping.GetChildNodeName();
+ var matchingNodes = GetMatchingNodes(nodes, nodeName);
+
+ if (matchingNodes.Count == 0)
+ {
+ continue;
+ }
+
+ var propType = mapping.Property.PropertyType;
+ var propMeta = TypeMetadata.For(propType);
+
+ if (propMeta.IsIEnumerable)
+ {
+ SetCollectionProperty(mapping.Property, instance, matchingNodes);
+ }
+ else if (propMeta.IsComplexType)
+ {
+ if (matchingNodes.Count > 1)
+ {
+ throw new KuddleSerializationException(
+ $"Expected single node '{nodeName}' for property '{mapping.Property.Name}', found {matchingNodes.Count}."
+ );
+ }
+
+ SetComplexProperty(mapping.Property, instance, matchingNodes[0]);
+ }
+ else
+ {
+ // Scalar property - extract from first argument
+ if (matchingNodes.Count > 1)
+ {
+ throw new KuddleSerializationException(
+ $"Expected single node '{nodeName}' for scalar property '{mapping.Property.Name}', found {matchingNodes.Count}."
+ );
+ }
+
+ var argValue = matchingNodes[0].Arg(0);
+ if (argValue is not null)
+ {
+ SetPropertyValue(mapping.Property, instance, argValue, mapping.TypeAnnotation);
+ }
+ }
+ }
+ }
+
+ private static List GetMatchingNodes(IReadOnlyList nodes, string nodeName)
+ {
+ var result = new List();
+ foreach (var node in nodes)
+ {
+ if (node.Name.Value.Equals(nodeName, NodeNameComparison))
+ {
+ result.Add(node);
+ }
+ }
+ return result;
+ }
+
+ private static void SetPropertyValue(
+ PropertyInfo property,
+ object instance,
+ KdlValue kdlValue,
+ string? expectedTypeAnnotation = null
+ )
+ {
+ var result = KdlValueConverter.FromKdlOrThrow(
+ kdlValue,
+ property.PropertyType,
+ $"Property: {property.DeclaringType?.Name}.{property.Name}",
+ expectedTypeAnnotation
+ );
+
+ property.SetValue(instance, result);
+ }
+
+ private static void SetComplexProperty(PropertyInfo property, object instance, KdlNode node)
+ {
+ var childInstance =
+ Activator.CreateInstance(property.PropertyType)
+ ?? throw new KuddleSerializationException(
+ $"Failed to create instance of '{property.PropertyType.Name}' for property '{property.Name}'."
+ );
+
+ var childMetadata = TypeMetadata.For(property.PropertyType);
+ MapNodeToObject(node, childInstance, childMetadata);
+
+ property.SetValue(instance, childInstance);
+ }
+
+ private static void SetCollectionProperty(
+ PropertyInfo property,
+ object instance,
+ List