Ready-Made Parsers
Parsers for common languages, written in PEGO and generated into Go with pego gen. Each is a Go module of its own
that depends only on the standard library and the PEGO runtime (github.com/ornew/pego/runtime): import it and parse, with nothing to generate or compile at run time.
| Language | Module | Specification | Checked against |
|---|---|---|---|
| CEL | github.com/ornew/pego/parsers/cel |
The CEL language definition, as cel-go parses it | All 2,527 conformance tests of cel-spec; cel-go v0.32.0 (trees, offsets and literal values on 32,794 expressions; fuzz tests) |
| CSV | github.com/ornew/pego/parsers/csv |
RFC 4180, with the leniencies of encoding/csv |
73 edge cases, encoding/csv (differential and fuzz tests) |
| CUE | github.com/ornew/pego/parsers/cue |
The CUE Language Specification, as cue/parser v0.17.1 parses it |
cue/parser: 4,061 sources of the CUE repository, 32,488 mutants, 15,000 generated inputs and 4,126 literals (trees, offsets and comments; no difference); fuzz tests |
| DuckDB SQL | github.com/ornew/pego/parsers/duckdb |
DuckDB 1.5.6's SQL dialect | DuckDB 1.5.6 on 158,605 texts (acceptance, statement splitting and the AST of SELECT statements; 13 known deviations) |
| Go | github.com/ornew/pego/parsers/golang |
The Go Programming Language Specification (go1.27), as go/parser parses it; ParseFile returns go/ast |
go/parser: every file of GOROOT/src (whole trees, positions included), the programs embedded in its tests, mutations and fuzz tests (no difference) |
| JSON | github.com/ornew/pego/parsers/json |
RFC 8259 | JSONTestSuite (every y_ and n_ case), encoding/json (differential and fuzz tests) |
| Python | github.com/ornew/pego/parsers/python |
Python 3.14, as CPython 3.14.0 parses it | CPython's ast.dump, positions included, on the standard library, Lib/test and its 61,540 code snippets (no difference); mutation and fuzz tests |
| TypeScript | github.com/ornew/pego/parsers/typescript |
TypeScript 5.9 and TSX, as the TypeScript 5.9.3 compiler parses them | The compiler's trees on its own test cases (14,799 of 14,804 files agree), its lib declaration files and mutated sources |
| XML | github.com/ornew/pego/parsers/xml |
XML 1.0 (Fifth Edition), non-validating, with Namespaces in XML 1.0 | W3C XML Conformance Test Suite (no failure among the XML 1.0 tests that need no external entity), encoding/xml (differential and fuzz tests) |
| YAML | github.com/ornew/pego/parsers/yaml |
YAML 1.2.2, with the core schema for Go values | yaml-test-suite (all 402 tests: events and JSON values) |
Install
Until PEGO publishes a release, the ready-made parser modules depend on the github.com/ornew/pego module through a
local replace directive (replace github.com/ornew/pego => ../.. in each parser's go.mod). That directive only
applies inside the repository, so go get github.com/ornew/pego/parsers/json does not work from another module. Use a
parser from a checkout of the repository, in one of two ways.
With a go.work file next to your module's go.mod:
go work init .
go work use ~/src/pego ~/src/pego/parsers/json
or with replace directives in your own go.mod, which the go.mod of the parser cannot supply for you:
require github.com/ornew/pego/parsers/json v0.0.0
replace github.com/ornew/pego/parsers/json => /path/to/pego/parsers/json
replace github.com/ornew/pego => /path/to/pego
(/path/to/pego is the full path of your checkout; go.mod does not expand ~.) Run go mod tidy afterwards to record the requirement of the github.com/ornew/pego module.
import "github.com/ornew/pego/parsers/json"
v, err := json.Decode(`{"name": "pego", "tags": ["peg", "operators-rule"]}`) // map[string]any{...}
ast, err := json.ParseAST(src) // typed values with positions
Every parser has the API of a parser generated with pego gen -types -recognize (see
code generation), plus functions written for its language:
ParseAST(input, opts...) |
The document as the Go types the grammar declares, each with its Span in the input |
Parse(input, opts...) |
The document as a tree of *Node, as the engine returns it |
Recognize(input, opts...) |
Only checks the input, without building anything |
*SyntaxError |
The position (Line, Col, Pos) and the expected tokens of a syntax error |
Positions are in code points by default; pass Bytes for byte offsets.
Layout
Each directory holds:
| File | Contents |
|---|---|
<language>.pego |
The grammar. It can be used with the engine too (pego.CompileSource), for streaming, incremental parsing or the pego tools. |
parser.go, api.go, types/types.go |
The parser generated from the grammar, the names it re-exports from the runtime, and the Go types of the grammar (the package types). The parser imports the runtime package github.com/ornew/pego/runtime (generated with -runtime import). Do not edit them. |
other .go files |
Code written for the language: documentation, conversions to Go values, helpers. Those in types/ hold the methods of the types of the grammar (a method can only be declared in the package of its type); what needs the parser or the decoder is a function of the module instead. |
*_test.go |
Tests against the language's specification, conformance suites and reference implementations; examples; benchmarks |
testdata/*.txt, *.golden |
Inputs and the expected trees and errors, checked on the generated parser here and on every backend of the engine by parsers_test.go |
go.mod, LICENCE |
The module, which requires github.com/ornew/pego for the runtime |
Development
go generate ./parsers # regenerate every parser (after changing a grammar, the runtime or the generator)
go test ./parsers # generated files up to date; golden files on every backend of the engine
go test ./parsers -update # rewrite the golden files from the engine
parsers/test.sh # both, and the tests of every module (fetches the test corpora first)
cd parsers/json && go test ./... # the tests of one module
The generation commands are the go:generate lines of generate.go; the up-to-date test reads them, so a
new parser needs only a new line there. The third-party corpora of the tests are fetched, not stored here (see
development); a test whose corpus is not fetched is skipped with the command to run. The modules are not part of the main module's go test ./...: run
parsers/test.sh after changing the engine or the generator.