<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="/rss.xsl"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Orn · Pablo Sabater</title><link>https://pablosabater.dev/projects/orn/</link><description>Pablo Sabater writes about what he finds interesting: compilers, low-level tools, open source and life.</description><language>en</language><managingEditor>pablo@pablosabater.dev (Pablo Sabater)</managingEditor><lastBuildDate>Wed, 07 Oct 2026 16:49:56 +0100</lastBuildDate><atom:link href="https://pablosabater.dev/projects/orn/index.xml" rel="self" type="application/rss+xml"/><item><title>How to Build a Pratt Parser</title><link>https://pablosabater.dev/posts/how-to-build-a-pratt-parser/</link><pubDate>Wed, 07 Oct 2026 16:49:56 +0100</pubDate><guid>https://pablosabater.dev/posts/how-to-build-a-pratt-parser/</guid><description>&lt;p&gt;How does a program know that &lt;code&gt;2 + 3 * 4&lt;/code&gt; is &lt;code&gt;14&lt;/code&gt; and not &lt;code&gt;20&lt;/code&gt;? Before it can
compute anything, it has to read the text and turn it into a tree that says
which operation goes first. That is the job of a &lt;mark&gt;parser&lt;/mark&gt;.&lt;/p&gt;
&lt;p&gt;Hi! In this post I&amp;rsquo;m going to talk about one kind of parser, the &lt;mark&gt;Pratt
parser&lt;/mark&gt;&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;a.k.a. top-down operator precedence parser&lt;/span&gt;&lt;/span&gt;, and
how to build one in C. I learned it to write the expression parser for
&lt;a href="https://pablosabater.dev/projects/orn/" data-preview-kind="Project" data-preview-title="Orn" data-preview-desc="A range-based systems programming language. I&amp;#39;m not building it to be useful, but to explore an idea."&gt;Orn&lt;/a&gt;&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;My range-based systems programming language,
still very much a work in progress.&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The idea comes from a 1973 paper by Vaughan Pratt&lt;sup class="cite"&gt;&lt;a href="#ref-3" id="cite-3-2"
 data-preview-kind="Vaughan R. Pratt · 1973"
 data-preview-title="Top Down Operator Precedence"
 data-preview-desc="The original paper, POPL 1973."&gt;[3]&lt;/a&gt;&lt;/sup&gt;, but I
learned it through Alex Kladov&amp;rsquo;s post&lt;sup class="cite"&gt;&lt;a href="#ref-1" id="cite-1-3"
 data-preview-kind="Alex Kladov · 2020"
 data-preview-title="Simple but Powerful Pratt Parsing"
 data-preview-desc="matklad.github.io"&gt;[1]&lt;/a&gt;&lt;/sup&gt;, Bob Nystrom&amp;rsquo;s
post&lt;sup class="cite"&gt;&lt;a href="#ref-6" id="cite-6-4"
 data-preview-kind="Bob Nystrom · 2011"
 data-preview-title="Pratt Parsers: Expression Parsing Made Easy"
 data-preview-desc="A Pratt parser in Java, built around one parselet class per token."&gt;[6]&lt;/a&gt;&lt;/sup&gt; and this video&lt;sup class="cite"&gt;&lt;a href="#ref-2" id="cite-2-5"
 data-preview-kind="Core Dumped · 2025"
 data-preview-title="This Simple Algorithm Powers Real Interpreters: Pratt Parsing"
 data-preview-desc="youtube.com"&gt;[2]&lt;/a&gt;&lt;/sup&gt;. Kladov&amp;rsquo;s post
is still the one I would recommend. This one takes a different
path: it starts from the grammar you see in a Compilers course, shows why it
gets painful, and builds the parser in C one step at a time, tracing every call.&lt;/p&gt;
&lt;p&gt;I had already heard &lt;strong&gt;a lot&lt;/strong&gt; about Pratt parsing from other developers talking
about their parsers, and it sounded really cool: a single function that parses
every expression, driven only by operator precedence. Last year I took Compilers
at university, but we were only taught LL and LR
parsing&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;Two families of parsers. LL parsers work top-down: they start
from the whole expression and split it into parts, usually with one function
per grammar rule (recursive descent). LR parsers work bottom-up: they join
tokens into bigger pieces, and are usually generated by tools like yacc (SLR,
LR(1) and LALR are variants of them).&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;So I knew the name, but not how it actually worked. This post is what I learned building one.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You don&amp;rsquo;t need to know any parsing theory to follow along: every term is
explained when it shows up.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 id="the-problem-with-grammars"&gt;The problem with grammars&lt;a class="anchor" href="#the-problem-with-grammars" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;mark&gt;grammar&lt;/mark&gt; describes what a valid expression looks like. It is usually
written in BNF&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;Backus–Naur form. &lt;code&gt;expr = expr '+' expr&lt;/code&gt; reads as “an
expression can be an expression, then a &lt;code&gt;+&lt;/code&gt;, then another expression”, and &lt;code&gt;|&lt;/code&gt;
separates the alternatives. Strictly, the notation in this post is closer to
EBNF (Extended BNF): classic BNF writes &lt;code&gt;&amp;lt;expr&amp;gt; ::= &amp;lt;expr&amp;gt; &amp;quot;+&amp;quot; &amp;lt;expr&amp;gt;&lt;/code&gt;.&lt;/span&gt;&lt;/span&gt;.
You would typically write the grammar for a small language that can only add,
subtract and multiply numbers and variables&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;A variable is a terminal,
imagine it as a single character, like &lt;code&gt;'x'&lt;/code&gt;. It cannot be expanded.&lt;/span&gt;&lt;/span&gt; like this:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bnf" data-lang="bnf"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;expr = expr &amp;#39;+&amp;#39; expr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | expr &amp;#39;-&amp;#39; expr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | expr &amp;#39;*&amp;#39; expr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | factor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;factor = number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | variable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;It is easy to read, but it is ambiguous: &lt;code&gt;1 + 2 * 3&lt;/code&gt; can be parsed as:&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt; * + 
 / \ / \ 
 + 3 or 1 *
 / \ / \ 
 1 2 2 3

(1 + 2) * 3 1 + (2 * 3)&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;To fix it, we need one rule per precedence
level, from the lowest to the highest:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bnf" data-lang="bnf"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;expr = term
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | expr &amp;#39;+&amp;#39; term
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | expr &amp;#39;-&amp;#39; term
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;term = factor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | term &amp;#39;*&amp;#39; factor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;factor = number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | variable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;If we also had division, it would go in &lt;code&gt;term&lt;/code&gt;:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bnf" data-lang="bnf"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;term = factor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | term &amp;#39;*&amp;#39; factor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | term &amp;#39;/&amp;#39; factor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;Both &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt; have the same precedence, so just as &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;-&lt;/code&gt; are together,
&lt;code&gt;/&lt;/code&gt; will go with &lt;code&gt;*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But let&amp;rsquo;s keep division out.&lt;/p&gt;
&lt;p&gt;The grammar is now unambiguous, but it has lost its simplicity.
And it is left-recursive (&lt;code&gt;expr = expr '+' term&lt;/code&gt;), so an LL parser,
like the recursive descent one I use for &lt;a href="https://pablosabater.dev/projects/orn/" data-preview-kind="Project" data-preview-title="Orn" data-preview-desc="A range-based systems programming language. I&amp;#39;m not building it to be useful, but to explore an idea."&gt;Orn&lt;/a&gt;, can&amp;rsquo;t use
it as it is: to parse &lt;code&gt;expr&lt;/code&gt; it would first call &lt;code&gt;expr&lt;/code&gt;, forever.
To make it LL, the left recursion has to be removed&lt;sup class="cite"&gt;&lt;a href="#ref-4" id="cite-4-9"
 data-preview-kind="Alfred V. Aho, Monica S. Lam, Ravi Sethi, Jeffrey D. Ullman · 2006"
 data-preview-title="Compilers: Principles, Techniques, and Tools (2nd edition)"
 data-preview-desc="Chapter 4 covers the expression grammar and left recursion removal."&gt;[4]&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bnf" data-lang="bnf"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;expr = term expr&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;expr&amp;#39; = &amp;#39;+&amp;#39; term expr&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | &amp;#39;-&amp;#39; term expr&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | ε
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;term = factor term&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;term&amp;#39; = &amp;#39;*&amp;#39; factor term&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | ε
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;factor = number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | variable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;It works, but now there are two extra rules, an &lt;code&gt;ε&lt;/code&gt;&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;&lt;code&gt;ε&lt;/code&gt; means
“nothing”: that alternative matches without reading any token.&lt;/span&gt;&lt;/span&gt;, and the original
&lt;code&gt;expr '+' expr&lt;/code&gt; is hard to recognize.&lt;/p&gt;
&lt;p&gt;EBNF makes it a bit nicer. Its &lt;code&gt;{ ... }&lt;/code&gt; means “repeat zero or more times”, so
the left recursion can be written as a repetition:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ebnf" data-lang="ebnf"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;expr &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;term &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;term &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;term &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="k"&gt;factor &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;*&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;factor &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;factor &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="k"&gt;number &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;variable&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;No &lt;code&gt;ε&lt;/code&gt; and no extra rules, and each &lt;code&gt;{ }&lt;/code&gt; becomes a &lt;code&gt;while&lt;/code&gt; loop in a
recursive descent parser. But there is still one rule per precedence level:
ten levels of operators are ten rules, and ten functions calling each other.&lt;/p&gt;
&lt;p&gt;Pratt parsing takes a different path: it keeps the short, ambiguous grammar
and moves precedence out of it, into a table.&lt;/p&gt;
&lt;h2 id="parsing-a-real-expression-simulating-the-algorithm"&gt;Parsing a real expression, simulating the algorithm&lt;a class="anchor" href="#parsing-a-real-expression-simulating-the-algorithm" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Take this expression:&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;a + b * c - d&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;The parser reads sequentially, from left to right. The first token is
&lt;code&gt;a&lt;/code&gt;, and right after it comes &lt;code&gt;+&lt;/code&gt;. So we know that &lt;code&gt;a&lt;/code&gt; will be added to
&lt;u&gt;&lt;em&gt;something&lt;/em&gt;&lt;/u&gt;.&lt;/p&gt;
&lt;h3 id="what-is-that-something"&gt;What is that &lt;em&gt;something&lt;/em&gt;?&lt;a class="anchor" href="#what-is-that-something" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We keep reading and the next token is &lt;code&gt;b&lt;/code&gt;. If we stopped here, we would think
the expression is &lt;code&gt;a + b&lt;/code&gt;. But if we peek one token further, we see &lt;code&gt;*&lt;/code&gt;:&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;a + b * c - d
 ^ ^
 | +-- next operator: *
 +---- current operand: b&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;Now &lt;code&gt;b&lt;/code&gt; is caught between two operators, &lt;code&gt;+&lt;/code&gt; on its left and &lt;code&gt;*&lt;/code&gt; on its right,
and both want it. Since &lt;code&gt;*&lt;/code&gt; has higher precedence, &lt;code&gt;b&lt;/code&gt; belongs to &lt;code&gt;*&lt;/code&gt;, and the
&lt;em&gt;something&lt;/em&gt; that &lt;code&gt;a&lt;/code&gt; is added to is not &lt;code&gt;b&lt;/code&gt; but &lt;code&gt;b * c&lt;/code&gt;, the expression built
at its right.&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;┌────────────────────────
│ ┌───────────┐
│ a + │ b * c │ ...
│ └───────────┘
└────────────────────────&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;h3 id="when-does-that-expression-end"&gt;When does that expression end?&lt;a class="anchor" href="#when-does-that-expression-end" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;From &lt;code&gt;b&lt;/code&gt; we keep going: &lt;code&gt;*&lt;/code&gt;, then &lt;code&gt;c&lt;/code&gt;. Peeking past &lt;code&gt;c&lt;/code&gt;, we find another
operator, &lt;code&gt;-&lt;/code&gt;. Since &lt;code&gt;-&lt;/code&gt; has lower precedence than &lt;code&gt;*&lt;/code&gt;, it can&amp;rsquo;t take &lt;code&gt;c&lt;/code&gt; away
from &lt;code&gt;*&lt;/code&gt;, so the multiplication is complete and we wrap it as &lt;code&gt;b * c&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From now on, &lt;code&gt;b * c&lt;/code&gt; behaves as a single unit, sitting between a &lt;code&gt;+&lt;/code&gt; on its
left and a &lt;code&gt;-&lt;/code&gt; on its right. This time both have the same precedence, so the
one on the left wins: &lt;code&gt;+&lt;/code&gt; takes it, giving &lt;code&gt;a + (b * c)&lt;/code&gt;. That whole result
then becomes the left side of &lt;code&gt;-&lt;/code&gt;, and the expression ends with &lt;code&gt;d&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s a lot of words, so here it is step by step:&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;step 1 a + b * c - d &amp;#39;a&amp;#39; waits for the right side of &amp;#39;+&amp;#39;
 ^

step 2 a + b * c - d &amp;#39;b&amp;#39;: next is &amp;#39;*&amp;#39;, stronger than &amp;#39;+&amp;#39;, so &amp;#39;*&amp;#39; takes &amp;#39;b&amp;#39;
 ^

step 3 a + (b * c) - d next is &amp;#39;-&amp;#39;, weaker than &amp;#39;*&amp;#39;: wrap &amp;#39;b * c&amp;#39;
 ^

step 4 (a + (b * c)) - d &amp;#39;-&amp;#39; is as strong as &amp;#39;+&amp;#39;, the left one wins: close &amp;#39;+&amp;#39;
 ^

step 5 ((a + (b * c)) - d) &amp;#39;d&amp;#39; is the last token: close &amp;#39;-&amp;#39;
 ^&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;h2 id="bringing-this-to-real-code"&gt;Bringing this to real code&lt;a class="anchor" href="#bringing-this-to-real-code" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll write this in &lt;mark&gt;C&lt;/mark&gt;. To keep it short, every operand is a single
character (a digit or a letter) until the last section, where tokens become
words. The input is assumed to be well-formed, so there is no error handling.
The complete program, with a &lt;code&gt;main()&lt;/code&gt; that parses one expression per line, is
in the &lt;a href="https://github.com/pabloosabaterr/pratt-parser-article/"&gt;repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First we have to think about how much &lt;u&gt;&lt;strong&gt;precedence&lt;/strong&gt;&lt;/u&gt; an operator has.
We will call this &lt;mark&gt;binding power&lt;/mark&gt;.&lt;/p&gt;
&lt;p&gt;For example, our last expression could be seen as:
&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;One value for each side of every operator.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;a + b * c - d
 1 1 2 2 1 1&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;In code, the operators are an enum, and the binding powers a table indexed by it:
&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;We don&amp;rsquo;t really care about the value of &lt;code&gt;ADD&lt;/code&gt;, &amp;hellip; They come from an
enum, so we know they are all different. &lt;code&gt;NOT_OP&lt;/code&gt; marks a terminal that is not
an operator&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;op_type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;ADD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;SUB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;MUL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;NOT_OP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;binding_powers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;binding_powers&lt;/span&gt; &lt;span class="n"&gt;binding_table&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ADD&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SUB&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MUL&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;But having both sides with the same binding power will make us face
situations like:&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;a - b - c
 1 1 1 1&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;Where when standing on &lt;code&gt;b&lt;/code&gt;, both sides have the same &lt;strong&gt;binding power&lt;/strong&gt;. The
code would still pick one: an equal left binding power is enough to get in,
so &lt;code&gt;b&lt;/code&gt; would go to the second &lt;code&gt;-&lt;/code&gt;, giving &lt;code&gt;a - (b - c)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;+&lt;/code&gt; that wouldn&amp;rsquo;t matter, but with &lt;code&gt;-&lt;/code&gt; it does: &lt;code&gt;(a - b) - c&lt;/code&gt; is not
&lt;code&gt;a - (b - c)&lt;/code&gt;. Which way an operator groups when it repeats is its
&lt;mark&gt;associativity&lt;/mark&gt;: &lt;code&gt;-&lt;/code&gt; is &lt;em&gt;left associative&lt;/em&gt;, because the left one goes first.
To fix it we need to make one of the sides greater.
&lt;em&gt;But which one?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We want &lt;code&gt;(a - b) - c&lt;/code&gt;, so &lt;code&gt;b&lt;/code&gt; has to choose the first &lt;code&gt;-&lt;/code&gt;. Look at what &lt;code&gt;b&lt;/code&gt;
actually compares:&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;a - b - c
 ^ ^
 | +-- left side of the second &amp;#39;-&amp;#39;
 +------ right side of the first &amp;#39;-&amp;#39;&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;It is the right side of &lt;code&gt;-&lt;/code&gt; against its left side. For the left side
to win, the operator&amp;rsquo;s right side has to be greater than its left side.&lt;/p&gt;
&lt;p&gt;For right associative operators like &lt;code&gt;=&lt;/code&gt; or &lt;code&gt;^&lt;/code&gt; it is the reverse: you make
the left side greater.&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;binding_powers&lt;/span&gt; &lt;span class="n"&gt;binding_table&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ADD&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SUB&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MUL&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;
&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;a - b - c
 1 2 1 2&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;And it is clear that on &lt;code&gt;b&lt;/code&gt;, it will be wrapped to the left. Same for our first expression:&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;a + b * c - d
 1 2 3 4 1 2&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;h2 id="the-algorithm"&gt;The algorithm&lt;a class="anchor" href="#the-algorithm" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With our table and everything we have talked about, we can
move on to the actual algorithm. First, the helpers that we are
going to need.&lt;/p&gt;
&lt;p&gt;A node holds a character, its &lt;mark&gt;lexeme&lt;/mark&gt;: the piece of the input it was
read from. Operators are inner nodes: their left
and right sides point to other nodes. Operands like &lt;code&gt;a&lt;/code&gt; are leaves, with no
children.&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;make_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;The input is a string, and &lt;code&gt;src&lt;/code&gt; points to the first character of that
string. &lt;code&gt;next()&lt;/code&gt; moves src to the next character, skipping spaces:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;And &lt;code&gt;get_type()&lt;/code&gt; tells us which is the type of any character:
&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;For simplicity we will only differentiate between operators, while
operands (including &lt;code&gt;'\0'&lt;/code&gt;) will be just labeled as &lt;code&gt;NOT_OP&lt;/code&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;op_type&lt;/span&gt; &lt;span class="nf"&gt;get_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;+&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ADD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SUB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;MUL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;NOT_OP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;h3 id="printing-the-tree"&gt;Printing the tree&lt;a class="anchor" href="#printing-the-tree" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To see what the parser built, we print the tree as an &lt;mark&gt;S-expression&lt;/mark&gt;
&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;The notation Lisp uses: the operator first, then its operands, all
inside parentheses.&lt;/span&gt;&lt;/span&gt;. Every operation becomes &lt;code&gt;(op lhs rhs)&lt;/code&gt; and every
operand is printed as it is, so &lt;code&gt;a + b * c&lt;/code&gt; comes out as &lt;code&gt;(+ a (* b c))&lt;/code&gt;.&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_sexpr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;putchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;(%c &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;print_sexpr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;putchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nf"&gt;print_sexpr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nf"&gt;putchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;A node with no children is an operand. Any other node prints its operator and
its children inside parentheses. The &lt;code&gt;if (n-&amp;gt;lhs)&lt;/code&gt; is for prefix operators,
which only have a right child. We will get to them later.&lt;/p&gt;
&lt;h3 id="lets-break-it-down"&gt;Let&amp;rsquo;s break it down&lt;a class="anchor" href="#lets-break-it-down" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Our so-talked-about Pratt parser:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;parse_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;min_bp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(;;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;op_type&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;NOT_OP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;			&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;binding_powers&lt;/span&gt; &lt;span class="n"&gt;bp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;binding_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;min_bp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;			&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;Here is the whole run. Each box inside another box is a recursive call to &lt;code&gt;parse_expr()&lt;/code&gt;,
and the number in parentheses is its &lt;code&gt;min_bp&lt;/code&gt;. On the right, the S-expression.
&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;Using the same expression from the start: &lt;code&gt;a + b * c - d&lt;/code&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;┌─ parse_expr(0) ─────────────────────────────┐
│ lhs = a │
│ &amp;#39;+&amp;#39; 1 &amp;gt;= 0, take it │ (+ a
│ ┌─ parse_expr(2) ─────────────────────────┐ │
│ │ lhs = b │ │
│ │ &amp;#39;*&amp;#39; 3 &amp;gt;= 2, take it │ │ (+ a (* b
│ │ ┌─ parse_expr(4) ─────────────────────┐ │ │
│ │ │ lhs = c │ │ │
│ │ │ &amp;#39;-&amp;#39; 1 &amp;lt; 4, return c │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ │ lhs = b * c │ │ (+ a (* b c)
│ │ &amp;#39;-&amp;#39; 1 &amp;lt; 2, return b * c │ │
│ └─────────────────────────────────────────┘ │
│ lhs = a + (b * c) │ (+ a (* b c))
│ &amp;#39;-&amp;#39; 1 &amp;gt;= 0, take it │ (- (+ a (* b c))
│ ┌─ parse_expr(2) ─────────────────────────┐ │
│ │ lhs = d │ │
│ │ end of input, return d │ │
│ └─────────────────────────────────────────┘ │
│ lhs = (a + (b * c)) - d │ (- (+ a (* b c)) d)
│ end of input, return │
└─────────────────────────────────────────────┘&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;Every call repeats the same steps: build a left-hand side, look at the next
operator, and check whether its left binding power is at least &lt;code&gt;min_bp&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Put another way, &lt;code&gt;parse_expr(min_bp)&lt;/code&gt; returns the longest expression whose
operators all have a left binding power of at least &lt;code&gt;min_bp&lt;/code&gt;. The first
operator that is too weak ends it, and it is left for one of the calls above
to take.&lt;/p&gt;
&lt;h2 id="parentheses-and-prefix-operators"&gt;Parentheses and prefix operators&lt;a class="anchor" href="#parentheses-and-prefix-operators" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So far &lt;code&gt;parse_expr()&lt;/code&gt; starts by turning the current character into an operand.
Parentheses and prefix operators like &lt;code&gt;!x&lt;/code&gt; also show up where an operand is
expected, so that first step needs more cases. The prefix &lt;code&gt;!&lt;/code&gt; also gets its
own entry in the table:
&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;Plus a &lt;code&gt;case '!': return NOT;&lt;/code&gt; in &lt;code&gt;get_type()&lt;/code&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;op_type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;ADD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;SUB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;MUL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;NOT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;NOT_OP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;binding_powers&lt;/span&gt; &lt;span class="n"&gt;binding_table&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ADD&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SUB&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MUL&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NOT&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="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;The first two lines of &lt;code&gt;parse_expr()&lt;/code&gt; become:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;(&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="cm"&gt;/* skip &amp;#39;)&amp;#39; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;parse_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;binding_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NOT&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;The loop stays the same.&lt;/p&gt;
&lt;p&gt;Parentheses call &lt;code&gt;parse_expr()&lt;/code&gt; with &lt;code&gt;0&lt;/code&gt;: inside them we start fresh, so any
operator is strong enough no matter what is outside. That is all it takes for
&lt;code&gt;(a + b) * c&lt;/code&gt; to work.&lt;/p&gt;
&lt;p&gt;A prefix operator has nothing on its left, so its node has no &lt;code&gt;lhs&lt;/code&gt;. But
&lt;code&gt;get_type()&lt;/code&gt; now returns &lt;code&gt;NOT&lt;/code&gt; for &lt;code&gt;!&lt;/code&gt;, so the loop does look at its left
binding power. That is why it is &lt;code&gt;-1&lt;/code&gt;: &lt;code&gt;min_bp&lt;/code&gt; is never below &lt;code&gt;0&lt;/code&gt;, so the
loop always stops on &lt;code&gt;!&lt;/code&gt; and never takes it as if it came after an
expression. With a &lt;code&gt;0&lt;/code&gt; there, &lt;code&gt;a ! b&lt;/code&gt; would sneak in as &lt;code&gt;(! a b)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What matters is the right one: the operand
is parsed with &lt;code&gt;parse_expr(5)&lt;/code&gt;, so only operators with a left binding power of
at least &lt;code&gt;5&lt;/code&gt; can get into it. For &lt;code&gt;!a * b&lt;/code&gt;:&lt;/p&gt;

&lt;div class="codeblock plain"&gt;
 &lt;pre tabindex="0"&gt;&lt;code&gt;┌─ parse_expr(0) ─────────────────────────────┐
│ &amp;#39;!&amp;#39; is prefix, parse its operand │
│ ┌─ parse_expr(5) ─────────────────────────┐ │
│ │ lhs = a │ │
│ │ &amp;#39;*&amp;#39; 3 &amp;lt; 5, return a │ │
│ └─────────────────────────────────────────┘ │
│ lhs = !a │ (! a)
│ &amp;#39;*&amp;#39; 3 &amp;gt;= 0, take it │ (* (! a)
│ ┌─ parse_expr(4) ─────────────────────────┐ │
│ │ lhs = b │ │
│ │ end of input, return b │ │
│ └─────────────────────────────────────────┘ │
│ lhs = (!a) * b │ (* (! a) b)
│ end of input, return │
└─────────────────────────────────────────────┘&lt;/code&gt;&lt;/pre&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;h2 id="what-about-right-associativity"&gt;What about right associativity?&lt;a class="anchor" href="#what-about-right-associativity" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every operator so far has its right side higher than its left, so all of them
are left associative. To make one right associative, its right side has to be
&lt;em&gt;lower&lt;/em&gt;. For example, a power operator:
&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;Plus a &lt;code&gt;POW&lt;/code&gt; in the enum and a &lt;code&gt;case '^'&lt;/code&gt; in &lt;code&gt;get_type()&lt;/code&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;POW&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="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;In &lt;code&gt;a ^ b ^ c&lt;/code&gt;, the first &lt;code&gt;^&lt;/code&gt; parses its right side with a minimum of &lt;code&gt;6&lt;/code&gt;.
The second &lt;code&gt;^&lt;/code&gt; has a left binding power of &lt;code&gt;7&lt;/code&gt;, so it gets in, and the result
is &lt;code&gt;a ^ (b ^ c)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;7&lt;/code&gt; is higher than the &lt;code&gt;5&lt;/code&gt; of &lt;code&gt;!&lt;/code&gt;, &lt;code&gt;^&lt;/code&gt; also gets into its operand:
&lt;code&gt;!a ^ b&lt;/code&gt; is &lt;code&gt;(! (^ a b))&lt;/code&gt;. To get &lt;code&gt;(!a) ^ b&lt;/code&gt; instead, give &lt;code&gt;NOT&lt;/code&gt; a right
binding power higher than &lt;code&gt;7&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="beyond-arithmetic-what-else-can-we-do"&gt;Beyond arithmetic, what else can we do?&lt;a class="anchor" href="#beyond-arithmetic-what-else-can-we-do" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Until now, every token had one of two jobs. In the first part of
&lt;code&gt;parse_expr()&lt;/code&gt; it &lt;strong&gt;starts&lt;/strong&gt; an expression: an operand, a &lt;code&gt;(&lt;/code&gt; or a &lt;code&gt;!&lt;/code&gt;. In the
loop it comes &lt;strong&gt;after&lt;/strong&gt; an expression that is already built: &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;,
&lt;code&gt;^&lt;/code&gt;. Pratt calls these two jobs &lt;mark&gt;nud&lt;/mark&gt; and &lt;mark&gt;led&lt;/mark&gt;&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;&lt;em&gt;Null denotation&lt;/em&gt;
and &lt;em&gt;left denotation&lt;/em&gt;. The led is the one that receives the expression on its
left.&lt;/span&gt;&lt;/span&gt;&lt;sup class="cite"&gt;&lt;a href="#ref-3" id="cite-3-19"
 data-preview-kind="Vaughan R. Pratt · 1973"
 data-preview-title="Top Down Operator Precedence"
 data-preview-desc="The original paper, POPL 1973."&gt;[3]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Nothing says a led has to be “an operator and then an expression”. It receives
the left-hand side, returns a new one, and in between it can do &lt;mark&gt;whatever it
wants&lt;/mark&gt;. That is what takes Pratt parsing way beyond arithmetic expressions.&lt;/p&gt;
&lt;h3 id="indexing-and-calls"&gt;Indexing and calls&lt;a class="anchor" href="#indexing-and-calls" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;a[b]&lt;/code&gt; is an infix &lt;code&gt;[&lt;/code&gt; with a very strong left binding power. Instead of
parsing its right side with a binding power, it parses a whole expression from
&lt;code&gt;0&lt;/code&gt;, like parentheses do, and then skips the &lt;code&gt;]&lt;/code&gt;. A call &lt;code&gt;f(a)&lt;/code&gt; is exactly the
same with &lt;code&gt;(&lt;/code&gt;.&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;INDEX&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="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="cm"&gt;/* right side is never used */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CALL&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="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;With &lt;code&gt;case '[': return INDEX;&lt;/code&gt; and &lt;code&gt;case '(': return CALL;&lt;/code&gt; in
&lt;code&gt;get_type()&lt;/code&gt;. The same goes for &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;,&lt;/code&gt; below.&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;In the loop, right after &lt;code&gt;next()&lt;/code&gt;:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;INDEX&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CALL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;			&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;inside&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;			&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="cm"&gt;/* skip &amp;#39;]&amp;#39; or &amp;#39;)&amp;#39; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;			&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inside&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;			&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;]&lt;/code&gt; and &lt;code&gt;)&lt;/code&gt; are &lt;code&gt;NOT_OP&lt;/code&gt;, so the inner &lt;code&gt;parse_expr(0)&lt;/code&gt; stops right on them.
&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;An empty call like &lt;code&gt;f()&lt;/code&gt; needs one extra check: if the next character
is already &lt;code&gt;)&lt;/code&gt;, skip it without parsing anything.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Notice that &lt;code&gt;(&lt;/code&gt; now lives in both places. As a nud it groups, as a led it
calls. The parser never mixes them up, because it always knows where it is: if
there is no expression yet, it is a nud; if there is one on its left, it is a
led. The same trick separates a unary &lt;code&gt;-a&lt;/code&gt; from a binary &lt;code&gt;a - b&lt;/code&gt;, although
then &lt;code&gt;-&lt;/code&gt; needs two rows, one for each job, so real parsers usually keep a
prefix table and an infix table&lt;sup class="cite"&gt;&lt;a href="#ref-1" id="cite-1-22"
 data-preview-kind="Alex Kladov · 2020"
 data-preview-title="Simple but Powerful Pratt Parsing"
 data-preview-desc="matklad.github.io"&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h3 id="member-access"&gt;Member access&lt;a class="anchor" href="#member-access" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;.&lt;/code&gt; is a plain infix operator, the strongest of all and left associative:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DOT&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="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;a.b.c&lt;/code&gt; is &lt;code&gt;(. (. a b) c)&lt;/code&gt;, and since &lt;code&gt;.&lt;/code&gt;, &lt;code&gt;[&lt;/code&gt; and &lt;code&gt;(&lt;/code&gt; share the same left
binding power, they chain from left to right: &lt;code&gt;a.b[c]&lt;/code&gt; is &lt;code&gt;([ (. a b) c)&lt;/code&gt;.
It also plays well with the prefix operators: &lt;code&gt;!a.b&lt;/code&gt; is &lt;code&gt;(! (. a b))&lt;/code&gt;,
because &lt;code&gt;9&lt;/code&gt; is higher than the &lt;code&gt;5&lt;/code&gt; of &lt;code&gt;!&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The right side of &lt;code&gt;.&lt;/code&gt; should be a name, not any expression. The parser can
check that the node it got back has no children, or leave it to a later pass.&lt;/p&gt;
&lt;h3 id="the-comma"&gt;The comma&lt;a class="anchor" href="#the-comma" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;,&lt;/code&gt; can be an operator too, the weakest one:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;COMMA&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;A left binding power of &lt;code&gt;0&lt;/code&gt; means it is only taken where we start fresh: at
the top level or inside &lt;code&gt;(&lt;/code&gt;, &lt;code&gt;[&lt;/code&gt; and calls. So &lt;code&gt;f(a, b, c)&lt;/code&gt; gives its call
node &lt;code&gt;(, (, a b) c)&lt;/code&gt; as the argument, a left-leaning list that is easy to
flatten later.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.geeksforgeeks.org/c/comma-in-c/"&gt;C actually has a comma operator&lt;/a&gt;,
but having it everywhere is not always what you want. The other option is to
keep &lt;code&gt;,&lt;/code&gt; out of the table and let the call led loop by itself: parse one
argument with &lt;code&gt;parse_expr(0)&lt;/code&gt;, which stops on &lt;code&gt;,&lt;/code&gt; because it is &lt;code&gt;NOT_OP&lt;/code&gt;, and
while the next character is &lt;code&gt;,&lt;/code&gt;, skip it and parse another one.&lt;/p&gt;
&lt;h3 id="if-fn-and-friends"&gt;if, fn and friends&lt;a class="anchor" href="#if-fn-and-friends" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Keywords like &lt;code&gt;if&lt;/code&gt; and &lt;code&gt;fn&lt;/code&gt; are longer than one character, so first the
lexer&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;The part that splits the input into tokens.&lt;/span&gt;&lt;/span&gt; has to
learn to read words. &lt;code&gt;src&lt;/code&gt; still points to the current token, and a new &lt;code&gt;len&lt;/code&gt;
says how long it is:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* start of the current token */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* length of the current token */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="n"&gt;len&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isalnum&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;next()&lt;/code&gt; skips the current token and the spaces after it, then measures the
next one: a run of letters and digits, or a single character otherwise. That
second case is what keeps &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;(&lt;/code&gt; and the rest working as before. Since &lt;code&gt;len&lt;/code&gt;
starts at &lt;code&gt;0&lt;/code&gt;, we call &lt;code&gt;next()&lt;/code&gt; once before parsing, so it holds the first
token.&lt;/p&gt;
&lt;p&gt;Two small helpers work on that token. &lt;code&gt;is()&lt;/code&gt; checks whether it is a given
word, and &lt;code&gt;take()&lt;/code&gt; returns it as a string and moves to the next
one&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;&lt;code&gt;bool&lt;/code&gt; needs &lt;code&gt;&amp;lt;stdbool.h&amp;gt;&lt;/code&gt; before C23, and &lt;code&gt;strndup()&lt;/code&gt; is
POSIX.&lt;/span&gt;&lt;/span&gt;:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;strncmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;strndup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;Nodes now hold a &lt;code&gt;char *lex&lt;/code&gt; instead of a &lt;code&gt;char&lt;/code&gt;. Wherever we used &lt;code&gt;c&lt;/code&gt; and
then called &lt;code&gt;next()&lt;/code&gt;, we now call &lt;code&gt;take()&lt;/code&gt;: an operand becomes
&lt;code&gt;make_node(take(), NULL, NULL)&lt;/code&gt;, and in the loop &lt;code&gt;next()&lt;/code&gt; becomes
&lt;code&gt;char *lex = take();&lt;/code&gt;, with &lt;code&gt;lex&lt;/code&gt; going into &lt;code&gt;make_node()&lt;/code&gt; instead of &lt;code&gt;c&lt;/code&gt;.
Careful with &lt;code&gt;!&lt;/code&gt;: in &lt;code&gt;make_node(take(), NULL, parse_expr(...))&lt;/code&gt;, C doesn&amp;rsquo;t say
which argument is evaluated first, so &lt;code&gt;take()&lt;/code&gt; goes on its own line:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;NOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;parse_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;binding_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NOT&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;get_type()&lt;/code&gt; doesn&amp;rsquo;t change: words start with a letter or a digit, so they
are &lt;code&gt;NOT_OP&lt;/code&gt;. That is also what makes &lt;code&gt;else&lt;/code&gt; stop the loop.&lt;/p&gt;
&lt;p&gt;With that, &lt;code&gt;if&lt;/code&gt; is one more nud. It reads a condition, a branch and maybe an
&lt;code&gt;else&lt;/code&gt;, which goes in a third child, &lt;code&gt;els&lt;/code&gt;&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;&lt;code&gt;make_node()&lt;/code&gt; now uses
&lt;code&gt;calloc()&lt;/code&gt;, so &lt;code&gt;els&lt;/code&gt; starts as &lt;code&gt;NULL&lt;/code&gt;.&lt;/span&gt;&lt;/span&gt;:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;if&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;else&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;			&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;			&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;els&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;print_sexpr()&lt;/code&gt; prints the lexeme with &lt;code&gt;%s&lt;/code&gt; and the &lt;code&gt;else&lt;/code&gt; branch after the
other two:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_sexpr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;fputs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;(%s &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;print_sexpr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;putchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nf"&gt;print_sexpr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;els&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;putchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nf"&gt;print_sexpr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;els&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nf"&gt;putchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;if x y else z + 1&lt;/code&gt; gives &lt;code&gt;(if x y (+ z 1))&lt;/code&gt;, and &lt;code&gt;if a if b c else d&lt;/code&gt; gives
&lt;code&gt;(if a (if b c d))&lt;/code&gt;: the &lt;code&gt;else&lt;/code&gt; goes to the closest &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is a catch: in &lt;code&gt;if c (x)&lt;/code&gt;, the &lt;code&gt;(&lt;/code&gt; is taken as a call, so the condition
becomes &lt;code&gt;c(x)&lt;/code&gt;. Rust avoids this kind of problem by requiring a block &lt;code&gt;{ }&lt;/code&gt;
after the condition.&lt;/p&gt;
&lt;p&gt;A block &lt;code&gt;{ ... }&lt;/code&gt; could be another nud that parses expressions separated by
&lt;code&gt;;&lt;/code&gt; until &lt;code&gt;}&lt;/code&gt;. And &lt;code&gt;fn(x) { ... }&lt;/code&gt; could be a nud that reads the parameters,
parses the body and returns a function node, a function without a name. Since
the loop still runs after any nud, that function can be called right where it
is written: in &lt;code&gt;fn(x) { x * 2 }(3)&lt;/code&gt;, the &lt;code&gt;(&lt;/code&gt; after the &lt;code&gt;}&lt;/code&gt; is just a call, so
it defines a function that doubles its argument and calls it with &lt;code&gt;3&lt;/code&gt;. Neither
is in the repo, but both are only more cases at the start of &lt;code&gt;parse_expr()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is how &lt;mark&gt;expression-oriented&lt;/mark&gt; languages like
&lt;a href="https://doc.rust-lang.org/reference/statements-and-expressions.html"&gt;Rust&lt;/a&gt;,
&lt;a href="https://docs.ruby-lang.org/en/master/syntax/control_expressions_rdoc.html"&gt;Ruby&lt;/a&gt;
or the Lisps see the world: &lt;code&gt;if&lt;/code&gt; gives back a value, and so does a group of
expressions (a block in Rust, &lt;code&gt;begin ... end&lt;/code&gt; in Ruby,
&lt;a href="https://www.lispworks.com/documentation/HyperSpec/Body/s_progn.htm"&gt;&lt;code&gt;progn&lt;/code&gt;&lt;/a&gt;
in Common Lisp), so they are expressions like any other.&lt;/p&gt;
&lt;p&gt;Douglas Crockford took it further and parsed a subset of JavaScript,
statements included, with nothing but TDOP&lt;span class="sn"&gt;&lt;span class="sn-ref" aria-hidden="true"&gt;&lt;/span&gt;&lt;span class="sn-body" role="note"&gt;a.k.a. Pratt
parser&lt;/span&gt;&lt;/span&gt;, adding a third job, &lt;code&gt;std&lt;/code&gt;, for statements like &lt;code&gt;var&lt;/code&gt; and
&lt;code&gt;return&lt;/code&gt;&lt;sup class="cite"&gt;&lt;a href="#ref-5" id="cite-5-27"
 data-preview-kind="Douglas Crockford · 2007"
 data-preview-title="Top Down Operator Precedence"
 data-preview-desc="Parses a subset of JavaScript, statements included, with TDOP."&gt;[5]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;At that point the whole parser is &lt;code&gt;parse_expr()&lt;/code&gt; and a table where every token
says what it does at the start of an expression and what it does after one.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor" href="#conclusion" aria-label="Link to this section"&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At the start, every precedence level was a new grammar rule, and to make it
work in a recursive descent parser we had to remove left recursion and add
rules with &lt;code&gt;ε&lt;/code&gt;. With Pratt parsing, the grammar stays the short, ambiguous
one, and precedence and associativity live in a table.&lt;/p&gt;
&lt;p&gt;yacc and Bison use the same idea: an ambiguous grammar plus
&lt;a href="https://www.gnu.org/software/bison/manual/html_node/Precedence.html"&gt;&lt;code&gt;%left&lt;/code&gt; and &lt;code&gt;%right&lt;/code&gt; declarations&lt;/a&gt;
to build LR parsers. Pratt does it by hand, inside a recursive descent parser.
The same loop is also known as
&lt;a href="https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm"&gt;precedence climbing&lt;/a&gt;,
which is essentially the same algorithm with a different way of writing the
precedences.&lt;/p&gt;
&lt;p&gt;The whole expression parser is one loop and one table, and adding an operator
is adding a row: comparisons, &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; and &lt;code&gt;||&lt;/code&gt; are only more rows. This is the
approach I&amp;rsquo;m taking for the expression parser of &lt;a href="https://pablosabater.dev/projects/orn/" data-preview-kind="Project" data-preview-title="Orn" data-preview-desc="A range-based systems programming language. I&amp;#39;m not building it to be useful, but to explore an idea."&gt;Orn&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What this post leaves out is error handling. A real parser has to say what is
wrong with &lt;code&gt;a +&lt;/code&gt; or an unclosed &lt;code&gt;(&lt;/code&gt;, and recover to keep going. That is
another post.&lt;/p&gt;
&lt;p&gt;So the final grammar is still the short one from the start, with a few more
alternatives, plus a table:&lt;/p&gt;

&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;binding_powers&lt;/span&gt; &lt;span class="n"&gt;binding_table&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;COMMA&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ADD&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SUB&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MUL&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NOT&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="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;POW&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="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;INDEX&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="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CALL&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="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DOT&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="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;
&lt;div class="codeblock"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bnf" data-lang="bnf"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;expr = expr binop expr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | expr &amp;#39;(&amp;#39; expr &amp;#39;)&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | expr &amp;#39;[&amp;#39; expr &amp;#39;]&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | atom
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;atom = number
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | &amp;#39;(&amp;#39; expr &amp;#39;)&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | &amp;#39;!&amp;#39; expr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | &amp;#39;if&amp;#39; expr expr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | &amp;#39;if&amp;#39; expr expr &amp;#39;else&amp;#39; expr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;binop = &amp;#39;,&amp;#39; | &amp;#39;+&amp;#39; | &amp;#39;-&amp;#39; | &amp;#39;*&amp;#39; | &amp;#39;^&amp;#39; | &amp;#39;.&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;button class="copy" type="button" aria-label="Copy code" hidden&gt;Copy&lt;/button&gt;
&lt;/div&gt;&lt;p&gt;On its own it is still ambiguous. The table decides how operators group, and
the parser decides that an &lt;code&gt;else&lt;/code&gt; goes to the closest &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Chao, Pablo&lt;/p&gt;</description></item></channel></rss>