Constant-Cost Text
Arata Furukawa · Last revised 2026-11-01
This proof shows that the Conditions for Linear Cost
stay sufficient when taking the text of a node is not a copying operation,
given the guarantee of Cost that text costs a
constant in a parse of a whole input and in a parse of a Document. It also
shows that comparing two strings may be counted as copying only one of its
operands, and what a stream adds to the promises of
Classification.
Setting
Fix a grammar, a start rule and an input of length n, and let \hat{n} = n + 1. "A constant" below means a number that depends only on the grammar and the backend.
Guarantee. By Cost:
- (G1) in a parse of a whole input, in bytes or in code points, valid UTF-8 or
not, and in a parse of a Document, each evaluation of
textcosts at most a constant c_t, apart from the work of (G2); - (G2) to make (G1) hold, a backend does work that adds up to at most c_p \hat{n} in a parse, such as decoding an input that is not valid UTF-8, or copying the texts that cross the pieces of a Document until it joins the pieces, and only in a parse that takes such a text;
- (G3) materializing a text value as a string of the host language is not part of the cost;
- (G4) comparing two strings costs at most c_t plus the length of the shorter operand;
- (G5) in a stream, each evaluation of
textcosts at most c_t plus the length of its result.
Two readings of the conditions. The copying reading is the definition
of a copying operation that counts taking the text of a node as a copy of its
range, and the refined reading is the definition of
Conditions for Linear Cost,
which does not. The two readings differ only in the operations that are
copying operations; the size of a value, and so what a value includes in the
sense of condition 4, is the same in both: the result of text has the size
of its range and includes what that range includes.
What the conditions bound. Under the conditions, the cost of a parse is bounded by bounding each part that Cost counts: rule bodies, examined input, iterations and applied operators, and the size of the values that actions and predicates build. A step of an action, a predicate or a binding that costs a constant, outside a scanning source, is part of the constant cost of the evaluation of the body that contains it: a body is a finite expression, and outside its scanning sources each of its parts is evaluated at most as many times as the upper bounds of the repetitions around it allow. A step inside a scanning source is charged to the iteration, applied operator or element of a list that evaluates it, and the conditions bound those. These are the local and scanned cost of the Linear Cost proof, which bounds them by its Lemma 1 and Lemma 4.
Lemma 1 (Text Is a Constant Step)
In a parse of a whole input or of a Document, the cost of all the
evaluations of text is at most c_t times their number plus c_p \hat{n},
and each evaluation is a step of constant cost of the evaluation that makes
it.
Proof. By (G1) each evaluation of text costs at most c_t besides the work
of (G2), which adds up to at most c_p \hat{n} in the parse. By (G3), a string that the caller later reads from a text value
is not part of the cost. An evaluation of text is a step of an action, a
predicate or a binding, made either outside the scanning sources of a body, or
inside one, in an iteration, an applied operator, or a lambda for one element
of a list, and so it is counted as the other constant steps there are. The
argument of text is a node, a string or nil
(text); text of a string returns it
unchanged and of nil returns "", which also cost a constant. \square
Lemma 2 (Refined Reading Is Sound)
If every rule that the start rule reaches satisfies conditions 1 to 5 in the
refined reading, then in a parse of a whole input or of a Document, the cost
is at most the bound that the conditions give in the copying reading for a
grammar in which every text is a constant step, plus c_p \hat{n}.
Proof. Compare the copying reading on the grammar in which every text is a
constant step, that is, an operation that is not a copying operation and
whose result has the size of the range. The two readings of this grammar and
the refined reading of the given grammar agree on every condition:
- Condition 1 reads bindings, captures and rule values, which do not depend on the reading.
- Condition 2 depends on the scanning sources. A copying operation is a
scanning source only when it has an operand not bounded in size by a
constant of the grammar; in the refined reading
textis not one, so it adds no scanning source, and every other source is the same in both. - Condition 3 depends on the scanning sources too, and so agrees.
- Condition 4 constrains the copying operations, by the sizes of their
operands. The copying operations other than
textare the same, and the sizes are the same, because the result oftexthas the size of its range in both: an operation that joins, compares, converts or measures the text of a capture of a recursion still copies a value that includes the value of a call on that recursion, and condition 4 rejects it. - Condition 5 does not mention values.
So the given grammar satisfies the conditions in the refined reading exactly
when the grammar with constant-step texts satisfies them in the copying
reading, and the bound that the conditions give applies to every part of the
cost of that grammar, where each text is a step of constant cost: part of
the local cost of Lemma 1 of Linear Cost
outside a scanning source, and of the activation that makes it inside one. By Lemma 1,
the cost of the given grammar differs from it only by the work of (G2), at most
c_p \hat{n}. \square
The promise of the class Linear, c \cdot \hat{n}, and of the class Linear Given an Environment Bound, c \cdot K \cdot (L + 1) \cdot \hat{n}, hold with c replaced by c + c_p, since K \ge 1 and L + 1 \ge 1.
Lemma 3 (Comparison Counts One Operand)
Counting a comparison of two strings as a copy of the operand whose size the classifier bounds better is sound.
Proof. By (G4) a comparison of strings a and b costs at most c_t + \min(|a|, |b|), which is at most c_t + |a| and at most c_t + |b|. Whichever operand the classifier counts, its size bounds the cost beyond the constant, which is a step of constant cost as in Lemma 1. A comparison with a literal costs at most c_t plus the length of the literal, a constant. \square
Lemma 4 (Streams)
In a stream, if every rule that the start rule reaches satisfies the
conditions in the refined reading, the cost is at most the bound of its class
plus the total length of the results of text.
Proof. By (G5) an evaluation of text in a stream costs at most c_t, a
step of constant cost as in Lemma 1, plus the length of its result. The
argument of Lemma 2, with (G5) in place of (G1) and no work of (G2), bounds
every part of the cost except these lengths, which add their total. \square
Theorem (Constant-Cost Text)
With the guarantee of Cost, the promises of the
classes Linear and Linear Given an Environment Bound of
Classification hold when the
classifier does not count taking the text of a node as a copying operation and
counts a comparison of strings as a copy of one operand: in a parse of a
whole input or of a Document as stated, and in a stream with the total length
of the results of text added.
Proof. Lemma 2 gives the bound for a whole input and a Document, Lemma 3 the counting of comparisons, and Lemma 4 the bound for a stream. \square
For a Document, the work of (G2) is the texts that cross two of its pieces: they are copied, and once the copies since an edit would reach the length of the document, its pieces are joined. The copies and the join cost at most twice the length of the document between two edits, so the cost of a parse after an edit includes at most that much, even when the parse reuses most of its earlier results; a parse that takes only short texts across the pieces pays only their lengths, and one that takes none pays nothing.