ziglang/zig
260
5.9k
Fork
You've already forked zig
765

Make std.zig.Ast.parse() and grammar.peg finally agree #36094

Merged
andrewrk merged 52 commits from ifreund/zig:parser-oracle into master 2026年07月08日 21:47:03 +02:00
Member
Copy link

It turns out that our formal grammar.peg and the actual language implementation did not agree in many places. Probably, the formal grammar has never actually 100% matched the actual handwritten tokenizer and parser.

This branch is the result of my quest to fix this problem and unblock future grammar changes and language specification work.

At a high level, the approach I took was to write a tool that accepts our grammar.peg as input and outputs a simple recursive descent parser. This generated parser is then used as an oracle for fuzz testing and the handwritten std.zig.Ast.parse() is compared against it. This approach ensures a single source of truth and allows for easy iteration as the grammar changes.

I put effort into the commit messages, they contain many more details than can be found in this cover letter.

Here are some of the highlights:

The only user-facing changes to the language implementation made by this branch are that a handful of errors that are currently Parser errors became AstGen errors instead:

The integrated fuzzer was useful early on in this branch, but the bulk of the fuzzing work was done using AFL++. My setup for running AFL++ can be found here: https://codeberg.org/ifreund/zig-parser-afl

At the time of opening this pull request, 9 parallel AFL++ instances ran for over 17 hours without finding any crashes (for example, because my assertion that the handwritten parser matches the behavior of the oracle failed) or hangs (generally indicating that the grammar wasn't LL(k)).

A lot of the time I spend on this branch went into making the handwritten parser implementation more fuzzable. For example, AFL++ proved very competent at triggering stack overflow by adding a million open parentheses somewhere in the input. This is however not an interesting fuzzing result and we don't want the fuzzer to waste time working towards such results. To fix this, several steps were necessary:

  1. The oracle generating tool was tweaked to enforce a "max depth" for loops and recursion (775dac9149)
  2. A feature was added to the handwritten parser to allow disabling recovery (62720ad9f9, 3e45baa60a)
  3. The handwritten parser was tweaked in several places to ensure an error was returned as soon as possible before parsing sub-expressions that occur after the error (e.g. 203e827953 or 010a98dbfc)

These improvements are in no way AFL-specific and will make all future fuzzing work more fruitful :)

It turns out that our formal grammar.peg and the actual language implementation did not agree in many places. Probably, the formal grammar has never actually 100% matched the actual handwritten tokenizer and parser. This branch is the result of my quest to fix this problem and unblock future grammar changes and language specification work. At a high level, the approach I took was to write a tool that accepts our grammar.peg as input and outputs a simple recursive descent parser. This generated parser is then used as an oracle for fuzz testing and the handwritten `std.zig.Ast.parse()` is compared against it. This approach ensures a single source of truth and allows for easy iteration as the grammar changes. I put effort into the commit messages, they contain many more details than can be found in this cover letter. Here are some of the highlights: - 20a2485061b9c480d1df82f8fef2bec13a23e74a - 9953d7edca95ddd6ee0a517f33fa8f390cfe04c8 The only user-facing changes to the language implementation made by this branch are that a handful of errors that are currently Parser errors became AstGen errors instead: - e21ced91e30d8bc943ebe0a1f1f6d3bc6821740e - 3681c7c506829322a2980d5bd98e493968fdea68 The integrated fuzzer was useful early on in this branch, but the bulk of the fuzzing work was done using AFL++. My setup for running AFL++ can be found here: https://codeberg.org/ifreund/zig-parser-afl At the time of opening this pull request, 9 parallel AFL++ instances ran for over 17 hours without finding any crashes (for example, because my assertion that the handwritten parser matches the behavior of the oracle failed) or hangs (generally indicating that the grammar wasn't LL(k)). A lot of the time I spend on this branch went into making the handwritten parser implementation more fuzzable. For example, AFL++ proved very competent at triggering stack overflow by adding a million open parentheses somewhere in the input. This is however not an interesting fuzzing result and we don't want the fuzzer to waste time working towards such results. To fix this, several steps were necessary: 1. The oracle generating tool was tweaked to enforce a "max depth" for loops and recursion (775dac91494ed602061ce4a28e7da8d64a0bd18a) 2. A feature was added to the handwritten parser to allow disabling recovery (62720ad9f9e65dd8c62579c90142cb043d60b01c, 3e45baa60adbb041bf75af4cde380abb3b05abfb) 3. The handwritten parser was tweaked in several places to ensure an error was returned as soon as possible before parsing sub-expressions that occur after the error (e.g. 203e8279539220db84823bb79671c5c6c7d1065f or 010a98dbfce6f42ae12fda09060e37748e58dc2d) These improvements are in no way AFL-specific and will make all future fuzzing work more fruitful :)
This improves the developer experience, especially with the new
gen_parser_oracle tool. My intent is for doc/langref/grammar.peg
to be the single source of truth, at least until we have an actual
language spec.
The separate copy in the separate zig-spec repo should not be considered
canonical as it is not tested against by CI.
This script parses a PEG grammar definition and generates a simple
recursive descent parser that recognizes that grammar.
The intent is to use this tool to generate an oracle against which
std.zig.Ast.parse() can be fuzz tested.
Unfortunately, generating a "smith" that can produce all possible valid
source code according to the PEG grammar definition does not seem
feasible due to PEG semantics. In particular, modeling the ordered
choice operator ('/') with a smith is problematic and seems to have
worst-case exponential runtime. Consider that `A / B` is equivalent to
`A / !A B`, it is not sufficient for a smith to choose an option from
the ordered choice at random and generate an input matched by that
sub-expression.
The current handwritten AstSmith.zig implementation does not match the
exact semantics of the PEG grammar. It has some hacks (see the `not_*`
variables) to work around specific instances of the general problem
with ordered choice described above but that is not an acceptable
long term solution in my opinion.
Generating the oracle for the fuzz test automatically from the PEG
makes the oracle correct by construction and gives us a single source of
truth: the PEG definition in the language spec.
(currently broken/failing)
The tokenizer does not yet perform UTF-8 validation. This violates the
language spec, but fixing it is out of scope for this branch. Leave
the intended language spec commented out in the grammar to be restored
when the tokenizer is fixed.
The tokenizer currently handles termination of comments/multiline string
literal lines differently from the grammar. The tokenizer forbids
e.g. tab characters at the end of comments before a newline and requires
\r to be directly followed by \n.
The tokenizer behavior here is intended, see c2b8afcac9.
The grammar needs to be fixed to match Parse.zig's "operator has
whitespace on one side but not the other" error, which is implemented
in Parse.zig using a constant lookbehind of 1.
However, standard PEG does not support lookbehind, which means our
approach to handling whitespace needs to be reworked.
Moving the `skip` non-terminal to be processed before each "token"
in the grammar rather than afterwards makes it possible to cleanly
match the Parse.zig operator whitespace handling, which will be
implemented in the next commit.
This commit is purely a refactor, no functional changes are intended.
Parse.zig requires whitespace to be either immediately before and after
a binary operator or neither before nor after the operator.
/// should not be parsed as a division operator followed by a comment
if it appears in a context where a division operator is accepted.
Add the missing negative lookahead to the SLASH token.
This matches the Parse.zig implementation, which has a special parse
error for this case:
> ambiguous use of '&&'; use 'and' for logical AND, or change whitespace
> to ' & &' for bitwise AND
This matches the behavior of Parse.zig
Original motivation: 95b95ea33e 
Currently the grammar fails to enforce matching whitespace or lack of
whitespace around operators that are immediately preceded by a multiline
string literal and terminating newline.
Currently Parse.zig gives a parse error when the number of for loop
inputs does not match the number of for loop captures. This property
is however both overly complex to specify in the formal grammar and not
necessary to make further parsing possible.
This eliminates yet another discrepancy between the formal grammar
and Parse.zig implementation that has been discovered through fuzzing
with AFL++.
Commit 785fb1be11 made many redundant
changes to the grammar due to insufficient understanding of PEG
semantics. This commit reverts the most obviously redundant of those
changes.
The unbounded lookahead through e.g. !ExprSuffix still needs to be
reverted, but I want to do that in a future commit since that change
can't be reasoned about locally.
This unbounded lookahead is causing discrepancies between the Parse.zig
implementation and the PEG grammar. Also, unbounded lookahead should
never have been added to the PEG grammar in the first place.
It was added in 785fb1be11 which
demonstrated insufficient understanding of PEG semantics through many
redundant additions.
Whatever problem this unbounded lookahead attempted to solve needs to be
solved differently in any case.
This commit adds one test case found by AFL++ that fails before this
commit and now passes.
My attempt to handle this case in 6f151109b5fdf88eb8b has proven
insufficient, the test case added by this commit was failing.
Solve this with a "start of file" non-terminal in the PEG grammar,
which unfortunately isn't portable but much better reflects the actual
implementation and is much simpler.
It is not clear why this lookahead was added in the first place, but
it does not reflect the behavior of the Parse.zig implementation as
demonstrated with the new test case.
This is a first pass at consistency with Parse.zig on the statement
level, adding constant lookaheads to the grammar in several places
to match the behavior of Parse.zig.
This is a first pass at consistency with Parse.zig at the expression
level, adding constant lookaheads to the grammar in several places
to match the behavior of Parse.zig.
I also updated the comments in Parse.zig and refactored for clarity,
adding assertions in a few places but not intending any change in
behavior.
This commit also adds comments to the grammar and Parse.zig explaining
what needs to be done in practice to ensure that the grammar is LL(k)
and that the parser has worst-case linear runtime.
This is necessary to match the behavior of the parser. This is not a
complete list of of prefixes that cause the PEG to differ in behavior
from the parser, it is however difficult to determine this list by
reading the grammar alone and I plan to let the AFL++ fuzzer find
the missing items and fill it in while adding test cases to prevent
regression.
Eliminate unbounded lookahead, match Parse.zig behavior
Currently the grammar only allows exactly one pointer modifier order but
the Parse.zig implementation allows any order. However, the current
Parse.zig behavior of allowing any order while forbidding duplicate
modifiers would require a combinatorial explosion of grammar rules to
specify (currently 5! i.e. 120).
The simplest, most permissive grammar would remove the ordering
requirement and allow duplicate pointer modifiers. However, this would
unfortunately require a more complex AST data layout due to the child
nodes of align() and addrspace() modifiers. Since these are the only
pointer modifiers with child nodes and 2! is a perfectly reasonable
number, forbid duplicate align() and addrspace() modifiers to keep the
Ast data structure simple. In order to resolve the difference between
the formal grammar and parser implementation, allow duplicate
single-token modifiers (allowzero, const, volatile) in the grammar and
move the compile error for that case to AstGen.
Note that zig fmt will now silently remove duplicate single-token
modifiers, which I think is a nice little UX improvement.
This is useful to avoid unbounded recursion/iteration while fuzzing.
It's not interesting to learn that the parser hits a stack overflow when
fed a million open parens for example.
This now matches the behavior of Parse.zig
This is necessary for fuzz testing.
Consider the case where there is a parse error right at the beginning of
the file, followed by a valid declaration with a million nested parens.
The oracle will not skip this input due to the max depth being exceeded
since the oracle hits a parse error right away and does no recovery.
However, std.zig.Ast.parse() does recovery by default and will hit a
stack overflow rather than returning after the parser error.
Stack overflows are not interesting and we do not want the fuzzer to be
able to find them.
The tokenizer allows the unicode byte order mark (U+FEFF) to be present
at the start of the file, but the grammar currently does not.
Fixing the grammar requires some care due to how same-line doc comments
are forbidden in the grammar.
This is a case in which the grammar is currently not LL(k) and needs a
negative lookahead to prevent backtracking.
The new grammar is consistent with the Parse.zig implementation.
See the new test case for an example.
Currently the grammar doesn't forbid chained compare ops, see the new
test case which now passes.
The previous attempt to disable recovery was incomplete, consider for
example the recovery done when parsing an init list with a missing comma
.{a, b c}
The parser will currently add a warning about the missing comma and
continue parsing, which means that the fuzzer can hit stack overflows
.{a, b (((((((((((((((((((((((((((((((((((((((((((((((((((((((...
To fix this in general, make the warn functions return ParseError when
recovery is disabled.
Currently in a special case the parser will keep parsing after it has
been determined that there is a parse error in order to give a more
user-friendly error message.
However, this opens the parser up to stack overflow when fuzzing,
so skip the extra parsing and potentially better error message when
recovery is disabled.
To prevent the fuzzer from being able to reach stack overflows, we
need to give an error for invalid field/decl ordering before attempting
to parse the next field.
Currently the fuzzer is able to hit a stack overflow due to an invalid
bit align on a pointer type that is not a single item pointer:
[]align(a:(((((((((((((((((((((((((((((((((((((((...
To fix this, warn (and return error.ParseError if recovery is disabled)
before parsing the invalid bit align expression.
To prevent the fuzzer from being able to reach stack overflows, we
need to give an error for non-final varargs (...) before parsing the
next argument.
Currently the grammar doesn't function as intended and forbids
addrspace followed by align. Add the required negative lookaheads
to fix this as well as a test case.
Consider the new test case (found by AFL++):
test{for(0)|t|0,const w=0;}
Currently the grammar backtracks after failing to parse this with the
ForStatement rule and instead finds that the VarAssignStatement rule
is a match. This behavior is not LL(k) and inconsistent with the parser.
Add the required negative lookahead to eliminate this case and similar
cases.
No change in semantics intended
AFL++ is able to identify "hangs" as well as crashes and has found
several small inputs that take multiple seconds for the generated parser
to parse. This is because our PEG is not yet LL(k) despite recognizing
the same language as our handwritten LL(k) recursive descent parser.
Consider the PEG semantics for the following non-terminal:
ParamDeclList <- (ParamDecl COMMA)* (ParamDecl / DOT3 COMMA?)?
Here, the PEG checks twice if the last ParamDecl matches when
there is no trailing comma. Now, consider that the ParamDecl may
recursively contain a nested ParamDeclList, which in turn has ParamDecls
that contain further nested ParamDeclLists. It should be clear that this
results in worst-case exponential runtime.
This can be avoided by defining ParamDeclList using recursion instead of
the * operator.
This same pattern likely needs to be applied to other instances of this
pattern in the grammar.
The main motivation for fixing this is to improve fuzzer performance.
Additionally, using recursion rather than the * operator makes it easier
to translate from a PEG to a CFG, which I'm quite confident we will want
to do for the language specification eventually. A CFG would also allow
for smith-based fuzz testing to complement the oracle-based approach.
More rules are being made recursive for efficiency reasons, see the
previous commit.
For in depth reasoning, see commit 296b39c323
(grammar: fix ParamDeclList worst-case exponential time)
Currently these definitions do not result in an LL(k) generated parser.
For in depth reasoning, see commit 296b39c323
(grammar: fix ParamDeclList worst-case exponential time)
The current AstSmith is hand-written based on the formal PEG. However,
there is a significant impedance mismatch here since PEGs are a parser
specification not a language specification like CFGs. In other words,
it is not possible to directly translate an PEG into code that
efficiently generates all possible inputs recognized by the PEG.
Requirements for a new AstSmith:
1. Must be automatically generated based on the formal grammar
 specification.
2. Must have linear runtime.
The current AstSmith is handwritten and unfortunately does not exactly
match the formal grammar. Tests like this need to have a single source
of truth and also need to be maintainable so I consider automatic
generation non-negotiable.
I did attempt to write a tool that takes a PEG as input and outputs an
AstSmith implementation. However, I no longer believe it is possible
to do a direct translation from an arbitrary PEG to an efficient
AstSmith, the lookahead and ordered choice features have worst-case
exponential runtime.
Conceptually, PEGs are simple to translate into parsers while CFGs
are simple to translate in to generators or smiths. I believe the
path forward is to translate our PEG into a CFG and generate a smith
based on that. I consider that task out of scope for this branch though.
This is a much cleaner way to expose the new option to disable recovery
added in 62720ad9f9. It also makes it possible to add further
options in the future without further breaking changes.
build: check if parser oracle must be regenerated
All checks were successful
ci / x86_64-freebsd-release (pull_request) Successful in 58m4s
ci / x86_64-freebsd-debug (pull_request) Successful in 58m26s
ci / x86_64-netbsd-release (pull_request) Successful in 59m2s
ci / x86_64-openbsd-release (pull_request) Successful in 1h5m56s
ci / x86_64-netbsd-debug (pull_request) Successful in 1h10m32s
ci / x86_64-windows-release (pull_request) Successful in 1h14m55s
ci / x86_64-linux-debug (pull_request) Successful in 1h19m46s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h22m28s
ci / x86_64-windows-debug (pull_request) Successful in 1h29m21s
ci / aarch64-macos-release (pull_request) Successful in 1h41m36s
ci / aarch64-linux-release (pull_request) Successful in 1h46m39s
ci / aarch64-macos-debug (pull_request) Successful in 2h8m39s
ci / s390x-linux-release (pull_request) Successful in 2h26m43s
ci / aarch64-netbsd-debug (pull_request) Has been skipped
ci / aarch64-netbsd-release (pull_request) Has been skipped
ci / powerpc64le-linux-release (pull_request) Successful in 3h1m16s
ci / aarch64-linux-debug (pull_request) Successful in 3h6m18s
ci / s390x-linux-debug (pull_request) Successful in 3h50m25s
ci / loongarch64-linux-release (pull_request) Successful in 2h52m34s
ci / aarch64-freebsd-debug (pull_request) Has been skipped
ci / aarch64-freebsd-release (pull_request) Has been skipped
ci / loongarch64-linux-debug (pull_request) Successful in 3h35m2s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 3h58m42s
ci / x86_64-linux-release (pull_request) Successful in 4h19m16s
ci / powerpc64le-linux-debug (pull_request) Successful in 4h30m2s
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
b2c3c33eef
ifreund changed title from (削除) Make std.zig.Ast.parse() and grammar.PEG finally agree (削除ここまで) to Make std.zig.Ast.parse() and grammar.peg finally agree 2026年07月08日 16:27:43 +02:00
andrewrk left a comment
Copy link

Wow. The thoroughness and attention to detail here is truly remarkable. Thank you for taking the time to do this!

Fun fact, if you look at the first few commits of this git repository, you'll see that pretty much the first thing I tried to do was basically to write tools/gen_parser_oracle.zig, and after a few weeks I gave up and wrote recursive descent instead because I found the task too difficult. Not only did you implement that in this patchset but it was just a small component in the bigger fuzzing story. Really impressive.

One thing I want to revisit later is the recovery code. Eventually, I want to get to a place where the parser has no more error.ParseFailed possibility. It must always return an AST (or OOM), although some of the nodes could be "error" nodes. This is something that @matklad talked me into. It's a key ingredient of sharing the same toolchain for both compilation and IDE support.

Wow. The thoroughness and attention to detail here is truly remarkable. Thank you for taking the time to do this! Fun fact, if you look at the first few commits of this git repository, you'll see that pretty much the first thing I tried to do was basically to write `tools/gen_parser_oracle.zig`, and after a few weeks I gave up and wrote recursive descent instead because I found the task too difficult. Not only did you implement that in this patchset but it was just a small component in the bigger fuzzing story. Really impressive. One thing I want to revisit later is the recovery code. Eventually, I want to get to a place where the parser has no more `error.ParseFailed` possibility. It must always return an AST (or OOM), although some of the nodes could be "error" nodes. This is something that @matklad talked me into. It's a key ingredient of sharing the same toolchain for both compilation and IDE support.

Followup: #36102

Followup: https://codeberg.org/ziglang/zig/pulls/36102
ifreund deleted branch parser-oracle 2026年07月09日 09:23:26 +02:00
ifreund referenced this pull request from a commit 2026年07月09日 09:42:45 +02:00
Contributor
Copy link

Really happy to see this! Hand-written parser cross-fuzzed against a formal grammar is imo how all real languages should work!

On the topic of parenthesis, I have a todo list to look closer into Carbon’s parser:

https://github.com/carbon-language/carbon-lang/blob/trunk/toolchain/docs/parse.md

The idea there is that recursion is bad, so they just went ahead and did a non-recursive parser by hand, and, reportedly, this turned out to not actually be terrible?

Really happy to see this! Hand-written parser cross-fuzzed against a formal grammar is imo how all real languages should work! On the topic of parenthesis, I have a todo list to look closer into Carbon’s parser: https://github.com/carbon-language/carbon-lang/blob/trunk/toolchain/docs/parse.md The idea there is that recursion is bad, so they just went ahead and did a non-recursive parser by hand, and, reportedly, this turned out to not actually be terrible?

Windows CI runs have been printing error: Invalid grammar since this was merged, tests should not generally be printing anything when they pass, or alternatively, failing tests should not be causing successful CI runs.

Windows CI runs have been printing `error: Invalid grammar` since this was merged, tests should not generally be printing anything when they pass, or alternatively, failing tests should not be causing successful CI runs.

Windows CI runs have been printing error: Invalid grammar

My guess is that this is CRLF line ending related.

EDIT: Yep #36119

> Windows CI runs have been printing error: Invalid grammar My guess is that this is CRLF line ending related. EDIT: Yep https://codeberg.org/ziglang/zig/pulls/36119
Sign in to join this conversation.
No reviewers
Labels
Clear labels
abi/f32
abi/ilp32
abi/sf
accepted
This proposal is planned.
arch/21k
arch/6502
arch/aarch64
arch/alpha
arch/amdgcn
arch/arc
arch/arc32
arch/arc64
arch/arm
arch/avr
arch/bfin
arch/bpf
arch/colossus
arch/cris
arch/csky
arch/dlx
arch/epiphany
arch/fr30
arch/frv
arch/hexagon
arch/hppa
arch/hppa64
arch/ia64
arch/kalimba
arch/kvx
arch/lanai
arch/lm32
arch/loongarch32
arch/loongarch64
arch/m32r
arch/m68k
arch/m88k
arch/mcore
arch/microblaze
arch/mips
arch/mips64
arch/mmix
arch/moxie
arch/mrisc32
arch/msp430
arch/nds32
arch/ns32k
arch/nvptx
arch/or1k
arch/powerpc
arch/powerpc64
arch/propeller
arch/riscv32
arch/riscv64
arch/rl78
arch/rx
arch/s390x
arch/sh
arch/sparc
arch/sparc64
arch/spirv
arch/spu
arch/tricore
arch/v850
arch/vax
arch/vc4
arch/ve
arch/wasm
arch/x86
arch/x86_64
arch/xcore
arch/xtensa
autodoc
The web application for interactive documentation and generation of its assets.
backend/c
The C backend outputs C source code.
backend/llvm
The LLVM backend outputs an LLVM bitcode module.
backend/self-hosted
The self-hosted backends produce machine code directly.
binutils
Zig's included binary utilities: zig ar, zig dlltool, zig lib, zig ranlib, zig objcopy, and zig rc.
breaking
Implementing this issue could cause existing code to no longer compile or have different behavior.
build system
The Zig build system - zig build, std.Build, the build runner, and package management.
debug info
An issue related to debug information (e.g. DWARF) produced by the Zig compiler.
docs
An issue with documentation, e.g. the language reference or standard library doc comments.
error message
This issue points out an error message that is unhelpful and should be improved.
frontend
Tokenization, parsing, AstGen, ZonGen, Sema, Legalize, and Liveness.
fuzzing
An issue related to Zig's integrated fuzz testing.
incremental
Reuse of internal compiler state for faster compilation.
lib/c
This issue relates to Zig's libc implementation and/or vendored libcs.
lib/compiler-rt
This issue relates to Zig's compiler-rt library.
lib/cxx
This issue relates to Zig's vendored libc++ and/or libc++abi.
lib/std
This issue relates to Zig's standard library.
lib/tsan
This issue relates to Zig's vendored libtsan.
lib/ubsan-rt
This issue relates to Zig's ubsan-rt library.
lib/unwind
This issue relates to Zig's vendored libunwind.
linking
Zig's integrated object file and incremental linker.
miscompilation
The compiler reports success but produces semantically incorrect code.
os/android
os/contiki
os/dragonfly
os/driverkit
os/emscripten
os/freebsd
os/fuchsia
os/haiku
os/hermit
os/hurd
os/illumos
os/ios
os/linux
os/maccatalyst
os/macos
os/managarm
os/netbsd
os/ohos
os/openbsd
os/plan9
os/redox
os/rtems
os/serenity
os/tvos
os/uefi
os/visionos
os/wasi
os/watchos
os/windows
proposal
This issue suggests language modifications. If it also has the "accepted" label then it is planned.
release notes
This issue or pull request should be mentioned in the release notes.
testing
This issue is related to testing the compiler, standard library, or other parts of Zig.
zig cc
Zig as a drop-in C-family compiler.
zig fmt
The Zig source code formatter.
zig reduce
The Zig source code reduction tool.
bounty
https://ziglang.org/news/announcing-donor-bounties
bug
Observed behavior contradicts documented or intended behavior.
contributor-friendly
This issue is limited in scope and/or knowledge of project internals.
downstream
An issue with a third-party project that uses this project.
enhancement
Solving this issue will likely involve adding new logic or components to the codebase.
infra
An issue related to project infrastructure, e.g. continuous integration.
optimization
A task to improve performance and/or resource usage.
question
No questions on the issue tracker; use a community space instead.
regression
Something that used to work in a previous version stopped working
upstream
An issue with a third-party project that this project uses.
use case
Describes a real use case that is difficult or impossible, but does not propose a solution.
No labels
abi/f32
abi/ilp32
abi/sf
accepted
arch/21k
arch/6502
arch/aarch64
arch/alpha
arch/amdgcn
arch/arc
arch/arc32
arch/arc64
arch/arm
arch/avr
arch/bfin
arch/bpf
arch/colossus
arch/cris
arch/csky
arch/dlx
arch/epiphany
arch/fr30
arch/frv
arch/hexagon
arch/hppa
arch/hppa64
arch/ia64
arch/kalimba
arch/kvx
arch/lanai
arch/lm32
arch/loongarch32
arch/loongarch64
arch/m32r
arch/m68k
arch/m88k
arch/mcore
arch/microblaze
arch/mips
arch/mips64
arch/mmix
arch/moxie
arch/mrisc32
arch/msp430
arch/nds32
arch/ns32k
arch/nvptx
arch/or1k
arch/powerpc
arch/powerpc64
arch/propeller
arch/riscv32
arch/riscv64
arch/rl78
arch/rx
arch/s390x
arch/sh
arch/sparc
arch/sparc64
arch/spirv
arch/spu
arch/tricore
arch/v850
arch/vax
arch/vc4
arch/ve
arch/wasm
arch/x86
arch/x86_64
arch/xcore
arch/xtensa
autodoc
backend/c
backend/llvm
backend/self-hosted
binutils
breaking
build system
debug info
docs
error message
frontend
fuzzing
incremental
lib/c
lib/compiler-rt
lib/cxx
lib/std
lib/tsan
lib/ubsan-rt
lib/unwind
linking
miscompilation
os/android
os/contiki
os/dragonfly
os/driverkit
os/emscripten
os/freebsd
os/fuchsia
os/haiku
os/hermit
os/hurd
os/illumos
os/ios
os/linux
os/maccatalyst
os/macos
os/managarm
os/netbsd
os/ohos
os/openbsd
os/plan9
os/redox
os/rtems
os/serenity
os/tvos
os/uefi
os/visionos
os/wasi
os/watchos
os/windows
proposal
release notes
testing
zig cc
zig fmt
zig reduce
bounty
bug
contributor-friendly
downstream
enhancement
infra
optimization
question
regression
upstream
use case
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
5 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ziglang/zig!36094
Reference in a new issue
ziglang/zig
No description provided.
Delete branch "ifreund/zig:parser-oracle"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?