<?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: Devin Weaver</title>
    <description>The latest articles on DEV Community by Devin Weaver (@sukima).</description>
    <link>https://dev.to/sukima</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%2F39729%2F2a03ed61-8816-477e-947e-49a76c160382.png</url>
      <title>DEV Community: Devin Weaver</title>
      <link>https://dev.to/sukima</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sukima"/>
    <language>en</language>
    <item>
      <title>Dealing with relative paths in JavaScript URL parsing</title>
      <dc:creator>Devin Weaver</dc:creator>
      <pubDate>Fri, 27 Jun 2025 21:02:44 +0000</pubDate>
      <link>https://dev.to/sukima/dealing-with-relative-paths-in-javascript-url-parsing-45jl</link>
      <guid>https://dev.to/sukima/dealing-with-relative-paths-in-javascript-url-parsing-45jl</guid>
      <description>&lt;p&gt;Hey friends! 👋 Let's talk about a neat trick for handling URLs in our apps, especially when dealing with relative paths.&lt;br&gt;
You know, those paths that look like &lt;code&gt;/app/route&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the deal: The URL constructor in JavaScript usually needs a full URI, including the schema (like &lt;code&gt;https://&lt;/code&gt; or &lt;code&gt;ftp://&lt;/code&gt;).&lt;br&gt;
But, we often work with relative paths that don't have all that extra info.&lt;/p&gt;

&lt;p&gt;Now, we could add a fake domain like &lt;code&gt;https://example.com/&lt;/code&gt; to make it work, but that feels a bit... well, fake! 😅&lt;/p&gt;

&lt;p&gt;Here's where it gets interesting: There's this cool thing called the &lt;code&gt;thismessage:/&lt;/code&gt; schema. It's like a special code that tells the URL parser, "Hey, just focus on the path part, don't worry about domains and stuff." It's perfect for our relative paths!&lt;/p&gt;

&lt;p&gt;The smart folks at &lt;a href="https://www.w3.org/wiki/UriSchemes/thismessage" rel="noopener noreferrer"&gt;W3C&lt;/a&gt; created this schema specifically for situations like ours. It's like a magic wand 🪄 that lets us parse relative paths without any extra baggage.&lt;/p&gt;

&lt;p&gt;Here's how we use it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We add &lt;code&gt;thismessage:/&lt;/code&gt; to our relative path.&lt;/li&gt;
&lt;li&gt;We parse it using the URL constructor.&lt;/li&gt;
&lt;li&gt;We do whatever we need to do with the URL object.&lt;/li&gt;
&lt;li&gt;When we're done, we can easily remove the &lt;code&gt;thismessage:&lt;/code&gt; part to get back our original relative path.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fullURI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/app/route?query=params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;relativeURI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/app/route?query=params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullURI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;relativeURI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// THROWS exception!&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullURI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;thismessage:/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;relativeURI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;thismessage:/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It's like putting on a special hat to get through a door, and then taking it off once we're inside! 🎩&lt;/p&gt;

&lt;p&gt;And it is reversible in cases when you need to preserve the URI&lt;br&gt;
but not the schema/hostname portions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;thismessage:/app/route&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// will auto URL encode correctly&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;someString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; "/app/route?query=params"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach is actually backed by some official internet rules (RFC2557 &lt;a href="https://www.rfc-editor.org/rfc/rfc2557.html#section-5" rel="noopener noreferrer"&gt;§5&lt;/a&gt; &amp;amp; &lt;a href="https://www.rfc-editor.org/rfc/rfc2557.html#section-12" rel="noopener noreferrer"&gt;§12&lt;/a&gt;, for the curious cats out there 🐱). These rules say that when you can't resolve a relative URI any other way, you should treat it as if it started with &lt;code&gt;thismessage:/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There you have it! A friendly, standards-compliant way to work with relative paths in our URL handling. It's like having a Swiss Army knife for URLs – versatile and handy!&lt;/p&gt;

&lt;p&gt;I hope this explanation makes the concept clearer and more fun to understand. Happy coding, everyone! 🚀💻&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>The Convergence of Literary Code: How AI Code Generation Accidentally Embodies Literate Programming Ideals</title>
      <dc:creator>Devin Weaver</dc:creator>
      <pubDate>Thu, 29 May 2025 11:50:00 +0000</pubDate>
      <link>https://dev.to/sukima/the-convergence-of-literary-code-how-ai-code-generation-accidentally-embodies-literate-programming-5cj</link>
      <guid>https://dev.to/sukima/the-convergence-of-literary-code-how-ai-code-generation-accidentally-embodies-literate-programming-5cj</guid>
      <description>&lt;p&gt;I had the thought the other day that the process of AI assisted discovery and generation was similar to what I understood as “Literate Programming”. Though at the time I did not have a means to articulate that similarity myself. And so what self respecting writer could write about AI without using AI?&lt;/p&gt;

&lt;p&gt;I dove into using Claude 3.7 Sonnet to have a conversation about this idea. I first had to give it some context:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; Compile a list of concepts for the philosophy of “literate programming”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It did some web searching and then as usual spit out a summarization of the topic. With some knowledge context in hand I then took it a step further to redirect the focus to the topic:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; With that understanding, make a comparison of literate programming and the use of ai prompting to generate code&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And here is where I was concerned; as it generated a bunch of lists highlighting one concept &lt;strong&gt;versus&lt;/strong&gt; another concept. It pitted them against each other instead of comparing similarities.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt; While literate programming treats &lt;strong&gt;programming as literature&lt;/strong&gt; with emphasis on human understanding and exposition, AI prompting treats programming as &lt;strong&gt;problem-solving automation&lt;/strong&gt;. Literate programming seeks to elevate the craft through careful explanation and style, while AI prompting seeks to democratize and accelerate code production. The former prioritizes the journey of understanding, while the latter prioritizes the destination of working code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn’t what I had in mind; time for me to coach the AI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; Given how LLMs are alliteration predictors and when generating code do so in a form of human-computer dialogue with essay like responses, are there any similarities to how literate programming is focused on understanding and ai code generation comes with prose and chain of thought conversations?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then it happened, somehow the pattern recognition saw what I was thinking.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt; This is a fascinating observation that reveals some striking philosophical parallels between literate programming and AI code generation, despite their different origins and mechanisms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And there I had it. I was able to use the detailed similarities comparison it generated to drive the creation of an essay. To which I will now place here for your enjoyment. &lt;em&gt;This was generated by AI, read and verified by me, and I align with the core message of this essay.&lt;/em&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  The Convergence of Literary Code: How AI Code Generation Accidentally Embodies Literate Programming Ideals
&lt;/h1&gt;

&lt;p&gt;When Donald Knuth introduced &lt;strong&gt;literate programming&lt;/strong&gt; in 1984, he envisioned a radical departure from conventional software development. &lt;strong&gt;The practitioner of literate programming can be regarded as an essayist, whose main concern is with exposition and excellence of style&lt;/strong&gt; . This paradigm &lt;strong&gt;represents a move away from writing computer programs in the manner and order imposed by the compiler, and instead gives programmers macros to develop programs in the order demanded by the logic and flow of their thoughts&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;Four decades later, large language models have emerged as powerful code generation tools, operating through human-computer dialogue with essay-like responses. While these systems were not designed with Knuth's literary vision in mind, they exhibit remarkable philosophical parallels to literate programming principles—suggesting that human-readable, explanation-rich code presentation may be a natural evolution in programming methodology.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Literary Foundation of Code
&lt;/h2&gt;

&lt;p&gt;Knuth's core insight was that &lt;strong&gt;programmers should think of programs as works of literature&lt;/strong&gt; . &lt;strong&gt;Literate programming is a programming paradigm in which a computer program is given as an explanation of how it works in a natural language, such as English, interspersed with snippets of macros and traditional source code&lt;/strong&gt; . The fundamental principle treats &lt;strong&gt;a program as a piece of literature, addressed to human beings rather than to a computer&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;This approach &lt;strong&gt;combines a programming language with a documentation language, making programs more robust, more portable, more easily maintained, and arguably more fun to write&lt;/strong&gt; . The methodology emphasizes &lt;strong&gt;the organization of source code into small sections and the production of a book quality program listing&lt;/strong&gt; , creating what amounts to &lt;strong&gt;hypertext documents&lt;/strong&gt;  that prioritize human understanding over machine efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Conversational Nature of AI Code Generation
&lt;/h2&gt;

&lt;p&gt;Large language models, functioning as sophisticated pattern predictors, generate code within inherently conversational contexts. When prompted to solve programming problems, these systems naturally produce &lt;strong&gt;essay-like responses&lt;/strong&gt; that combine natural language explanation with code snippets—a format that mirrors literate programming's integration of exposition and implementation.&lt;/p&gt;

&lt;p&gt;This conversational approach creates a &lt;strong&gt;human-computer dialogue&lt;/strong&gt; where code emerges through iterative explanation and refinement. The AI's responses typically follow a &lt;strong&gt;chain-of-thought progression&lt;/strong&gt;, building solutions through logical exposition rather than jumping directly to implementation details. This process echoes literate programming's emphasis on &lt;strong&gt;top-down exposition&lt;/strong&gt;  and development &lt;strong&gt;in the order demanded by the logic and flow of their thoughts&lt;/strong&gt; .&lt;/p&gt;

&lt;h2&gt;
  
  
  Philosophical Convergences
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Exposition-Driven Development&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Both approaches prioritize &lt;strong&gt;explanation as a primary concern&lt;/strong&gt;. Literate programming treats the programmer as &lt;strong&gt;an essayist, whose main concern is with exposition and excellence of style&lt;/strong&gt; , while AI code generation naturally embeds code within explanatory contexts that aid human understanding. The AI's responses demonstrate a similar commitment to making code comprehensible through prose.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Natural Language Integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Knuth's vision of &lt;strong&gt;natural language explanations interspersed with code snippets&lt;/strong&gt;  finds unexpected realization in AI-generated responses. Both approaches seamlessly blend programming logic with human-readable explanation, creating unified presentations that serve both functional and educational purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Human-Centric Presentation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Literate programming emphasizes &lt;strong&gt;human readability as a primary concern&lt;/strong&gt; , treating programs as &lt;strong&gt;literature addressed to human beings rather than to a computer&lt;/strong&gt; . Similarly, AI code generation prioritizes human understanding through conversational interfaces, presenting solutions in formats optimized for human comprehension rather than machine efficiency.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Flexible Organization&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Both methodologies move away from &lt;strong&gt;compiler-imposed structure&lt;/strong&gt;. Literate programming allows development &lt;strong&gt;in the order demanded by the logic and flow of their thoughts&lt;/strong&gt; , while AI responses follow &lt;strong&gt;conversational logic&lt;/strong&gt; and problem-solving progression rather than strict programming constraints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fundamental Distinctions
&lt;/h2&gt;

&lt;p&gt;Despite these convergences, crucial differences separate the two approaches:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Intentionality and Craftsmanship&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Literate programming requires &lt;strong&gt;deliberate human craftsmanship&lt;/strong&gt; and commitment to &lt;strong&gt;excellence of style&lt;/strong&gt; . The programmer consciously constructs both code and exposition as literary art. AI generation, while producing explanatory responses, lacks the &lt;strong&gt;intentional literary quality&lt;/strong&gt; that defines Knuth's vision.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Philosophical Purpose&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Literate programming aims to elevate programming to &lt;strong&gt;literary art&lt;/strong&gt;, emphasizing &lt;strong&gt;book quality program listing&lt;/strong&gt;  and treating code as &lt;strong&gt;works of literature&lt;/strong&gt; . AI code generation serves &lt;strong&gt;functional problem-solving&lt;/strong&gt; within conversational interfaces, prioritizing utility over literary excellence.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Knowledge Preservation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Literate programming preserves &lt;strong&gt;human thought processes&lt;/strong&gt; and reasoning within code structure, creating lasting documentation of decision-making. AI responses, while explanatory, represent &lt;strong&gt;algorithmic pattern matching&lt;/strong&gt; rather than genuine human insight preservation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Accidental Embodiment
&lt;/h2&gt;

&lt;p&gt;The convergence reveals how &lt;strong&gt;LLMs accidentally embody some literate programming ideals&lt;/strong&gt; without the philosophical commitment to programs as literature. AI systems achieve &lt;strong&gt;functional literacy&lt;/strong&gt;—making code accessible through dialogue—while literate programming pursues &lt;strong&gt;artistic literacy&lt;/strong&gt; through deliberate literary methodology.&lt;/p&gt;

&lt;p&gt;This parallel suggests that &lt;strong&gt;human-readable, explanation-rich code presentation&lt;/strong&gt; may be an inevitable evolution in programming, whether achieved through conscious literary practice or emergent conversational AI capabilities. Both approaches recognize that code serves not just machines but human understanding, though they pursue this goal through different philosophical frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implications for Programming Practice
&lt;/h2&gt;

&lt;p&gt;The unexpected alignment between these paradigms highlights the enduring relevance of Knuth's insights. While &lt;strong&gt;literate programming has never taken off&lt;/strong&gt; and remains &lt;strong&gt;a curiosity, hidden in a dark corner, and ignored&lt;/strong&gt; , its core principles—exposition, human readability, and natural language integration—find new expression through AI-mediated development.&lt;/p&gt;

&lt;p&gt;This convergence suggests that the future of programming may naturally evolve toward more literate practices, not through adoption of Knuth's specific methodology, but through tools that inherently prioritize human understanding and explanation. The dialogue between human and AI in code generation creates a new form of literate programming—one that achieves exposition and accessibility through conversation rather than conscious literary craft.&lt;/p&gt;

&lt;p&gt;In this light, AI code generation represents not a departure from programming tradition, but an unexpected fulfillment of literate programming's vision: code that speaks to humans in human terms, embedded within explanatory contexts that make programming more accessible and understandable. The essayist programmer that Knuth envisioned may have found expression not in human literary discipline, but in the conversational nature of artificial intelligence itself.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Idea conceived by Devin Weaver. Content generated by &lt;a href="https://kagi.com/assistant" rel="noopener noreferrer"&gt;The Assistant — kagi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>philosophy</category>
      <category>ai</category>
    </item>
    <item>
      <title>Why Ember.js is designed for Enterprise Software Development</title>
      <dc:creator>Devin Weaver</dc:creator>
      <pubDate>Mon, 25 Sep 2023 17:46:00 +0000</pubDate>
      <link>https://dev.to/sukima/why-emberjs-is-designed-for-enterprise-software-development-6le</link>
      <guid>https://dev.to/sukima/why-emberjs-is-designed-for-enterprise-software-development-6le</guid>
      <description>&lt;p&gt;By: &lt;a href="https://tritarget.org/#Why%20Ember.js%20for%20Enterprise%20Software%20Development"&gt;Devin Weaver&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Enterprises require robust and reliable software solutions to stay competitive. The choice of a development framework plays a pivotal role in determining the success of these software projects. Among the various options available, Ember.js stands out as a powerful and comprehensive framework that is ideally suited for enterprise-level software development. This essay aims to elucidate why Ember.js is a more appropriate choice than its competitors for developing enterprise software.&lt;/p&gt;

&lt;h2&gt;
  
  
  I. Strong Conventions
&lt;/h2&gt;

&lt;p&gt;Ember.js is well known for its strong conventions, which provide a clear and structured path for developers to follow. In the enterprise world, where collaboration and scalability are paramount, these conventions offer several benefits. They ensure that team members understand and adhere to best practices consistently, reducing the likelihood of code discrepancies and fostering maintainability. Competing frameworks often lack such rigor, leading to a more chaotic development process and making Ember.js a superior choice for enterprise projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  II. Stability and Long-Term Support
&lt;/h2&gt;

&lt;p&gt;Enterprise software needs to be reliable and stable, as it forms the backbone of critical business operations. Ember.js is distinguished by its commitment to stability and long-term support. The Ember project follows a strict release cycle with LTS (Long-Term Support) versions, guaranteeing that businesses can rely on a consistent and dependable framework for years. In contrast, many competitors are known for frequent breaking changes and a lack of commitment to backward compatibility, causing headaches for enterprise developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  III. Extensive Ecosystem
&lt;/h2&gt;

&lt;p&gt;Ember.js boasts a rich ecosystem of add-ons, libraries, and tools, which significantly accelerates the development process. Enterprises can leverage these resources to expedite the creation of complex features, reducing time-to-market. Moreover, Ember's convention over configuration (CoC) approach ensures that many common application level problems have built-in solutions, saving developers from reinventing the wheel. This extensive ecosystem fosters productivity and sets Ember.js apart from competitors that may require extensive custom solutions for similar functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  IV. Robust Testing Capabilities
&lt;/h2&gt;

&lt;p&gt;Quality assurance is critical for enterprise software, and Ember.js excels in this aspect. The framework provides a built-in testing suite, methodologies for CI pipelines, and a slew of supporting add-ons (like ember-exam), which all help to streamline the testing process. This ensures that software remains reliable and bug-free even as it evolves. Competing frameworks often lack such integrated testing tools, requiring additional third-party solutions, which can be cumbersome and less effective for enterprise-scale projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  V. Community
&lt;/h2&gt;

&lt;p&gt;The Ember community has been consistent in their dedication to supporting enterprise-scale solutions. They focus efforts into accessibility, testing, conventions, and support for third-party integrations. Not only are they welcoming to new developers but are also supportive of experienced developers. They hold to inclusive values and provide public transparency to their future plans by means of a defined RFC process. Many of those in the community continue to show a dedication and enthusiasm for helping others.&lt;/p&gt;

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

&lt;p&gt;In the realm of enterprise software development, selecting the right framework is a critical decision that can impact the success of a project and the future of a business. Ember.js emerges as the superior choice among competitors due to its strong conventions, stability, extensive ecosystem, robust testing capabilities, and support for modern web development trends. Its commitment to providing a reliable and efficient platform makes it the optimal choice for enterprises looking to develop scalable, maintainable, and feature-rich software solutions. Ember.js is not just a framework; it is a powerful ally in the pursuit of enterprise excellence.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ember</category>
    </item>
    <item>
      <title>State Machines work for logic too</title>
      <dc:creator>Devin Weaver</dc:creator>
      <pubDate>Sun, 09 Aug 2020 18:33:35 +0000</pubDate>
      <link>https://dev.to/sukima/state-machines-work-for-logic-too-494p</link>
      <guid>https://dev.to/sukima/state-machines-work-for-logic-too-494p</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://tritarget.org/#State%20Machines%20work%20for%20logic%20too"&gt;Original Article&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The other day I found myself in a very peculiar situation. I was writing a very specific &lt;a href="https://en.wikipedia.org/wiki/Bookmarklet"&gt;bookmarklet&lt;/a&gt; where the code I was writing was intentionally terse. It also meant I had to do everything in browser only JavaScript. No CDNs or NPM modules or babel compilation. Luckily the target was the most up-to-date modern browsers (Chrome, FireFox).&lt;/p&gt;

&lt;p&gt;In this template I found that I needed to construct a bunch of URLs based on changing data provided to the program. In any normal situation I would use some kind of URL builder library. Something very much like &lt;a href="https://medialize.github.io/URI.js/uri-template.html"&gt;URI Template&lt;/a&gt;. This would allow me to define several templates and then run them with the changing data to get expanded URLs for the program.&lt;/p&gt;

&lt;p&gt;I looked and found most all implementations of &lt;a href="https://tools.ietf.org/html/rfc6570"&gt;RFC 6570&lt;/a&gt; I found were huge. And they all implemented many features of the RFC I knew I didn't need to use. Since I was constrained to a small source file and no libs I felt copy pasting was not a good option.&lt;/p&gt;

&lt;p&gt;My adventure began with me attempting to write my own mini implementation of &lt;a href="https://tools.ietf.org/html/rfc6570"&gt;RFC 6570&lt;/a&gt; cherry-picking the features I knew I wanted and ignoring the rest of the spec. Specifically I wanted to support simple replacement, path and dot prefixes, query params, and optionally fragments and multiple variables (comma separated).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;makeUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://tritarget.org{/path}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;makeUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://foo{.domain}.org{/path}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;makeUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://tritarget.org{/path}{?foo,bar,baz}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I thought about RegExp and knew that would be &lt;a href="https://xkcd.com/1171/"&gt;too many problems&lt;/a&gt;. Then I thought JavaScript comes with its own &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URL"&gt;URL building API&lt;/a&gt; Unfortunately that API was more focused on parsing then it was building and my initial attempts to make a bunch of mutations to the object really made the code ugly and had difficulty capturing all the edge cases. I finally settled on making a mini template parser and URL compiler. I know, definitely a &lt;em&gt;bad idea&lt;/em&gt; but it's my little world &lt;strong&gt;YOLO&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;When I've experimented with making my own micro parsers in the past I had a lot of boolean switches to track the states while I scanned a string. I also had to mange building up the resulting AST manually. With my simple syntax I wanted I knew that instead of parsing things into an AST like normal I could cut out the middle man and simply make a list of OP Codes. The compiler would be liner and non-contextual.&lt;/p&gt;

&lt;p&gt;It also meant that since the parser would tokenize to a flat list of OP Codes I could get away with using a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*"&gt;generator function&lt;/a&gt; and a &lt;a href="https://en.wikipedia.org/wiki/Finite-state_machine"&gt;finite state machine&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Parser
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8eUhZeWP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0pvoyamczmhe4pjzh7iy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8eUhZeWP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0pvoyamczmhe4pjzh7iy.png" alt="UML State Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea behind this is that each character can produce an event that the state machine can react to. For example say we define the following character map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EOL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EOL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TOKENS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;EOL&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;END_INPUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPEN_BRACE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CLOSE_BRACE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPERATION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPERATION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPERATION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPERATION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPERATION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPERATION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SPLIT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EOL&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;eventName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TOKENS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TEXT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Walking through the example &lt;code&gt;foo.com{/bar,baz}&lt;/code&gt; would mean we would kick off a series of events: &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;OPERATION&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;OPEN_BRACE&lt;/code&gt;, &lt;code&gt;OPERATION&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;SPLIT&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;CLOSE_BRACE&lt;/code&gt;, &lt;code&gt;END_INPUT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Looking at the UML State Diagram above we can follow those events and see how they would affect a running state machine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NJ9d7Lwg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8qwj2oxeeto7phrmfau4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NJ9d7Lwg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8qwj2oxeeto7phrmfau4.png" alt="Example Sequence"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And finally if we take into account the actions defined in the UML State Diagram we can see the OP Codes being built.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;append&lt;/code&gt; — adds the character into the OP Code's &lt;code&gt;value&lt;/code&gt; property&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;flush&lt;/code&gt; — yield (or push onto an array) the current OP Code and prepare a new one&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;assignModifier&lt;/code&gt; — set the OP Code's &lt;code&gt;modifier&lt;/code&gt; property&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setTextOpCode&lt;/code&gt; — set the OP Code's &lt;code&gt;code&lt;/code&gt; property to &lt;code&gt;TEXT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setReplaceOpCode&lt;/code&gt; — set the OP Code's &lt;code&gt;code&lt;/code&gt; property to &lt;code&gt;REPLACE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setModifiedReplaceOpCode&lt;/code&gt; — set the OP Code's &lt;code&gt;code&lt;/code&gt; property to &lt;code&gt;RAWREPLACE&lt;/code&gt;, &lt;code&gt;PREFIXREPLACE&lt;/code&gt;, or &lt;code&gt;QPREPLACE&lt;/code&gt; depending on the OP Code's &lt;code&gt;modifier&lt;/code&gt; value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setParseError&lt;/code&gt; — set the current error message to something specific about the syntax error&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setEOLError&lt;/code&gt; — set the current error message to something specific about a premature end to the input&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;throwError&lt;/code&gt; — throw an error with the stored error message
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TEXT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PREFIXREPLACE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PREFIXREPLACE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;baz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TEXT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&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;
  
  
  Modeling the machine
&lt;/h2&gt;

&lt;p&gt;Using the UML State Diagram we can model this in object notation like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lexer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;states&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setTextOpCode&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;append&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;OPERATION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;append&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;SPLIT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;append&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;OPEN_BRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;replacement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flush&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;CLOSE_BRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;END_INPUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flush&lt;/span&gt;&lt;span class="dl"&gt;'&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="na"&gt;replacement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setReplaceOpCode&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;variable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;append&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;OPERATION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;operation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assignModifier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;SPLIT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;OPEN_BRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;CLOSE_BRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;END_INPUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setEOLError&lt;/span&gt;&lt;span class="dl"&gt;'&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="na"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setModifiedReplaceOpCode&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;variable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;append&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;OPERATION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;SPLIT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;OPEN_BRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;CLOSE_BRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;END_INPUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setEOLError&lt;/span&gt;&lt;span class="dl"&gt;'&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="na"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;append&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;OPERATION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;SPLIT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flush&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;OPEN_BRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setParseError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;CLOSE_BRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flush&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;END_INPUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setEOLError&lt;/span&gt;&lt;span class="dl"&gt;'&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="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;final&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;final&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;throwError&lt;/span&gt;&lt;span class="dl"&gt;'&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 format looks similar to &lt;a href="https://xstate.js.org"&gt;XState&lt;/a&gt; notation but because I wrote this for a bookmarklet I wanted something much smaller. I really only needed events and actions and so was able to implement this with minimal vanilla code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;opCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TEXT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EOL&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;eventName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TOKENS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TEXT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;states&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;states&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="nx"&gt;perform&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;named&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;described&lt;/span&gt; &lt;span class="nx"&gt;above&lt;/span&gt; &lt;span class="err"&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;We set up some scoped state, our work in progress OP Code object and track the character position (for error messages). The beauty is that the act of transitioning between states in the state machine is just a matter of sending a mapped event for each character as it scans the string. How those events are reacted to depends on the current state the machine is in. The logic involved practically writes itself.&lt;/p&gt;

&lt;p&gt;Feel free to &lt;a href="https://tritarget.org/#examples%2Fstate-machines-work-for-logic-too"&gt;view the full source for this utility&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>state</category>
      <category>statechart</category>
      <category>statemachine</category>
    </item>
  </channel>
</rss>
