Skip to content

feat(opt): emit rule comments as options - #110

Merged
3Hren merged 1 commit into
mainfrom
feat/comment-option
Sep 16, 2026
Merged

3Hren merged 1 commit into
mainfrom
feat/comment-option

Conversation

@3Hren

@3Hren 3Hren commented Sep 16, 2026

Copy link
Copy Markdown
Member

A // comment is a rule option, as in FreeBSD, where TOK_COMMENT sits among rule_options and fill_comment writes an O_NOP opcode that keeps its F_NOT and F_OR bits. The parser now hands it to State.OnOption as an OptComment whose Text is the rest of the line up to any #, leading space kept and trailing whitespace removed, instead of storing it in Instruction.InlineComment.

The comment arrives wherever it stands: after a rule body, after check-state, and as the body of a comment-only rule (add 100 // note still gives a count rule with TargetAny source and destination, then the comment option). ParseOptions consumes it instead of stopping at it, and an OptionHook is never asked about //.

Taking the rest of the line, a comment inside { … } leaves the group unclosed: { in or // c } now fails with ErrExpectedOr at the end of the line, where it used to be ErrUnknownOption. not // text is accepted, as upstream does, and makes the rule never match.

VM

program.DropComments removes a comment that decides nothing before a rule is closed: not negated, not in an or-group and not followed by an option joined to it. A commented rule therefore keeps an empty option run and the fast path of a rule without options. A negated comment, or one a hook placed in a group, stays and holds through matchPolicy, so not // fails its rule.

Unchanged divergences

The accepted syntax is otherwise the same as before. FreeBSD requires // to be a whole word, here glued forms such as in// c keep being accepted. The 80-character limit is not enforced and the words are not rejoined with single spaces.

Compatibility

Breaking: Instruction.InlineComment is removed, the comment is an option. v0.2.0 is already incompatible with v0.1.0.

Performance

taskset -c 12-15, prebuilt binaries before and after, benchstat, n=6:

benchmark before after
Parser_Next_CommentOnlyRule 124.2 ns 178.8 ns
Parser_Next_CommentOptionLong (about 4 KB of comment) 905 ns 1030 ns
Parser_Next_OptionsAfterTarget 2.33 µs 2.37 µs (p=0.46)
Parser_Next_Grammar/Ruleset/Raw 9.81 ms 10.12 ms (p=0.065)

A comment line now pays for a 192-byte Opt through the State interface. A comment right after the destination skips the speculative option pass, without which the long comment was 44% slower. All Benchmark_Parser_Next* stay at 0 allocs/op, and the VM check path keeps its AllocsPerRun == 0 guard.

Validation

Tests were rewritten first and failed: every InlineComment assertion became a full ReduceState with the OptComment option, plus new cases for CRLF, not //, comments inside groups, a state rejecting the comment, hooks next to comments, and Test_VM_Check_CommentOption for the verdicts. make test (race) and make lint pass.

A `//` comment is an option, as in FreeBSD where it is an O_NOP opcode
among the rule options. The parser hands it to State.OnOption as an
OptComment holding the text up to any `#`, wherever it stands: after a
body, after check-state or as the body of a comment-only rule. It takes
the rest of the line, so inside a group it leaves the group unclosed,
and `not //` is accepted and makes the rule never match. ParseOptions
consumes the comment instead of stopping at it.

The VM drops a comment that decides nothing when it builds a rule, so a
commented rule keeps its empty option run.

This breaks the API: Instruction.InlineComment is gone, the comment
arrives as an option.
@3Hren
3Hren merged commit 3261202 into main Sep 16, 2026
1 check passed
@3Hren
3Hren deleted the feat/comment-option branch September 16, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant