<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="72567" data-post-id="72567">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I have added support for state. Here is how to implement a simple XML parser with it:</p>
<p><a href="https://github.com/plataformatec/nimble_parsec/blob/master/examples/simple_xml.exs" class="onebox" target="_blank" rel="noopener nofollow">https://github.com/plataformatec/nimble_parsec/blob/master/examples/simple_xml.exs</a></p>
<aside class="quote no-group" data-username="OvermindDL1" data-post="19" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>Hmm, how might that look?  I use a lot of bases at times and what base to use is calculated based on what was previously parsed (passed in via state) rather than being hardcoded variants.</p>
</blockquote>
</aside>
<p>We can support two new primitives here. One is <code>context_choice</code> which allows you to choose which branch to process based on what is under a given key in the context.</p>
<p>The other one is to allow context keys to be given to <code>times</code>. So you can say “this integer min/max/length will be given by certain key in context”.</p>
<p>Both should be straight-forward to add and are generalizations of primitives we currently have in place. I don’t plan to work on them now but if someone is working on a parser that needs it, please open up an issue with the use case, code examples and rationale and we can find out the best way to handle it.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72567" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-72567" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72567"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #21"></div>
  </section>
</div>
    <div class="postbit" id="72568" data-post-id="72568">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Eiji" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Eiji/120/36743_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Eiji
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><a class="mention" href="/u/josevalim" rel="nofollow">@josevalim</a>: How about add optional <code>opts</code>?</p>
<p>I prefer to write: <code>rule(term, ignore: true, optional: true)</code> instead of <code>optional(ignore(rule(term)))</code>.</p>
<p>For real world example simply compare my version with its original form from <a href="https://github.com/plataformatec/nimble_parsec/blob/v0.1.0/README.md" rel="noopener nofollow ugc">README.md</a>:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyParser do
  import NimbleParsec

  date =
    integer(4)
    |&gt; literal("-", ignore: true)
    |&gt; integer(2)
    |&gt; literal("-", ignore: true)
    |&gt; integer(2)

  time =
    integer(2)
    |&gt; literal(":", ignore: true)
    |&gt; integer(2)
    |&gt; literal(":", ignore: true)
    |&gt; integer(2)
    |&gt; literal("Z", optional: true)

  defparsec :datetime, date |&gt; literal("T", ignore: true) |&gt; concat(time), debug: true
end
</code></pre>
<p>I know that’s extra work for you, but at least for me code will look much cleaner.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72568" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-72568" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72568"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #22"></div>
  </section>
</div>
    <div class="postbit" id="72583" data-post-id="72583">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mischov" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mischov/120/2489_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mischov
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule NimbleParsec do
  @moduledoc "README.md"
             |&gt; File.read!()
             |&gt; String.split("&lt;!-- MDOC !--&gt;")
             |&gt; Enum.fetch!(1)
</code></pre>
<p>Where has this been my whole life?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72583" data-batch-url="/posts/batch_likers">
                        7
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-72583" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72583"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #23"></div>
  </section>
</div>
    <div class="postbit" id="72599" data-post-id="72599">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tmbb" data-post="20" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>How would you maintain an indentation stack with only local state? You need all indent levels lower than the previous one. Would you push the stack into local state every time?</p>
</blockquote>
</aside>
<p>Yep, that’s the traditional way in the original Spirit.  Though it’s syntax makes it shorter than the same in Elixir.</p>
<aside class="quote no-group" data-username="tmbb" data-post="21" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Your problem here is not a lack of bases, it’s the lack of a state system xD</p>
</blockquote>
</aside>
<p>And the ability to pass state as arguments to the parsers…  ^.^;</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>I have added support for state. Here is how to implement a simple XML parser with it:</p>
</blockquote>
</aside>
<p>A few issues:</p>
<p>First, the length, all of this in Nimble:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  text =
    ascii_char(not: ?&lt;)
    |&gt; repeat(ascii_char(not: ?&lt;))
    |&gt; reduce({List, :to_string, []})
</code></pre>
<p>Is this in ExSpirit:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  defrule text( chars(-?&lt;) )
</code></pre>
<p>And this in Nimble:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  letter = ascii_char([?a..?z, ?A..?Z])
  tag = letter |&gt; repeat(letter) |&gt; reduce({List, :to_string, []})
</code></pre>
<p>Is this in ExSpirit:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  defrule tag_name( chars([?a..?z, ?A..?Z, ?0..?9, ?_, ?-]) )
</code></pre>
<p>And this in Nimble:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  opening_tag =
    ignore(string("&lt;"))
    |&gt; concat(tag)
    |&gt; ignore(string("&gt;"))

  closing_tag =
    ignore(string("&lt;/"))
    |&gt; concat(tag)
    |&gt; ignore(string("&gt;"))

  defparsec :__xml__,
            opening_tag
            |&gt; traverse(:store_tag_in_context)
            |&gt; repeat_until(
              choice([
                parsec(:__xml__),
                text
              ]),
              [string("&lt;/")]
            )
            |&gt; wrap()
            |&gt; concat(closing_tag)
            |&gt; traverse(:check_close_tag_and_emit_tag)

  defp store_tag_in_context([tag], %{tags: tags} = context, _line, _offset) do
    {[tag], %{context | tags: [tag | tags]}}
  end

  defp check_close_tag_and_emit_tag([closing, [opening | contents]], context, _line, _offset) do
    if closing == opening do
      context = update_in(context.tags, &amp;tl/1)

      element =
        case contents do
          [text] -&gt; {String.to_atom(opening), [], text}
          nodes -&gt; {String.to_atom(opening), [], nodes}
        end

      {[element], context}
    else
      {:error, "closing tag #{inspect(closing)} did not match opening tag #{inspect(opening)}"}
    end
  end
end
</code></pre>
<p>Is just this in ExSpirit:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  defrule tag(
    lit(?&lt;) |&gt; tag_name() |&gt; put_state(:tagname, :result) |&gt; lit(?&gt;) |&gt; expect(seq([
      get_state_into(:tagname, tag(&amp;1, repeat(node_()))),
      lit("&lt;/"), get_state_into(:tagname, lit(&amp;1)), lit(?&gt;)
    ]))
  )

  defrule node_(
    alt([
      tag(),
      text(),
    ])
  )
</code></pre>
<p>In addition, though this is an example, it was demonstrating features that, though easy to bypass in this example (you can do it in ExSpirit the same way you did in Nimble), is not bypassable in many other cases.  Specifically this line in ExSpirit:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">get_state_into(:tagname, lit(&amp;1))
</code></pre>
<p>How would this be done in Nimble, your example does not demonstrate this thus your example is not a faithful recreation.  This specific expression, though in this case can be done by comparing ‘later’, this shows that you can parameterize parsers based on prior parsed data, and this is what I’ve set to see how you could do it in Nimble as this is an absolutely mandatory capability that a lot of languages need to parse else the parser can become infinitely large in order to handle all possible variants.</p>
<p>Like to make it slightly more complex (though still not infinitely configurable as some languages get), how would you parse the xml example of <code>&lt;foo&gt;&lt;bar&gt;one&lt;baz&gt;two&lt;/foo&gt;</code> as if it were <code>&lt;foo&gt;&lt;bar&gt;one&lt;baz&gt;two&lt;/baz&gt;&lt;/bar&gt;&lt;/foo&gt;</code>?  In ExSpirit that would involve changing this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">      lit("&lt;/"), get_state_into(:tagname, lit(&amp;1)), lit(?&gt;)
</code></pre>
<p>To be something like (although format it better of course):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">      alt([lit("&lt;/"), get_state_into(:tagname, lit(&amp;1)), lit(?&gt;), success()])
</code></pre>
<p>And then you get nice auto-closing tags when left open, and yet it still fails if there is a mismatched closing tag.</p>
<p>Also, these two cases in your parse call:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">      {:ok, _, rest, %{tags: []}, line, offset} -&gt;
        {:error, "document continued after last closing tag", rest, line, offset}

      {:ok, _, rest, %{tags: [tag | _]}, line, offset} -&gt;
        {:error, "tag #{inspect(tag)} was not closed", rest, line, offset}
</code></pre>
<p>How would you enforce those as part of the grammar?  In ExSpirit for the first you just add an <code>eoi()</code> (and an alternate <code>fail("reason")</code> if you want a customized message) at the end, and for the second, well, that’s <em>already</em> an error in ExSpirit, like <em>why</em> does that parse at all in Nimble as it really absolutely should <em>not</em> (not as big of an issue for something trivial like SimpleXML but a larger issue when you have complex grammars that need to be self-terminating based on state information).</p>
<p>For comparison, here’s how you make SimpleAST in the original Spirit:</p>
<pre data-code-wrap="cpp"><code class="lang-cpp">        text = lexeme[+(char_ - '&lt;')        [_val += _1]];
        node = (xml | text)                 [_val = _1];

        start_tag =
                '&lt;'
            &gt;&gt;  !lit('/')
            &gt;&gt;  lexeme[+(char_ - '&gt;')       [_val += _1]]
            &gt;&gt;  '&gt;'
        ;

        end_tag =
                "&lt;/"
            &gt;&gt;  string(_r1)
            &gt;&gt;  '&gt;'
        ;

        xml =
                start_tag                   [at_c&lt;0&gt;(_val) = _1]
            &gt;&gt;  *node                       [push_back(at_c&lt;1&gt;(_val), _1)]
            &gt;&gt;  end_tag(at_c&lt;0&gt;(_val))
        ;
</code></pre>
<p>And yes, that is entire pure and valid C++, no preprocessor or anything of the sort needed, consequently <a class="mention" href="/u/tmbb" rel="nofollow">@tmbb</a> you see how the local state it uses has to be passed up and down through the parsers?  And yes, it will generate code that is at least on par but usually <strong>better</strong> than hand-rolling your own parser in any language, even assembly, without <em>substantial</em> work (and even with that work you will only get on par with Spirit in speed, literally if you find any time where spirit is slower than anything else it can optimize for that and fix it, that is part of it’s design, which I did not follow in ExSpirit for a quick whipping up, though the expression version would be better at it).</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>We can support two new primitives here. One is context_choice which allows you to choose which branch to process based on what is under a given key in the context.</p>
</blockquote>
</aside>
<p>That is not as useful though, need to pass state into the parser arguments to be able to parse many language grammars, else you end up with infinite parser variations required (or falling back to multiple passes and more code and mis-matched errors with the parsers and all that).</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>The other one is to allow context keys to be given to times. So you can say “this integer min/max/length will be given by certain key in context”.</p>
</blockquote>
</aside>
<p>It would not just be <code>times</code>, you’d have to allow passing state as an argument to an any parser to really allow it in full (which the original spirit allows for and ExSpirit allows for in ‘most’ cases, though not all…)</p>
<aside class="quote no-group" data-username="Eiji" data-post="23" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/48/36743_2.png" class="avatar"> Eiji:</div>
<blockquote>
<p><a class="mention" href="/u/josevalim" rel="nofollow">@josevalim</a>: How about add optional opts?</p>
<p>I prefer to write: rule(term, ignore: true, optional: true) instead of optional(ignore(rule(term))).</p>
</blockquote>
</aside>
<p>Eh, it might be nicer but generalizing that to everything everyone might possibly make sounds a bit irritating since in his design they are all just functions and not a built expression tree like the C++ spirit is).</p>
<aside class="quote no-group" data-username="mischov" data-post="24" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mischov/48/2489_2.png" class="avatar"> mischov:</div>
<blockquote>
<p>Where has this been my whole life?</p>
</blockquote>
</aside>
<p>Lol!  Just module attributes so you can do whatever.  ^.^</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72599" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-72599" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72599"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #24"></div>
  </section>
</div>
    <div class="postbit" id="72600" data-post-id="72600">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Also another thing, how do you define a skip parser in Nimble?  Or do you have to add the skip parser to every-single-possible-rule-and-skippable-location-which-is-utterly-<em>ginormous</em>-in-count?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72600" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-72600" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72600"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #25"></div>
  </section>
</div>
    <div class="postbit" id="72602" data-post-id="72602">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="Eiji" data-post="23" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/48/36743_2.png" class="avatar"> Eiji:</div>
<blockquote>
<p><a class="mention" href="/u/josevalim" rel="nofollow">@josevalim</a>: How about add optional opts?</p>
</blockquote>
</aside>
<p>Not planned. You can easily wrap it though!</p>
<aside class="quote no-group quote-modified" data-username="OvermindDL1" data-post="25" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>And this in Nimble … Is this in ExSpirit</p>
</blockquote>
</aside>
<p>As the name of the library says, my plan is to stay nimble and not focus in providing high level constructs. <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"> The fact it allows runtime composition and the focus on primitives mean you should be able to build <code>chars</code> and <code>text</code> yourself, like I did. Put those in a module as regular functions and you will be able to use them as if they were part of nimble.</p>
<aside class="quote no-group" data-username="OvermindDL1" data-post="25" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>How would this be done in Nimble, your example does not demonstrate this thus your example is not a faithful recreation.</p>
</blockquote>
</aside>
<p>To clarify, I was not trying to recreate ex_spirit parser here. I haven’t checked its implementation. In any case, what you proposed can be implemented with <code>traverse</code>, which receives the context and can return the accumulator and a possibly updated context.</p>
<aside class="quote no-group" data-username="OvermindDL1" data-post="25" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>How would you enforce those as part of the grammar?</p>
</blockquote>
</aside>
<p>It can be done by using <code>traverse</code> as well but it should be easy to add a lookahead construct too.</p>
<aside class="quote no-group" data-username="OvermindDL1" data-post="25" data-topic="12860">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>you’d have to allow passing state as an argument to an any parser to really allow it in full</p>
</blockquote>
</aside>
<p>I don’t think this will ever be possible. All combinators are compiled down to function clauses. A combinator cannot be used with state information unless the underlying combinator has been taught to read from state. Which goes back to the point I want to rather focus on the small set of primitives, making them powerful enough to build everything else on top of it.</p>
<p>I mentioned this in the issues tracker but getting a traditional parser combinator and translating it to <code>NimbleParsec</code> is not going to work. I am pretty sure the C++ implementation is faster and more flexible than <code>NimbleParsec</code> but for nimble we need to stay within the rules of the Erlang VM. That’s why I am more interested in particular examples we cannot handle than a particular feature, because when all is said and done, the feature may need to be implemented in completely different way in nimble.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72602" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-72602" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72602"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #26"></div>
  </section>
</div>
    <div class="postbit" id="72617" data-post-id="72617">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>v0.2.0 is out with lookahead, user contexts, custom errors, byte offsets and  <code>ascii_string/3</code> and <code>utf8_string/3</code>. See the CHANGELOG:</p>
<p><a href="https://github.com/plataformatec/nimble_parsec/blob/master/CHANGELOG.md" class="onebox" target="_blank" rel="noopener nofollow">https://github.com/plataformatec/nimble_parsec/blob/master/CHANGELOG.md</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72617" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-72617" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72617"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #27"></div>
  </section>
</div>
    <div class="postbit" id="72621" data-post-id="72621">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Cool. I’ll start rewriting my Elixir lexer directly in <code>nimble_parsec</code>. Then, when I see anything worth refactoring into its own module, I’ll start porting Makeup to see if it can be based on <code>nimble_parsec</code> (Makeup is basically a library of useful combinators that can be reused between languages + some plumbing so that the entire chain from lexer to formatter works.</p>
<p>This might take some time, especially because there isn’t a 1-to-1 mapping between ExSpirit combinators and NimbleParsec combinators.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72621" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-72621" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72621"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #28"></div>
  </section>
</div>
    <div class="postbit" id="72628" data-post-id="72628">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I will be very glad to help if you have any questions or you need help translating some constructs!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72628" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-72628" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72628"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #29"></div>
  </section>
</div>
    <div class="postbit" id="72629" data-post-id="72629">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Also, maybe a good suggestion is to start with the smaller language you currently handle. So we can directly compare compile and execution times.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="72629" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nimbleparsec-a-simple-and-fast-parser-combinator-for-elixir/12860/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-72629" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="72629"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #30"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/12860/load_more?page=4">Load more posts (111 remaining)</a>
</div></template></turbo-stream>