Tag. parsing
Notes (20)
Definition. Representable Grammars representable-grammar
For any string , we can define a representable grammar which matches exactly the string and nothing else. The parse trees for a representable grammar are proofs that the string is exactly equal to :
Cloudflare Parsing Error cloudflare-parsing-error
An error in the Cloudflare HTML parser would allow uninitialized memory to be dumped when there were imbalanced HTML tags.
This is indeed a case where a verified parser would have alleviated the issue.
Definition. First Set first-set
The first set () of a grammar are all the characters that may appear at the beginning of a word in the language of .
Definition. First Sets in Dependent Lambek Calculus first-set-in-dependent-lambek
The first set of a grammar may be captured in Lambek via the following proposition:
Or perhaps with ones of the grammars
Definition. FollowLast Set followlast-set
The followlast set () of a grammar are all the characters that may follow a word in the language of in a string that is in the language of .
Definition. FollowLast Sets in Dependent Lambek Calculus followlast-set-in-dependent-lambek
The followlast set of a grammar may be captured in Lambek via the following proposition:
Or perhaps with ones of the grammars
Definition. LL(1) Condition ll1-condition
A context-free grammar satisfies the LL(1) condition if it satisfies the following three conditions:
- All of its productions have pairwise disjoint first sets
- If a concatenation of nonterminals appears in a production, then has a disjoint followlast set from the first set of
- At most one production is nullable
This is essentially the type system of [1], which characterizes the LL(1) condition for context-free expressions.
Intutively, an LL(1) grammar can be parsed unambiguously, and without backtracking, by a predictive parser that only needs one token of lookahead.
Definition. Nullability in Dependent Lambek Calculus nullability-in-dependent-lambek
The nullability () of a grammar may be captured in Lambek via the following proposition:
Or perhaps with one of the grammars
Definition. Nullable Grammar nullable-grammar
A grammar is nullable if the empty string belongs to the language of .
Definition. Sequential Unambiguity sequential-unambiguity
Grammars and are sequentially unambiguous if the followlast set of is disjoint from the first set of .
We can understand this intuitively by characterizing the behavior of a left-to-right parser of . First it searches for a parse of , then upon finding a character that is not in it may begin trying search for .
That is, there is a unique boundary between the -parse and the -parse.
Definition. The Quotient and its Right Adjoint in Day Convolution day-quotient
Let be a small monoidal category. Recall that for presheaves , the Day convolution provides a closed monoidal structure:
which forms an adjunction .
For covariant functors and presheaves , we can define the quotient and its right adjoint, each of which is a presheaf on :
These form the adjunction .
Definition. Dependent Tensor of Grammars dependent-tensor
The tensor of grammars,
is simply typed, so cannot see what matched.
Just as we have the generalization from the pair type to the dependent pair , we can define a dependent tensor operation. It is a -like generalization over the ordinary tensor, in which the second grammar depends on a parse tree of the first.
Write for the type of parse trees of , each paired with the string it parses.
For a grammar and a family of grammars , the dependent tensor is:
We may also write it as .
When is a constant family, the dependent tensor reduces to the ordinary tensor .
Dependence runs left to right here, which fits left-to-right parsing. The other handedness, in which the first grammar depends on a parse of the second, is also definable.
Relation to Day Convolution
Just as the ordinary tensor is given by Day convolution, I think there is a similar dependent Day convolution for which this operation is an instance. My best guess is for any presheaf on a monoidal category and a functor from the category of elements of into presheaves on ,
Iβm not positive on this though, and I would hope to also extend this to enrichments that arenβt but I donβt see how that could make sense given that I have quantified over the element in the coend rather than using the tensor of the enriching category.
Definition. Formal Grammar formal-grammar
For an alphabet , let be the free monoid of strings over . A formal grammar is a family of types indexed by strings:
This definition views formal grammars directly as indexed families of types over strings (which equivalently form presheaves on the discrete category of strings). This view forms the central notion of the Dependent Lambek Calculus. For a given string , the type represents the type of all valid parse trees for according to the grammar . If the grammar cannot parse , then is the empty type.
Definition. The Derivative of a Grammar grammar-derivative
When a grammar quotient is taken with respect to a representable grammar (matching exactly the string ), it coincides with the residual , as established by the Quotient and Residual Coincidence.
This special case is known as the Brzozowski derivative of by the string , often written as . We have the following coincidence:
Definition. Later on Grammars grammar-later
Write when is a proper suffix of , that is, with . The later of a grammar is
A parse of over is a parse of over every proper suffix of . In particular is a singleton.
This is later on families for strings under the proper-suffix order. That order is well-founded because it strictly decreases length, so it is a thin direct category. There is at most one map , so the product over maps from the strict past has one factor per proper suffix. Guarded recursion is modelled by presheaves on , the topos of trees, and more generally by sheaves over a well-founded base [1]. Here the later acts on families, which is what grammars are, and there is no clock.
Later is the right adjoint of the proper-suffix derivative. Let be the grammar of non-empty strings. Then the derivative has the right adjoint
so . Splitting into its summands gives the form of that the calculus can define:
The component at says: if the string begins with , then the rest parses as .
The restriction to non-empty is what makes this a later. At the component is . Including it would give a projection , and LΓΆb would then prove every grammar. For the same reason the later is a product over suffixes. A sum such as is empty at , and at it is . The identity step would then give LΓΆb a proof of .
In the Agda this is β· in Grammar/Later/Base.agda, which is defined as the indexed conjunction of βl-string. The mirror image β·r, over proper prefixes, is defined in the same way. See also the bilateral later and the later along an arbitrary well-founded order.
Theorem. LΓΆb Induction for Grammars grammar-lob
For every grammar and every term , where is the later on grammars, there is a unique global parse with
Here restricts a global parse to every proper suffix.
The proof is recursion on the length of the string. At , the parses already built at the proper suffixes of form an element of , and turns it into a parse at . Uniqueness is LΓΆb for families over the proper-suffix order. In the Agda, lob in Grammar/Later/Base.agda is this recursion, done by well-founded induction on length.
To prove an entailment this way, apply LΓΆb to . The hypothesis is the induction hypothesis at every proper suffix. It becomes usable once a non-nullable grammar has been consumed. If , then
because a parse of over splits with non-empty, so . This is β·-app-NE in Grammar/Later/Properties.agda. Induction on a Kleene star is the standard use.
Theorem. Next on Grammars Is Presheaf Structure grammar-next-presheaf
For presheaves, restricts along the strict past, as in later on presheaves. A grammar is only a family over strings, so a map into the later on grammars is extra data. It sends a parse over to parses over every proper suffix of .
Let , so that . This is the comonad for the suffix order, and presheaves are comonadic over families. The counit law forces the first component of a coalgebra to be the identity. Hence:
- a presheaf on strings under the suffix order is the same as a grammar with a map that satisfies coassociativity. Restricting to and then to must agree with restricting to directly;
- for a proposition-valued grammar (a language), coassociativity is automatic, and exists exactly when the language is closed under suffixes. For example, has one, but does not, since is empty.
LΓΆb does not need on . The fixed-point equation only restricts a global parse , and a global parse can always be restricted. In the Agda, the grammar-level IsCoalgebra record, with only the field next, is in Grammar/Later/Coalgebra.agda on the guarded branch.
On presheaves the strict downset of is represented by , because every proper suffix of is a suffix of . So predecessors simplify later to . On grammars there is no such simplification, since the factors at different suffixes are unrelated.
Definition. Grammar Quotients grammar-quotients
For formal grammars and , the quotient of by is the grammar of what is left of once an has been read off the front:
A parse of the quotient consists of an -parses at prefix and a -parse of the full string .
This operation has a right adjoint:
Intuitively, parses if: for all splittings of into a prefix and suffix, if the prefix matches then the suffix must match .
Together, these form the adjunction:
This is an instance of the Day quotient over the discrete monoidal category of strings.
Definition. Grammar Residuals grammar-residual
For formal grammars and , the residual (sometimes called the lollipop or linear implication) is the right adjoint to the grammar tensor . It describes strings that, when prefixed by a string matching , will match .
Formally, it is defined as:
Intuitively, a parse of at a string is a function that takes any prefix string and a parse of in , and produces a parse of the full concatenated string in .
Definition. Tensor of Grammars grammar-tensor
For formal grammars and , their tensor represents the concatenation of the languages they describe. A parse for at a string consists of a splitting of into a prefix and suffix , along with a parse of in and a parse of in .
Formally, it is defined as:
This operation is exactly the Day convolution of and , where we view formal grammars as presheaves over the monoid of strings.
Talks and videos (2)
Intrinsic Verification of Parsers and Formal Grammar Theory in Dependent Lambek Calculus pldi-2025-talk
We present Dependent Lambek Calculus, a domain-specific dependent type theory for verified parsing and formal grammar theory. In Dependent Lambek Calculus, linear types are used as a syntax for formal grammars, and parsers can be written as linear terms. The linear typing restriction provides a form of intrinsic verification that a parser yields only valid parse trees for the input string. We demonstrate the expressivity of this system by showing that the combination of inductive linear types and dependency on non-linear data can be used to encode commonly used grammar formalisms such as regular and context-free grammars as well as traces of various types of automata. Using these encodings, we define parsers for regular expressions using deterministic automata, as well as examples of verified parsers of context-free grammars.
We present a denotational semantics of our type theory that interprets the types as a mathematical notion of formal grammars. Based on this denotational semantics, we have made a prototype implementation of Dependent Lambek Calculus using a shallow embedding in the Agda proof assistant. All of our examples parsers have been implemented in this prototype implementation.
Intrinsic Verification of Parsers and Formal Grammar Theory in Dependent Lambek Calculus mwpls-2024-talk
We present Dependent Lambek Calculus, a domain-specific dependent type theory for verified parsing and formal grammar theory. In Dependent Lambek Calculus, linear types are used as a syntax for formal grammars, and parsers can be written as linear terms. The linear typing restriction provides a form of intrinsic verification that a parser yields only valid parse trees for the input string. We demonstrate the expressivity of this system by showing that the combination of inductive linear types and dependency on non-linear data can be used to encode commonly used grammar formalisms such as regular and context-free grammars as well as traces of various types of automata. Using these encodings, we define parsers for regular expressions using deterministic automata, as well as examples of verified parsers of context-free grammars.
We present a denotational semantics of our type theory that interprets the types as a mathematical notion of formal grammars. Based on this denotational semantics, we have made a prototype implementation of Dependent Lambek Calculus using a shallow embedding in the Agda proof assistant. All of our examples parsers have been implemented in this prototype implementation.
References (56)
Syntactic Completions with Material Obligations moon-2025-syntactic
Intrinsic Verification of Parsers and Formal Grammar Theory in Dependent Lambek Calculus intrinsic-verification-of-parsers
We present Dependent Lambek Calculus (Lambek), a domain-specific dependent type theory for verified parsing and formal grammar theory. In Lambek, linear types are used as a syntax for formal grammars, and parsers can be written as linear terms. The linear typing restriction provides a form of intrinsic verification that a parser yields only valid parse trees for the input string. We demonstrate the expressivity of this system by showing that the combination of inductive linear types and dependency on non-linear data can be used to encode commonly used grammar formalisms such as regular and context-free grammars as well as traces of various types of automata. Using these encodings, we define parsers for regular expressions using deterministic automata, as well as examples of verified parsers of context-free grammars.
We present a denotational semantics of our type theory that interprets the linear types as functions from strings to sets of abstract parse trees and terms as parse transformers. Based on this denotational semantics, we have made a prototype implementation of Lambek using a shallow embedding in the Agda proof assistant. All of our examples parsers have been implemented in this prototype implementation.
The categorical contours of the Chomsky-SchΓΌtzenberger representation theorem mellies-2025-the
ACGtk: A toolkit for developing and running abstract categorial grammars Guillaume2024
Curbing the Vulnerable Parser: Graded Modal Guardrails for Secure Input Handling bond-2023-curbing
Saggitarius: A DSL for Specifying Grammatical Domains miltner-2023-saggitarius
Coqlex: Generating formally verified lexers Ouedraogo_2023
A compiler consists of a sequence of phases going from lexical analysis to code generation. Ideally, the formal verification of a compiler should include the formal verification of each component of the tool-chain. An example is the CompCert project, a formally verified C compiler, that comes with associated tools and proofs that allow to formally verify most of those components.
However, some components, in particular the lexer, remain unverified. In fact, the lexer of Compcert is generated using OCamllex, a lex-like OCaml lexer generator that produces lexers from a set of regular expressions with associated semantic actions. Even though there exist various approaches, like CakeML or Verbatim++, to write verified lexers, they all have only limited practical applicability.
In order to contribute to the end-to-end verification of compilers, we implemented a generator of verified lexers whose usage is similar to OCamllex. Our software, called Coqlex, reads a lexer specification and generates a lexer equipped with a Coq proof of its correctness. It provides a formally verified implementation of most features of standard, unverified lexer generators.
The conclusions of our work are two-fold: Firstly, verified lexers gain to follow a user experience similar to lex/flex or OCamllex, with a domain-specific syntax to write lexers comfortably. This introduces a small gap between the written artifact and the verified lexer, but our design minimizes this gap and makes it practical to review the generated lexer. The user remains able to prove further properties of their lexer. Secondly, it is possible to combine simplicity and decent performance. Our implementation approach that uses Brzozowski derivatives is noticeably simpler than the previous work in Verbatim++ that tries to generate a deterministic finite automaton (DFA) ahead of time, and it is also noticeably faster thanks to careful design choices.
We wrote several example lexers that suggest that the convenience of using Coqlex is close to that of standard verified generators, in particular, OCamllex. We used Coqlex in an industrial project to implement a verified lexer of Ada. This lexer is part of a tool to optimize safety-critical programs, some of which are very large. This experience confirmed that Coqlex is usable in practice, and in particular that its performance is good enough. Finally, we performed detailed performance comparisons between Coqlex, OCamllex, and Verbatim++. Verbatim++ is the state-of-the-art tool for verified lexers in Coq, and the performance of its lexer was carefully optimized in previous work by Egolf and al. (2022). Our results suggest that Coqlex is two orders of magnitude slower than OCamllex, but two orders of magnitude faster than Verbatim++.
Verified compilers and other language-processing tools are becoming important tools for safety-critical or security-critical applications. They provide trust and replace more costly approaches to certification, such as manually reading the generated code. Verified lexers are a missing piece in several Coq-based verified compilers today. Coqlex comes with safety guarantees, and thus shows that it is possible to build formally verified front-ends.
flap: A Deterministic Parser with Fused Lexing yallop-2023-flap
Interval Parsing Grammars for File Format Parsing zhangIntervalParsingGrammars2023
Verified ALL(*) Parsing with Semantic Actions and Dynamic Input Validation lasserCoStar2023
Verbatim++: verified, optimized, and semantically rich lexing with derivatives egolf-2022-verbatim
Parsing as a lifting problem and the Chomsky-SchΓΌtzenberger representation theorem mellis_zeilberger_2022
We begin by explaining how any context-free grammar encodes a functor of operads from a freely generated operad into a certain βoperad of spliced wordsβ. This motivates a more general notion of CFG over any category , defined as a finite species equipped with a color denoting the start symbol and a functor of operads into the operad of spliced arrows in . We show that many standard properties of CFGs can be formulated within this framework, and that usual closure properties of CF languages generalize to CF languages of arrows. We also discuss a dual fibrational perspective on the functor via the notion of βdisplayedβ operad, corresponding to a lax functor of operads .
We then turn to the Chomsky-SchΓΌtzenberger Representation Theorem. We describe how a non-deterministic finite state automaton can be seen as a category equipped with a pair of objects denoting initial and accepting states and a functor of categories satisfying the unique lifting of factorizations property and the finite fiber property. Then, we explain how to extend this notion of automaton to functors of operads, which generalize tree automata, allowing us to lift an automaton over a category to an automaton over its operad of spliced arrows. We show that every CFG over a category can be pulled back along a ND finite state automaton over the same category, and hence that CF languages are closed under intersection with regular languages. The last important ingredient is the identification of a left adjoint to the operad of spliced arrows functor, building the βcontour categoryβ of an operad. Using this, we generalize the C-S representation theorem, proving that any context-free language of arrows over a category is the functorial image of the intersection of a -chromatic tree contour language and a regular language.
Technical Report: Match-reference regular expressions and lenses musca-2022-technical
Symbolic and automatic differentiation of languages elliottSymbolicAutomaticDifferentiation2021
CoStar: A verified ALL(*) parser lasserCoStarVerifiedALL2021
Verbatim: A verified lexer generator egolfVerbatim
Zippy LL(1) parsing with derivatives EdelmannZippy2020
A typed, algebraic approach to parsing krishnaswami_typed_2019
Self-certifying Railroad Diagrams: Or: How to Teach Nondeterministic Finite Automata hinze-2019-self
A Verified LL(1) Parser Generator lasserLL1_2019
Reasonably programmable literal notation omar-2018-reasonably
agdarsec β total parser combinators allais_2018
Certified Normalization of Context-Free Grammars firsovCertifiedNormalizationContextFree2015
Adaptive LL(*) parsing: the power of dynamic analysis parr-2014-adaptive
Algebra-coalgebra duality in brzozowskiβs minimization algorithm bonchi-2014-algebra
Safely Composable Type-Specific Languages omar-2014-safely
Infinitary Axiomatization of the Equational Theory of Context-Free Languages grathwohl_infinitary_2013
The semantics of parsing with semantic actions atkey_2012
Brzozowskiβs Algorithm (Co)Algebraically bonchi-2012-brzozowski
Validating LR(1) Parsers jourdanValidatingLRParsers2012
Parsing with derivatives: A functional pearl mightParsingDerivativesFunctional2011
We present a functional approach to parsing unrestricted context-free grammars based on Brzozowskiβs derivative of regular expressions. If we consider context-free grammars as recursive regular expressions, Brzozowskiβs equational theory extends without modification to context-free grammars (and it generalizes to parser combinators). The supporting actors in this story are three concepts familiar to functional programmers - laziness, memoization and fixed points; these allow Brzozowskiβs original equations to be transliterated into purely functional code in about 30 lines spread over three functions.
Yet, this almost impossibly brief implementation has a drawback: its performance is sour - in both theory and practice. The culprit? Each derivative can double the size of a grammar, and with it, the cost of the next derivative.
Fortunately, much of the new structure inflicted by the derivative is either dead on arrival, or it dies after the very next derivative. To eliminate it, we once again exploit laziness and memoization to transliterate an equational theory that prunes such debris into working code. Thanks to this compaction, parsing times become reasonable in practice.
We equip the functional programmer with two equational theories that, when combined, make for an abbreviated understanding and implementation of a system for parsing context-free languages.
LL(*): the foundation of the ANTLR parser generator parr-2011-ll
Regular expression containment: Coinductive axiomatization and computational interpretation henglein_regular_2011
Grammatical framework: Programming with multilingual grammars ranta-2011
Context-Free Languages, Coalgebraically winterCFL
Total parser combinators danielssonTotalParserCombinators2010
A monadic parser combinator library which guarantees termination of parsing, while still allowing many forms of left recursion, is described. The libraryβs interface is similar to those of many other parser combinator libraries, with two important differences: one is that the interface clearly specifies which parts of the constructed parsers may be infinite, and which parts have to be finite, using dependent types and a combination of induction and coinduction; and the other is that the parser type is unusually informative.
The library comes with a formal semantics, using which it is proved that the parser combinators are as expressive as possible. The implementation is supported by a machine-checked correctness proof.