<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chris</title>
    <description>The latest articles on DEV Community by Chris (@furesoft).</description>
    <link>https://dev.to/furesoft</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F978230%2F26ca2428-a4d7-4c16-af46-b0ed581e4b5d.jpeg</url>
      <title>DEV Community: Chris</title>
      <link>https://dev.to/furesoft</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/furesoft"/>
    <language>en</language>
    <item>
      <title>Parsing in C#</title>
      <dc:creator>Chris</dc:creator>
      <pubDate>Mon, 12 Aug 2024 12:31:12 +0000</pubDate>
      <link>https://dev.to/furesoft/parsing-in-c-45ih</link>
      <guid>https://dev.to/furesoft/parsing-in-c-45ih</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/furesoft/Silverfly" rel="noopener noreferrer"&gt;Silverfly&lt;/a&gt; is a robust framework designed for building parsers with a focus on reusability through a composition pattern. This approach allows you to reuse existing parsers or components seamlessly. But why create another parsing framework? As someone who has developed numerous parsers—sometimes by generating them from EBNF, other times by coding from scratch—I often found the process cumbersome. The need to learn a new language and the lack of control over how the code functions or how error messages are generated were frustrating. That’s why I decided to create Silverfly—a framework that maximizes reusability and control. &lt;/p&gt;

&lt;p&gt;To demonstrate just how straightforward it is to build a parser with Silverfly, this article will guide you through the creation of a JSON parser.&lt;/p&gt;

&lt;h2&gt;
  
  
  The JsonGrammar Class
&lt;/h2&gt;

&lt;p&gt;At the core of our JSON parser is the JsonGrammar class, which extends the base Parser class. This class is where we define the rules for lexing and parsing JSON data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JsonGrammar&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Parser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InitLexer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LexerConfig&lt;/span&gt; &lt;span class="n"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Lexer configuration&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InitParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParserDefinition&lt;/span&gt; &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Parser configuration&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring the Lexer
&lt;/h2&gt;

&lt;p&gt;In this setup, we define keywords for null, true, and false, instruct the lexer to ignore whitespace, and enable it to recognize boolean values, numbers, and strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InitLexer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LexerConfig&lt;/span&gt; &lt;span class="n"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddKeywords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"null"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//true and false are only registered for the repl syntax highlighting&lt;/span&gt;
    &lt;span class="n"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IgnoreWhitespace&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MatchBoolean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MatchNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MatchString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring the Parser
&lt;/h2&gt;

&lt;p&gt;Next, we configure the parser in the InitParser method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InitParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParserDefinition&lt;/span&gt; &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCommonLiterals&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ObjectParselet&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"null"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NullParselet&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"["&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JsonArrayParselet&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we add common literals (likely for numbers, strings, and boolean values) and register specialized parselets to handle objects ({), null values, and arrays ([).&lt;/p&gt;

&lt;h2&gt;
  
  
  Parselets
&lt;/h2&gt;

&lt;p&gt;Parselets are specialized classes responsible for parsing specific JSON structures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ObjectParselet: Manages JSON objects, such as {"key": "value"}&lt;/li&gt;
&lt;li&gt;NullParselet: Handles null values.&lt;/li&gt;
&lt;li&gt;JsonArrayParselet: Parses JSON arrays, such as [1, 2, 3].&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Parsing Null-Values
&lt;/h3&gt;

&lt;p&gt;Parsing a null value is straightforward. We implement the IPrefixParselet interface and return a LiteralNode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NullParselet&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IPrefixParselet&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;AstNode&lt;/span&gt; &lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;LiteralNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Parsing JSON Objects
&lt;/h3&gt;

&lt;p&gt;Now, let's dive deeper into the ObjectParselet class, which handles JSON object parsing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectParselet&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IPrefixParselet&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;AstNode&lt;/span&gt; &lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Dictionary to store key-value pairs of the JSON object&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;objectMembers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AstNode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Continue parsing until we encounter a closing brace&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"}"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Parse the key, which must be a string&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;keyToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Consume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PredefinedSymbols&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keyToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Consume the colon separator&lt;/span&gt;
            &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Consume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// Parse the value associated with the key&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ParseExpression&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Add the key-value pair to our dictionary&lt;/span&gt;
            &lt;span class="n"&gt;objectMembers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;// If we don't find a comma, we've reached the end of the object&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Consume the closing brace&lt;/span&gt;
        &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Consume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Create and return a new JsonObject node with our parsed members&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JsonObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objectMembers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code builds a dictionary of key-value pairs, continually parsing until it encounters a closing brace (}), at which point it returns a JsonObject node containing the parsed members.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parsing JSON Arrays
&lt;/h2&gt;

&lt;p&gt;Finally, let's explore the JsonArrayParselet class, which is tasked with parsing JSON arrays. Like other parselets, it implements the IPrefixParselet interface, maintaining consistency within the framework.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JsonArrayParselet&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IPrefixParselet&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;AstNode&lt;/span&gt; &lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ParseSeperated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"]"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JsonArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This class efficiently parses an array by identifying elements separated by commas until it reaches a closing bracket (]).&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Parser
&lt;/h2&gt;

&lt;p&gt;To use the JSON parser, you would typically create an instance of the JsonGrammar class and then call the Parse method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;jsonGrammar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JsonGrammar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonGrammar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advantages of this Approach
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Flexibility: The framework’s design makes it simple to support new data formats by creating new Grammar classes.&lt;/li&gt;
&lt;li&gt;Extensibility: Complex structures can be handled effortlessly by adding new Parselets.&lt;/li&gt;
&lt;li&gt;Readability: The declarative style of the Grammar definition ensures the code is easy to read and maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Silverfly parser framework offers a powerful and adaptable method for parsing JSON. By clearly separating lexing and parsing, and utilizing specialized Parselets and matchers, Silverfly enables efficient and structured handling of JSON data. Moreover, this approach can easily be extended to other data formats or languages, making it a solid foundation for a variety of parsing tasks in your projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix
&lt;/h2&gt;

&lt;p&gt;The Silverfly framework is not just limited to parsing JSON—it's a versatile tool with several advanced features that can enhance your development experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pretty Error Messages
&lt;/h3&gt;

&lt;p&gt;Silverfly can display pretty error messages in the console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bzsmqr39p27v12dmtbo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bzsmqr39p27v12dmtbo.png" alt="Pretty Error Message" width="379" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  REPL
&lt;/h3&gt;

&lt;p&gt;Silverfly also excels in interactive programming environments. It offers built-in support for creating Read-Eval-Print Loops (REPLs) with syntax highlighting. This feature is particularly valuable for developers who want to test and evaluate code snippets on the fly. The syntax highlighting not only makes the code more readable but also helps in identifying syntax errors early, leading to a smoother and more intuitive development process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xut3tyd95i4f7wuqd5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xut3tyd95i4f7wuqd5u.png" alt="REPL Input" width="352" height="29"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>parser</category>
      <category>dsl</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Experience with rewriting a complete application</title>
      <dc:creator>Chris</dc:creator>
      <pubDate>Thu, 15 Dec 2022 07:21:53 +0000</pubDate>
      <link>https://dev.to/furesoft/experience-with-rewriting-a-complete-application-5cge</link>
      <guid>https://dev.to/furesoft/experience-with-rewriting-a-complete-application-5cge</guid>
      <description>&lt;p&gt;Hello friends of programming,&lt;/p&gt;

&lt;p&gt;in this post I am going to tell you my experiences of rewriting a working application from scratch.&lt;/p&gt;

&lt;p&gt;But first, which application?&lt;/p&gt;

&lt;p&gt;I have done a lots of work for my tool for the Remarkable tablet called Slithin. But there were some problems. I have not known that the application would be so complex and big. So I started programming without any plan. Later there were some problems and I have decided to use an IOC-Container to fix the dependency hell. But for some reason now there are such a big amount of code smells from the old synchronisation algorithm that cannot be easily removed and the dependency problem is not complete solved.&lt;/p&gt;

&lt;p&gt;Because I have worked most of my time on my programming language I leaved the focus on this project but since I had the idea of making a framework for modular applications I had decided to rewrite Slithin with my custom framework. The application structure is now modular. You can simply replace them and they are seperated by other modules.&lt;/p&gt;

&lt;p&gt;But what is a module?&lt;/p&gt;

&lt;p&gt;A module consist of two assemblies. One for the logic and the other for the models. A module can register services that other modules can interact with but it can also invoke custom logic with a &lt;code&gt;OnStart&lt;/code&gt; method. &lt;/p&gt;

&lt;p&gt;Modules can communicate without any dependencies. Every module has an Inbox and an Outbox to send/receive messages. You can simply send data or trigger some actions on specific kind of messages. So modules can be loosly coupled.&lt;/p&gt;

&lt;p&gt;A module can also have sub-actions that can be scheduled. A module can invoke for example writing the log cache to file every 10 minutes. &lt;/p&gt;

&lt;p&gt;Because the modulesystem is so flexible you can create a model to specify the contract you can implement different modules for different providers like different databases. &lt;/p&gt;

&lt;p&gt;The framework has some loosly coupled services/modules implemeted by default for example for logging with different logging frameworks. &lt;/p&gt;

&lt;p&gt;So back to slithin:&lt;/p&gt;

&lt;p&gt;Slithin has now only a bootstrapper executable that loads the modules and start them. Each functionality is now splitted into it's own module. The userinterface, the file synchronisation, the communication with the device and the communication with the filesystem for example. This modularity gives the opportunity to handle dependencies easily. The only thing I have to think of is which modules have to be loaded first to register the services that other modules need. &lt;/p&gt;

&lt;p&gt;I have learned so much with this project and for the future I am going to make a plan for new applications (requirements and code architecture).&lt;/p&gt;

&lt;p&gt;If you want to take a look here are the repositories:&lt;br&gt;
&lt;a href="https://github.com/furesoft/Slithin" rel="noopener noreferrer"&gt;Slithin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/furesoft/AuroraModularis" rel="noopener noreferrer"&gt;AuroraModularis - framework for modular applications&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was my little story.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>programming</category>
    </item>
    <item>
      <title>Backlang- Status Report</title>
      <dc:creator>Chris</dc:creator>
      <pubDate>Wed, 30 Nov 2022 07:38:01 +0000</pubDate>
      <link>https://dev.to/furesoft/backlang-status-report-3ahl</link>
      <guid>https://dev.to/furesoft/backlang-status-report-3ahl</guid>
      <description>&lt;p&gt;Hello friends of programming,&lt;/p&gt;

&lt;p&gt;This is the first post about the status of &lt;a href="https://www.backlang.org/#/" rel="noopener noreferrer"&gt;backlang&lt;/a&gt;. But first, why making a new language? I can answer this question really quickly. A big reason for me is I want to reduce my daily code that I write. The compiler should generate automaticly what it needs to create a runnable executable. I also really love making languages. In the past I have created some Domain Specific Languages and I have discovered many ways to write parsers. From parser generators to parser combinators over parsers from scratch. Backlang helps me a lot to learn more about formal languages and compilers.  &lt;/p&gt;

&lt;p&gt;So here are the first things that are already implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declare classes/structs/enums/functions/unions/discriminated unions/interfaces&lt;/li&gt;
&lt;li&gt;Extend types, also types that are not part of your assembly&lt;/li&gt;
&lt;li&gt;Generate overloads for different primitve types&lt;/li&gt;
&lt;li&gt;Generate ToString, Constructor and GetHashCode for structs&lt;/li&gt;
&lt;li&gt;Declare mutable and immutable variables&lt;/li&gt;
&lt;li&gt;Assignments&lt;/li&gt;
&lt;li&gt;Type deduction for values/members&lt;/li&gt;
&lt;li&gt;default and typeof expressions&lt;/li&gt;
&lt;li&gt;Macro expansion&lt;/li&gt;
&lt;li&gt;Operator overloading&lt;/li&gt;
&lt;li&gt;Array declaration&lt;/li&gt;
&lt;li&gt;Pointer and reference types/reference&lt;/li&gt;
&lt;li&gt;Reference parameters&lt;/li&gt;
&lt;li&gt;Type deduction for variables&lt;/li&gt;
&lt;li&gt;Property declarations&lt;/li&gt;
&lt;li&gt;Conditions&lt;/li&gt;
&lt;li&gt;Import namespace with wildcard(import all namespaces one layer deep)&lt;/li&gt;
&lt;li&gt;While/Do-While loops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see there is a lot implemented but unfortunately not enough to write working programs. There are some features implemented like if-else-statements but they work not as supposed to do.&lt;/p&gt;

&lt;p&gt;But I have good news. I make really good progress. I have implemented such new good things like automatic return type deduction for functions. Now you don't need to specify the return type in most of the simple cases. I'll extend the return type deducing so in future you can miss types for complex types like for generics.&lt;br&gt;
But how does the return type deduction work?&lt;/p&gt;

&lt;p&gt;The implementation is really simple. First it checks if they can be implicit casted through a simple map or an operator overload if at least one is defined. If they cannot be casted the algorithm looks for the parent types. If the algorithm cannot find a common type between those types it looks recursive on the next layer of inheritance. If the type is System.ValueType or System.Object the algorithm stops and throws an error.&lt;/p&gt;

&lt;p&gt;That was the compiler. But what differs a programming language from a good programming language? - The tooling to make it easier to write code and find errors.&lt;/p&gt;

&lt;p&gt;I've been working on a visual studio code extension since the parser is functional. The extension has simple syntax highlighting, code folding and for now "simple" code completion for keywords. Simple means that the language server cannot suggest names and other stuff for now. But the completion system in the language server is clever. It suggests not all keywords, only those which are valid in a certain context like the &lt;code&gt;mut&lt;/code&gt; keyword it is only valid in a variable declaration.&lt;/p&gt;

&lt;p&gt;As you can see I give all my passion to this language. I really want to make it usable. But making a new programming language is really time consuming for one man. There is not only the compiler and the vscode extension. A huge part is also the documentation and the website. &lt;/p&gt;

&lt;p&gt;If you like this language please share it with your friends or contribute. I really need help in some parts like integrating the debugger into the vs code extension. &lt;/p&gt;

&lt;p&gt;This was a little journey to backlang. I hope you enjoyed it and see you the next post.&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>gratitude</category>
    </item>
  </channel>
</rss>
