PEGO Cookbook
Short recipes for concrete problems. Each one is a complete solution: the problem in a sentence or two, the grammar and the Go program, the output they print, and a few lines on how it works and what to change. They differ from the other documents in how they are organized:
- The tutorial teaches the language from the first rule on.
- The guides explain one feature at a time, in depth.
- The cookbook starts from a task (read a configuration file, report three errors at once, reparse on every keystroke) and combines the features that the task needs.
Running a recipe
Every program is a main package that you can run as it is. Put the files in a directory (a block whose first line is
// name.go or // name.pego is a file of that name, without that line), make it a module that uses PEGO, and run it:
mkdir recipe && cd recipe
go mod init example.com/recipe
go get github.com/ornew/pego
go run .
The recipes need Go 1.27 or later and nothing else, except where a recipe says otherwise (the ones that generate code
install the pego tool with go get -tool, and the one about ready-made parsers adds a module). The grammars are
embedded in the programs with go:embed, so the .pego files are real files that pego fmt, pego parse and the
editor support work with. Every output was produced by running the code shown, with Go 1.27.1 on an Apple M3 Max;
times differ from machine to machine.
Read data
| Recipe | What it shows |
|---|---|
| Read a configuration file into Go structs | A grammar for key = value lines with typed values, and Go code that fills a struct and reports the line of a wrong value |
| Parse log lines fast | A generated parser with typed values (ParseAST) and Recognize; what each costs on 100,000 lines |
| Process a file that does not fit in memory | #stream and ParseStream: records one at a time, in 17 MiB for 5 million lines |
| Parse indentation-based input | Nested entries as nested Go maps, with a variable for the indentation and an error for inconsistent indentation |
Evaluate and query
| Recipe | What it shows |
|---|---|
| Evaluate arithmetic with variables and functions | A Pratt expression with precedence, associativity and calls, and an evaluator that runs the same tree for many inputs |
| Compile a filter language into a Go predicate | age > 30 and name ~ "a*" as closures, with word operators that do not collide with field names |
Report problems
| Recipe | What it shows |
|---|---|
| Report an error with its source line and a caret | #error messages and the position of a *pego.SyntaxError, printed like a compiler |
| Report several errors in one run | #recover: a tree of what could be read, the errors, and what to watch for in the skip |
Build tools
| Recipe | What it shows |
|---|---|
| Tokenize source for syntax highlighting | A tokenizer that cannot fail, and HTML spans from the flat tree |
| Reparse a document on every keystroke | Document, Edit and Stats; a grammar shaped so that edits reuse most of the last parse |
Ship, reuse and test
| Recipe | What it shows |
|---|---|
| Ship a parser and keep it up to date | pego gen with go generate, a test that fails when the generated file is stale, and .pegoc for grammars that stay data |
| Validate a YAML file and point at the problem | A ready-made parser of parsers/: syntax errors with positions, and your own checks with the positions of the typed tree |
| Test hand-written code against a grammar | Inputs and near misses generated from the grammar, a differential test and a fuzz test |
Where to go next
| To learn about | Read |
|---|---|
| The grammar language, from the beginning | Getting started |
| One feature in depth | Guides |
| The exact rules of a construct | Language specification |
| Complete grammars with tests | examples/ and parsers/ |