summaryrefslogtreecommitdiff
path: root/devdocs/elisp/operator-precedence-grammars.html
diff options
context:
space:
mode:
Diffstat (limited to 'devdocs/elisp/operator-precedence-grammars.html')
-rw-r--r--devdocs/elisp/operator-precedence-grammars.html23
1 files changed, 23 insertions, 0 deletions
diff --git a/devdocs/elisp/operator-precedence-grammars.html b/devdocs/elisp/operator-precedence-grammars.html
new file mode 100644
index 00000000..7b36c16d
--- /dev/null
+++ b/devdocs/elisp/operator-precedence-grammars.html
@@ -0,0 +1,23 @@
+ <h4 class="subsubsection">Operator Precedence Grammars</h4> <p>SMIE’s precedence grammars simply give to each token a pair of precedences: the left-precedence and the right-precedence. We say <code>T1 &lt; T2</code> if the right-precedence of token <code>T1</code> is less than the left-precedence of token <code>T2</code>. A good way to read this <code>&lt;</code> is as a kind of parenthesis: if we find <code>... T1 something
+T2 ...</code> then that should be parsed as <code>... T1 (something T2 ...</code> rather than as <code>... T1 something) T2 ...</code>. The latter interpretation would be the case if we had <code>T1 &gt; T2</code>. If we have <code>T1 = T2</code>, it means that token T2 follows token T1 in the same syntactic construction, so typically we have <code>"begin" = "end"</code>. Such pairs of precedences are sufficient to express left-associativity or right-associativity of infix operators, nesting of tokens like parentheses and many other cases. </p> <dl> <dt id="smie-prec2-&gt;grammar">Function: <strong>smie-prec2-&gt;grammar</strong> <em>table</em>
+</dt> <dd><p>This function takes a <em>prec2</em> grammar <var>table</var> and returns an alist suitable for use in <code>smie-setup</code>. The <em>prec2</em> <var>table</var> is itself meant to be built by one of the functions below. </p></dd>
+</dl> <dl> <dt id="smie-merge-prec2s">Function: <strong>smie-merge-prec2s</strong> <em>&amp;rest tables</em>
+</dt> <dd><p>This function takes several <em>prec2</em> <var>tables</var> and merges them into a new <em>prec2</em> table. </p></dd>
+</dl> <dl> <dt id="smie-precs-&gt;prec2">Function: <strong>smie-precs-&gt;prec2</strong> <em>precs</em>
+</dt> <dd><p>This function builds a <em>prec2</em> table from a table of precedences <var>precs</var>. <var>precs</var> should be a list, sorted by precedence (for example <code>"+"</code> will come before <code>"*"</code>), of elements of the form <code>(<var>assoc</var> <var>op</var> ...)</code>, where each <var>op</var> is a token that acts as an operator; <var>assoc</var> is their associativity, which can be either <code>left</code>, <code>right</code>, <code>assoc</code>, or <code>nonassoc</code>. All operators in a given element share the same precedence level and associativity. </p></dd>
+</dl> <dl> <dt id="smie-bnf-&gt;prec2">Function: <strong>smie-bnf-&gt;prec2</strong> <em>bnf &amp;rest resolvers</em>
+</dt> <dd>
+<p>This function lets you specify the grammar using a BNF notation. It accepts a <var>bnf</var> description of the grammar along with a set of conflict resolution rules <var>resolvers</var>, and returns a <em>prec2</em> table. </p> <p><var>bnf</var> is a list of nonterminal definitions of the form <code>(<var>nonterm</var> <var>rhs1</var> <var>rhs2</var> ...)</code> where each <var>rhs</var> is a (non-empty) list of terminals (aka tokens) or non-terminals. </p> <p>Not all grammars are accepted: </p>
+<ul> <li> An <var>rhs</var> cannot be an empty list (an empty list is never needed, since SMIE allows all non-terminals to match the empty string anyway). </li>
+<li> An <var>rhs</var> cannot have 2 consecutive non-terminals: each pair of non-terminals needs to be separated by a terminal (aka token). This is a fundamental limitation of operator precedence grammars. </li>
+</ul> <p>Additionally, conflicts can occur: </p>
+<ul> <li> The returned <em>prec2</em> table holds constraints between pairs of tokens, and for any given pair only one constraint can be present: T1 &lt; T2, T1 = T2, or T1 &gt; T2. </li>
+<li> A token can be an <code>opener</code> (something similar to an open-paren), a <code>closer</code> (like a close-paren), or <code>neither</code> of the two (e.g., an infix operator, or an inner token like <code>"else"</code>). </li>
+</ul> <p>Precedence conflicts can be resolved via <var>resolvers</var>, which is a list of <em>precs</em> tables (see <code>smie-precs-&gt;prec2</code>): for each precedence conflict, if those <code>precs</code> tables specify a particular constraint, then the conflict is resolved by using this constraint instead, else a conflict is reported and one of the conflicting constraints is picked arbitrarily and the others are simply ignored. </p>
+</dd>
+</dl><div class="_attribution">
+ <p class="_attribution-p">
+ Copyright &copy; 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br>
+ <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Operator-Precedence-Grammars.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Operator-Precedence-Grammars.html</a>
+ </p>
+</div>