wp-lang 0.3.1

WPL language crate with AST, parser, evaluator, builtins, and generators.
Documentation
# WPL Group Logic

WPL groups control matching behavior. They are not field types.

## Group Types

### seq - Sequence

```wpl
(digit:id, chars:name, ip:addr)
seq(digit:id, chars:name, ip:addr)
```

All fields must match in order.

### opt - Optional Group

```wpl
opt(chars:tag")
```

The whole group may be absent without failing the rule.

### alt - Alternative Group

```wpl
alt(ip:addr, chars:addr)
```

The first successful candidate wins.

### some_of - Repeated Candidate Matching

```wpl
some_of(kvarr, ip, digit)
```

WPL keeps trying the candidates until none match anymore.

### not - Negative Assertion Group

```wpl
not(peek_symbol(ERROR):check)
```

The group succeeds when the inner field does not match.

## Important Rules

- Group operators are `seq`, `opt`, `alt`, `some_of`, and `not`.
- They operate at group level.
- Do not write nested groups such as `opt(alt(...))`.
- If one segment is optional, split it into its own group first.

Valid:

```wpl
(ip:client_ip, digit:status),
opt(chars:tag")
```

Invalid:

```wpl
(ip:client_ip, opt(chars:tag"))
opt(alt(ip:addr, chars:domain))
```

## Input Consumption

- `not(symbol(...))` may consume input depending on the inner parser behavior.
- `not(peek_symbol(...))` is the safer lookahead form when you need non-consuming checks.