|
| 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 | + ``` |
0 commit comments