Skip to content

Commit 9e41751

Browse files
committed
Add AGENTS.md style guide and TASKS.md parity roadmap
1 parent f04696b commit 9e41751

3 files changed

Lines changed: 422 additions & 17 deletions

File tree

‎AGENTS.md‎

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Development Charter & Agent Guidelines
2+
3+
## General Instructions
4+
5+
- Deliver code, tests, and documentation directly with zero introductory fluff or pleasantries.
6+
- Strictly adhere to 2 spaces for indentation.
7+
- Preserve zero external runtime dependencies for `petitparser-core` (rely exclusively on the Java standard library).
8+
- Target Java 11 bytecode compatibility (`<maven.compiler.release>11</maven.compiler.release>`).
9+
10+
---
11+
12+
## Backward Compatibility & Java Idioms
13+
14+
### Backward Compatibility Principles
15+
- **No Breaking Changes**: Existing public methods, constructors, and classes must remain intact. Downstream modules (`petitparser-json`, `petitparser-xml`, `petitparser-smalltalk`) and user code must continue to compile and pass tests without modification.
16+
- **Additive Evolution**: Introduce new functionality alongside existing APIs (e.g., provide `starSeparated` returning `SeparatedList` without removing `separatedBy` returning `List<Object>`).
17+
- **Raw-Type Compatibility**: When introducing generic parameters (`Parser<R>`, `Result<R>`, etc.), ensure raw-type usage compiles cleanly without requiring modifications to existing untyped grammars.
18+
19+
### Java-Centric Best Practices
20+
- **Idiomatic Java vs. Verbatim Dart**: Avoid mechanical translations of Dart-specific features (such as extension methods, positional record tuples, or operator overloading). Leverage standard Java paradigms:
21+
- Fluent method chaining on `Parser` and builders.
22+
- Standard functional interfaces (`java.util.function.Function`, `Predicate`, `BiFunction`, `Supplier`, `Consumer`).
23+
- Java `Stream` and lazy `Iterable`/`Iterator` for streaming matching and graph traversals.
24+
- Immutability for core state (`Context`, `Result`, `Token`, `SeparatedList`) using defensive copies and `Collections.unmodifiableList`.
25+
- Null-safety checks using `Objects.requireNonNull(arg, "message")`.
26+
27+
---
28+
29+
## Java Performance & Efficiency Guidelines
30+
31+
### Zero-Allocation Fast Parsing
32+
- Subclasses must implement an optimized `int fastParseOn(String buffer, int position)`:
33+
- Never allocate `Context`, `Result`, `Success`, or `Failure` objects on the fast path.
34+
- Avoid boxing primitive `char` or `int` values.
35+
- Never throw exceptions on normal parse failure; return `-1` immediately.
36+
37+
### Primitive Specialization & Character Lookups
38+
- **$O(1)$ Character Lookup Tables**: For ASCII/Latin-1 character sets, specialize character predicates with boolean lookup tables (`boolean[256]`) or primitive bitmasks (`BitSet`/`long[]`) to perform instantaneous $O(1)$ checks instead of linear scans or branching.
39+
- **Cache-Friendly Range Searching**: For sparse/Unicode ranges, use sorted primitive arrays (`char[] starts`, `char[] stops`) with `Arrays.binarySearch`.
40+
- **Pre-Merged Ranges**: Automatically merge adjacent and overlapping ranges during grammar construction so runtime checks execute minimum comparisons.
41+
42+
### Direct Substring Extraction (Zero-List Lexing)
43+
- In lexing and tokenization, eliminate intermediate `List<Character>` allocations. Parsers matching sequences of characters (`starString()`, `plusString()`, `repeatString()`, `flatten()`) must scan characters using primitive loop indexes on `buffer.charAt(i)` and extract the final sub-string with a single `buffer.substring(start, stop)` call.
44+
45+
### JVM Intrinsics & String Matching
46+
- Leverage HotSpot-intrinsic methods such as `String.startsWith(prefix, position)` and `String.regionMatches` for multi-character literals to benefit from vectorized SIMD instructions.
47+
48+
### Singleton Reuse & Allocation Minimization
49+
- Reuse immutable static singleton instances for stateless parsers and predicates (e.g. `PositionParser`, `EpsilonParser`, `NewlineParser`, `ConstantCharPredicate.any()`, `DigitCharPredicate.INSTANCE`).
50+
51+
---
52+
53+
## Architecture & Code Quality
54+
55+
### Package Structure
56+
Implementation files must strictly adhere to the established package layout:
57+
- `org.petitparser.context`: Context, Result, Success, Failure, Token, ParseError.
58+
- `org.petitparser.parser`: Parser base class and common combinator methods.
59+
- `org.petitparser.parser.actions`: Action, Trimming, Flatten, Where, Continuation parsers.
60+
- `org.petitparser.parser.combinators`: Choice, Sequence, Settable, Optional, Not, And, Skip, Label, SequentialParser, ResolvableParser.
61+
- `org.petitparser.parser.primitive`: CharacterParser, CharacterPredicate, StringParser, EpsilonParser, FailureParser, PositionParser, NewlineParser.
62+
- `org.petitparser.parser.repeating`: Possessive, Greedy, Lazy, Limited, RepeatingCharacterParser, SeparatedRepeatingParser, SeparatedList.
63+
- `org.petitparser.tools`: GrammarDefinition, GrammarParser, ExpressionBuilder, Indent.
64+
- `org.petitparser.utils`: Mirror, Optimizer, Analyzer, Linter, Profiler, Tracer, FailureJoiner, Functions.
65+
66+
### Parser Contracts
67+
Every concrete `Parser` subclass must implement:
68+
1. `Result parseOn(Context context)`: Primary parsing logic allocating `Success` or `Failure`.
69+
2. `int fastParseOn(String buffer, int position)`: Optimized parsing logic without allocating context/result objects. Returns new position on success, `-1` on failure.
70+
3. `Parser copy()`: Shallow copy of the parser.
71+
4. `boolean hasEqualProperties(Parser other)`: State comparison if the parser adds fields/configuration.
72+
5. `List<Parser> getChildren()` and `void replace(Parser source, Parser target)`: If the parser references child/delegate parsers.
73+
6. `String toString()`: Human-readable representation including key configuration or message.
74+
75+
### Documentation & Comments
76+
- Provide Javadoc comments (`/** ... */`) for all public classes, interfaces, constructors, methods, and constants.
77+
- Include `@param`, `@return`, and `@throws` tags where appropriate.
78+
- Include executable, accurate code examples for non-trivial public combinators and builders.
79+
- Use `{@link ...}` and `{@code ...}` tags to reference classes and code constructs.
80+
81+
---
82+
83+
## Testing & Quality Assurance
84+
85+
### Parallel Test Hierarchy
86+
- Maintain a strict 1:1 parallel package and class hierarchy between source and test trees:
87+
- Source: `src/main/java/org/petitparser/pkg/MyClass.java`
88+
- Test: `src/test/java/org/petitparser/pkg/MyClassTest.java`
89+
- Existing root-level tests in `org.petitparser.*` should be preserved, while new parser tests must follow the parallel package structure.
90+
91+
### Test Coverage Expectations
92+
- Unit tests are required for every line of code, including edge cases, fast-parse paths, error conditions, copy semantics, and structural equality (`isEqualTo`).
93+
- Every parser must be tested with:
94+
1. Passing inputs verifying parsed value and position.
95+
2. Failing inputs verifying failure message and exact failure position.
96+
3. Prefix/sub-string inputs to test non-zero start positions and bounds.
97+
4. Fast-parse path (`accept(input)` or `fastParseOn(buffer, position)`).
98+
5. Copy semantics (`copy()`) and structural equality (`isEqualTo()`).
99+
100+
### Running Tests
101+
Execute the Maven wrapper from the repository root:
102+
- Run all tests across the reactor:
103+
```bash
104+
./mvnw test
105+
```
106+
- Run tests only in `petitparser-core`:
107+
```bash
108+
./mvnw test -pl petitparser-core
109+
```
110+
- Run a specific test class:
111+
```bash
112+
./mvnw test -pl petitparser-core -Dtest=MyClassTest
113+
```
114+
- Run a specific test method:
115+
```bash
116+
./mvnw test -pl petitparser-core -Dtest=MyClassTest#testMethodName
117+
```
118+
- Clean and build:
119+
```bash
120+
./mvnw clean test
121+
```

‎README.md‎

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
PetitParser for Java
2-
====================
1+
# PetitParser for Java
32

43
[![Release Status](https://jitpack.io/v/petitparser/java-petitparser.svg)](https://jitpack.io/#petitparser/java-petitparser)
54
[![Java CI](https://github.com/petitparser/java-petitparser/actions/workflows/maven.yml/badge.svg)](https://github.com/petitparser/java-petitparser/actions/workflows/maven.yml)
@@ -22,9 +21,7 @@ on [GitHub](https://github.com/petitparser/java-petitparser). Feel free to
2221
report issues or create a pull-request there. General questions are best asked
2322
on [StackOverflow](http://stackoverflow.com/questions/tagged/petitparser+java).
2423

25-
26-
Installation
27-
------------
24+
## Installation
2825

2926
To include the latest release in your Java project follow the instructions
3027
below.
@@ -111,8 +108,7 @@ To also include the example grammars, use the following dependency:
111108
Instructions for alternative build systems you can find
112109
on [Maven Central](https://search.maven.org/artifact/com.github.petitparser/petitparser-core)
113110

114-
Tutorial
115-
--------
111+
## Tutorial
116112

117113
### Writing a Simple Grammar
118114

@@ -135,12 +131,12 @@ If you look at the object `id` in the debugger, you'll notice that the code
135131
above builds a tree of parser objects:
136132

137133
- `SequenceParser`: This parser accepts a sequence of parsers.
138-
- `CharacterParser`: This parser accepts a single letter.
139-
- `PossessiveRepeatingParser`: This parser accepts zero or more times
134+
- `CharacterParser`: This parser accepts a single letter.
135+
- `PossessiveRepeatingParser`: This parser accepts zero or more times
140136
another parser.
141-
- `ChoiceParser`: This parser accepts a single word character.
142-
- `CharacterParser`: This parser accepts a single letter.
143-
- `CharacterParser`: This parser accepts a single digit.
137+
- `ChoiceParser`: This parser accepts a single word character.
138+
- `CharacterParser`: This parser accepts a single letter.
139+
- `CharacterParser`: This parser accepts a single digit.
144140

145141
### Parsing Some Input
146142

@@ -518,8 +514,7 @@ parse("2^2^3"); // 256
518514
You can find this example as test case
519515
here: [ExamplesTest.java](petitparser-core/src/test/java/org/petitparser/ExamplesTest.java)
520516

521-
Misc
522-
----
517+
## Misc
523518

524519
### Examples
525520

@@ -551,6 +546,4 @@ implementations adopt best practises of the target language.
551546

552547
### License
553548

554-
The MIT License,
555-
see [LICENSE](https://raw.githubusercontent.com/petitparser/java-petitparser/master/LICENSE)
556-
.
549+
The MIT License, see [LICENSE](https://raw.githubusercontent.com/petitparser/java-petitparser/master/LICENSE).

0 commit comments

Comments
 (0)