---
title: Cyclic Compilation Algorithm for Operator Precedence Grammars
url: https://www.emergentmind.com/topics/cyclic-compilation-algorithm
type: topic
---

# Cyclic Compilation Algorithm for Operator Precedence Grammars

The cyclic compilation algorithm is a parallel parsing and compilation method built on cyclic operator precedence grammars, an enriched form of operator precedence grammars in which the traditional acyclicity restriction on the equality precedence relation $\doteq$ is removed while conflict-freeness is preserved. In this setting, operator precedence languages retain the local parsability property, so a code fragment enclosed within suitable boundary markers can be compiled with no knowledge of its external context, but cyclic equality also permits sentences with flat unbounded substructures and unranked syntax trees that can be naturally partitioned into chunks suitable for parallel parsing [2309.04200].

## 1. Formal framework and precedence structure

Let $\Sigma$ be a finite terminal alphabet and $N$ a finite nonterminal set, with $V=\Sigma\cup N$. An operator grammar (O-grammar) is a context-free grammar $G=(\Sigma,N,P,S)$ whose productions $A\to\alpha$ satisfy the operator form: in every right-hand side $\alpha\in V^*$, at least one terminal symbol is interposed between any two consecutive nonterminals. Renaming rules and $\varepsilon$-rules are forbidden, except possibly one $\varepsilon$-rule whose LHS is a start symbol not appearing on any RHS [2309.04200].

The left and right terminal sets for $A\in N$ are
$$
\mathcal{L}_G(A)=\{ a\in\Sigma \mid \exists C\in N\cup\{\varepsilon\}, \exists \alpha\in V^*: A \xLongrightarrow{*} C\, a\, \alpha \},
$$
$$
\mathcal{R}_G(A)=\{ a\in\Sigma \mid \exists C\in N\cup\{\varepsilon\}, \exists \alpha\in V^*: A \xLongrightarrow{*} \alpha\, a\, C \}.
$$

Over $\Sigma\cup\{\#\}$, with $\#$ a delimiter not in $\Sigma$, the standard Floyd operator precedence relations are defined as follows. Equal precedence is
$$
a \doteq b \iff \exists A \to \alpha\, a\, C\, b\, \beta \in P,\quad C \in N \cup \{\varepsilon\}.
$$
Takes precedence is
$$
a \gtrdot b \iff \exists A \to \alpha\, B\, b\, \beta \in P \text{ and } a \in \mathcal{R}_G(B);\quad a \gtrdot \# \iff B \in S \text{ and } a \in \mathcal{R}_G(B).
$$
Yields precedence is
$$
a \lessdot b \iff \exists A \to \alpha\, a\, B\, \beta \in P \text{ and } b \in \mathcal{L}_G(B);\quad \# \lessdot b \iff B \in S \text{ and } b \in \mathcal{L}_G(B).
$$

These relations are collected in an operator precedence matrix
$$
M \in \left( \{ \lessdot,\, \doteq,\, \gtrdot \}^{\Sigma_\# \times \Sigma_\# } \right), \quad \Sigma_\#=\Sigma\cup\{\#\},
$$
where each cell $M_{a,b}\subseteq\{\lessdot,\doteq,\gtrdot\}$ records the relations holding between $a$ and $b$. The matrix is conflict-free iff $\forall a,b\in\Sigma\cup\{\#\}, |M_{a,b}|\le 1$. A grammar is an operator precedence grammar iff its operator precedence matrix is conflict-free. The matrix is complete iff $\forall a,b, |M_{a,b}|=1$, and if $M_{\#,\#}$ is nonempty then $M_{\#,\#}=\{\doteq\}$.

Prior literature traditionally assumed that $\doteq$ is acyclic over $\Sigma$, meaning that the transitive closure of $\doteq$ is irreflexive on $\Sigma\times\Sigma$. This implies a uniform bound on the length of rule RHSs and prevents cycles such as $a\doteq a$ or longer loops. The cyclic setting removes this restriction and admits equality cycles of the form
$$
a_1 \doteq a_2 \doteq \dots \doteq a_k \doteq a_1
$$
provided the matrix remains conflict-free.

## 2. Local parsability and chain decomposition

Local parsability is formalized through chains. Given a conflict-free operator precedence matrix $M$ and $\#$ delimiters, a simple chain is
$$
{}^{a_0}\{a_1 a_2 \dots a_n\}^{a_{n+1}}
\quad \text{with } a_0,a_{n+1}\in\Sigma_\#,\, a_i\in\Sigma,\, a_0 \lessdot a_1 \doteq \dots \doteq a_n \gtrdot a_{n+1}.
$$
A composed chain allows interposed subchains between the equal-precedence terminals [2309.04200].

The locality principle states that if $(\Sigma,M)$ is a conflict-free OP-alphabet, $c={}^{a}\{x\}^{b}$ is any chain, and $\mathcal{A}$ is any operator precedence automaton compatible with $M$, then there exists a support run in $\mathcal{A}$, written $q \xRightarrow{x} q'$, such that the first move is a push and the last move is a pop. The construction of that support depends only on $x$ and the boundary relations $a\lessdot x$ and $x\gtrdot b$, not on the context surrounding $a$ and $b$ in the full input.

In operator precedence automata, configurations are triples $(\text{stack},\text{state},\text{unread-input})$. If the top-of-stack symbol $a$ and the next input symbol at the beginning of $x$ satisfy $a\lessdot x$, the run must begin with a push. Inside $x$, all moves are shifts along $\doteq$ links and pops when ending nested subchains. Because $M$ is conflict-free, the sequence of shifts and pops generated by $x$ is uniquely determined by the structure of $x$ as a chain. The final symbol $b$ triggers a pop from the cell $a_n\gtrdot b$.

This locality principle holds unchanged in cyclic operator precedence grammars. Cyclic $\doteq$ only prolongs simple-chain bodies; the support within an equal-precedence run is a loop of shift moves. The first and last moves are still push and pop determined by the surrounding yield and take relations, so locality remains valid. This is the formal basis for chunk-level independence in the cyclic compilation algorithm.

## 3. Cyclic grammars, regular-expression RHSs, and unranked trees

To capture unbounded flat fragments implied by equality cycles, cyclic operator precedence grammars enrich the right-hand side format with simplified regular expressions. A “$^+$-O-expression” is a regular expression over $V$ using concatenation and Kleene plus “$+$”, subject to the operator-form constraint and with each argument to $+$ ending in a terminal. A cyclic O-grammar (C-OG) is an O-grammar whose productions $A\to\alpha$ have RHS $\alpha$ that is a $^+$-O-expression. Immediate derivation is defined by $\beta A \gamma \Rightarrow \beta \zeta \gamma$ if $\zeta\in L(\alpha)$ [2309.04200].

In this enriched setting, equal precedence is extended to RHS languages:
$$
a \doteq b \iff \exists A \to \alpha \in P\ \exists\, \zeta \in L(\alpha),\, \exists\, \eta,\theta \in V^* \text{ such that } \zeta = \eta\, a\, B\, b\, \theta,\ B\in N\cup\{\varepsilon\}.
$$
The relations $\lessdot$ and $\gtrdot$ remain defined as usual through $\mathcal{L}$ and $\mathcal{R}$. A C-OG is a cyclic operator precedence grammar (C-OPG) iff its operator precedence matrix is conflict-free.

Allowing “$+$” in RHSs lets rules denote infinite regular sets of terminal and nonterminal patterns consistent with operator form. The implicit syntax trees become unranked: nodes can have unbounded numbers of children along an equal-precedence run. This exactly matches the intended structure of flat, associative operators or list-like constructs.

A concrete cyclic grammar over terminals $\Sigma=\{+, -, \times, /, (, ), n\}$ and nonterminals $\{P,T,M,N,F,D,E\}$ includes schematic productions such as
- $P \to (T +)^+ T$
- $T \to (F \times)^+ F \mid M - N \mid D / E$
- $M \to M - N \mid (F \times)^+ F \mid D / E$
- $N \to (F \times)^+ F \mid D / E$
- $F \to D / E \mid n$

with parenthesized $T$ generated by $D$ and $E$. In the corresponding matrix, $+\doteq +$ and $\times\doteq\times$ are equality cycles, multiplicative operators take precedence over additive ones, and $/$ and $-$ take precedence over $\times$ and $+$ respectively. For the sentence
$$
n + n + (n\times n) + \frac{(n+n)}{n} + n + n
$$
the parse tree has a $T$-node whose additive children are many, reflecting an unbounded flat structure governed by $+\doteq +$.

## 4. Cyclic compilation algorithm

The cyclic compilation algorithm is a parallel parsing and compilation algorithm exploiting local parsability and equality cycles. It comprises five stages [2309.04200].

The first stage is construction of the operator precedence matrix from a cyclic grammar $G=(\Sigma,N,P,S)$ whose RHSs are $^+$-O-expressions. For every production $A\to\alpha$, the construction considers the regular language $L(\alpha)$. For each word $\zeta\in L(\alpha)$ and each pair of terminals $(a,b)$ that appear with at most one nonterminal between them, it adds $a\doteq b$ if $\zeta$ has a segment $\eta a B b \theta$ with $B\in N\cup\{\varepsilon\}$. Yield and take relations are computed through $\mathcal{L}$ and $\mathcal{R}$, and relations with $\#$ are set using $\mathcal{L}_G(S)$ and $\mathcal{R}_G(S)$. Conflict-freeness is then checked. For regular RHSs, the algorithmic trick is to use finite normalizations: let $\hat{P}$ be the set of bare RHSs with plus operators removed and $\tilde{P}$ the set of prefixes of strings from $L(\alpha)$ while normalizing double occurrences under $+$ by keeping at most two occurrences. Computing $\mathcal{L}$ and $\mathcal{R}$ from these finite normalizations preserves correctness while giving a finite basis for matrix construction.

The second stage is input partitioning. For input $w=a_1a_2\dots a_n$ with $\#$ padding, the algorithm computes precedence relations between consecutive terminals. A chunk is any maximal interval $[i..j]$ such that $a_{i-1}\lessdot a_i$, $a_j\gtrdot a_{j+1}$, and for $k\in[i..j-1]$, $a_k\doteq a_{k+1}$ or the interval continues through nested subchains. Intuitively, a chunk is the body $x$ of a chain ${}^{a_{i-1}}\{x\}^{a_{j+1}}$. Markers such as parentheses provide obvious chunk boundaries, but equality cycles also make long equal-precedence runs available for splitting. If an equal-precedence run is extremely long, the algorithm further subpartitions it into subchunks of bounded size $B$, a tunable parameter. Formally, within any maximal run
$$
a_p \doteq a_{p+1} \doteq \dots \doteq a_q,
$$
one chooses boundaries $p=k_0<k_1<\dots<k_m=q$ with $m\approx \lceil (q-p)/B \rceil$ so that each subrun $[k_t+1..k_{t+1}]$ has length at most $B$.

The third stage is parallel parsing of chunks. Each chunk is parsed locally by a bottom-up operator precedence parser or an operator precedence automaton-based recognizer, starting from a push and ending at a pop, as guaranteed by the $\lessdot$ and $\gtrdot$ boundaries. The chunk parser builds a partial parse forest, with unranked trees for cyclic equality runs, and uses a backward-deterministic grammar to prevent ambiguity. Synchronization points occur at chunk boundaries. Because local parsability holds, chunk parses are independent and merging only needs to inspect adjacency relations in the precedence matrix for the extreme terminals.

The fourth stage concerns determinism and conflict resolution. Determinism requires a conflict-free precedence matrix and a backward-deterministic grammar satisfying the condition that if $B\to\alpha$ and $C\to\alpha$ are both in $P$, then $B=C$. For cyclic $\doteq$ runs, the local parser uses normalized “two-occurrence” equivalence to prevent looping ambiguity; it recognizes patterns under $+$ by detecting double occurrence of cycles and then compacting them. If precedence construction detects conflicts, the grammar must be revised. If chunk boundaries fall within an equal-precedence cycle, the algorithm meta-labels subchunks and merges them under a single parent node representing the operator at that precedence level.

The fifth stage is merging. Chunks are processed in input order, and merging examines only the extreme terminals of adjacent chunks. If the previous chunk’s right extreme and the next chunk’s left extreme satisfy $\doteq$, the algorithm performs an equal-precedence merge, combining the partial parses under a single flat node. If they satisfy $\lessdot$ or $\gtrdot$, the algorithm uses operator precedence to decide nesting and perform reductions or pops. The invariants are that each chunk parse respects operator form and precedence relations inside the chunk, merging checks only adjacency of chunk extremes via the precedence matrix and performs reductions without peeking inside chunk bodies, and after merging the frontier of the global tree equals the original input while the parse respects the matrix.

The stated complexity is as follows. Let $n=|w|$, $k$ be the number of chunks, and $P$ the number of processors. Building the precedence matrix is linear in grammar size and in the finite normalization of RHSs; if $h$ is the maximum nesting depth of $+$ and $m$ is the maximum primitive RHS length, the normalization yields $O(m^h)$ distinct prefixes and building the matrix is $O(|P|\cdot m^h)$ in the worst case. Partitioning is $O(n)$, with chunk splitting incurring $O(k)$. Parsing chunks has total work $O(n)$, since each terminal participates in $O(1)$ local decisions under a conflict-free matrix, and the parallel parse time is approximately $\max_t |C_t|$, where $C_t$ are chunk lengths. Merging is $O(k)$. Overall sequential time is $O(n)$, and the parallel time is described as
$$
T_{\mathrm{par}(n,k,P)} \approx \max_{t=1..k} |C_t| + O(k).
$$
Space usage is $O(n)$ for distributed parse stacks and $O(|\Sigma|^2)$ for the precedence matrix.

## 5. Expressive equivalences and formal correspondences

The enriched cyclic formalism is presented as fully equivalent in expressive power to other formalisms for

Source: https://www.emergentmind.com/topics/cyclic-compilation-algorithm