dewbead
Pure-Dart parser for dewbead lines — the single-line output format of the
dewdrop schedule-extraction model. Turns one line into a structured
ParsedEvent. No runtime dependencies.
Design: two stages, NOW isolated
The model never knows the current time. So does the parser's stage 1:
parse(String) -> AstResult— pure syntax, never touches NOW.resolve(DewbeadAst, DateTime now, {String? sourceText}) -> ParsedEvent— the only place NOW is used (weekday/week math, carry, year inference, endpoint computation, review flags).parseDewbead(String, DateTime now, {String? sourceText}) -> ParseResult— runs both.
Parsing never throws: failures come back as Err(reason, rawInput).
Grammar (summary)
line = "N" | type body
type = "E" (event) | "T" (todo)
body = when ["@" location] ">" title
when = datetime ["~" endpoint] // "~" is event-only
datetime = t-anchor | n-anchor | absolute
t-anchor = "t" [±Nd|±Nw] [".WD"] [hh:mm] // date anchor; no h/m
n-anchor = "n" {±N(d|h|m)} // now anchor; no clock
absolute = (yyyy-)mm-dd [hh:mm]
endpoint = "+"… duration | hh:mm (date from start) | absolute
- All-day when no clock is present (
n-anchors are never all-day). - Week = Monday start (ISO-8601).
t+Nw=+N*7days. - ClockEndpoint earlier than start rolls to the next day (
22:00~02:00). - AbsoluteEndpoint with omitted year infers from start, not NOW.
Usage
import 'package:dewbead/dewbead.dart';
void main() {
// Fixed `now` here so the output is deterministic; in your app pass DateTime.now().
final now = DateTime(2026, 3, 10, 9, 0); // Tuesday, local
switch (parseDewbead('Et+1d15:00~+1h@회의실>스탠드업', now)) {
case Ok(:final value):
print(value.start); // 2026-03-11 15:00:00.000
print(value.end); // 2026-03-11 16:00:00.000
print(value.location); // 회의실
case Err(:final reason):
print('parse failed: $reason');
}
}
Time zones
start/end are naive local DateTimes carrying the wall-clock in NOW's
zone. The library never converts to UTC, so toIso8601String() never emits
Z. If you need an explicit zone, apply it at your app boundary.
Known limitations (v1)
- No per-month day/leap validation:
02-30rolls over viaDateTimenormalization (→03-02). - Model-owned review flags (
vague_time, etc.) are not yet carried on the line; only code flags (inferredDate,inferredTitle,partialInfo) are emitted.inferredTitlenormalization aggressiveness is still being tuned.
See dewbead-v1.md for the full format specification.
Libraries
- dewbead
- Parse
dewdropoutput lines (dewbead) into structured calendar events.