diff --git a/mecha.zig b/mecha.zig index 6d20dff..3b05627 100644 --- a/mecha.zig +++ b/mecha.zig @@ -30,6 +30,8 @@ pub fn Parser(comptime _T: type) type { pub const mapConst = mecha.mapConst; pub const map = mecha.map; pub const opt = mecha.opt; + pub const peek = mecha.peek; + pub const not = mecha.not; }; } @@ -361,6 +363,35 @@ test "opt" { try expectOk(?u8, 0, null, try p1.parse(fa, "1")); } +pub fn not(comptime parser: anytype) Parser(void) { + return _peek(parser, true); +} + +pub fn peek(comptime parser: anytype) Parser(void) { + return _peek(parser, false); +} + +pub fn _peek(comptime parser: anytype, _not: bool) mecha.Parser(void) { + const Res = mecha.Result(void); + return .{ .parse = struct { + fn parse(allocator: mem.Allocator, str: []const u8) mecha.Error!Res { + const res = try parser.parse(allocator, str); + return switch (res.value) { + .ok => if (_not) Res.err(0) else Res.ok(0, {}), + .err => if (_not) Res.ok(0, {}) else Res.err(0), + }; + } + }.parse }; +} + +test "peek" { + const fa = testing.failing_allocator; + const p1 = comptime ascii.range('a', 'z').peek(); + try expectOk(void, 0, {}, try p1.parse(fa, "a")); + try expectOk(void, 0, {}, try p1.parse(fa, "aa")); + try expectErr(void, 0, try p1.parse(fa, "1")); +} + fn parsersTypes(comptime parsers: anytype) []const type { var types: []const type = &[_]type{}; for (parsers) |parser| {