define StringParser { refines Parser @value String match run (contextOld) { if (contextOld.hasAnyError()) { return contextOld.convertError() } String message <- "Failed to match \"" + match + "\" at " + contextOld.getPosition() ParseContext context <- contextOld traverse (Counter.zeroIndexed(match.size()) -> Int index) { $ReadOnly[index]$ if (context.atEof() || context.current() != match.readAt(index)) { if (index > 0) { // Partial match => set error context. return context.setBrokenInput(message) } else { return context.setValue(ErrorOr:error(message)) } } context <- context.advance() } return context.setValue(ErrorOr:value(match)) } create (match) { return delegate -> #self } } define SequenceOfParser { refines Parser @value String matches @value Int min @value Int max run (contextOld) { if (contextOld.hasAnyError()) { return contextOld.convertError() } String message <- "Failed to match [" + matches + "]{" + min.formatted() + "," + max.formatted() + "} at " + contextOld.getPosition() ParseContext context <- contextOld [Append & Build] builder <- String.builder() optional Order counter <- defer if (max == 0) { counter <- Counter.unlimited() } else { counter <- Counter.zeroIndexed(max) } Int count <- 0 traverse (counter -> count) { $Hidden[count, counter]$ if (context.atEof()) { break } Bool found <- false traverse (Counter.zeroIndexed(matches.size()) -> Int index) { $ReadOnly[context, index]$ if (context.current() == matches.readAt(index)) { \ builder.append(matches.readAt(index)) found <- true break } } if (!found) { break } context <- context.advance() } if (count >= min) { return context.setValue(ErrorOr:value(builder.build())) } elif (count > 0) { // Partial match => set error context. return context.setBrokenInput(message) } else { return context.setValue(ErrorOr:error(message)) } } create (matches, min, max) { return delegate -> #self } } define CharParser { refines Parser @value Char match run (contextOld) { if (contextOld.hasAnyError()) { return contextOld.convertError() } if (contextOld.atEof() || contextOld.current() != match) { String message <- "Failed to match '" + match.formatted() + "' at " + contextOld.getPosition() return contextOld.setValue(ErrorOr:error(message)) } else { return contextOld.advance().setValue(ErrorOr:value(match)) } } create (match) { return delegate -> #self } } concrete ConstParser<#x> { #x immutable @type create (#x) -> (Parser<#x>) } define ConstParser { refines Parser<#x> @value #x value run (contextOld) { return contextOld.setValue(ErrorOr:value(value)) } create (value) { return delegate -> #self } } concrete ErrorParser { @type create (Formatted) -> (Parser) } define ErrorParser { refines Parser @value String message run (contextOld) { return contextOld.setValue(ErrorOr:error(message)) } create (message) { return ErrorParser{ message.formatted() } } } concrete TryParser<#x> { @type create (Parser<#x>) -> (Parser<#x>) } define TryParser { refines Parser<#x> @value Parser<#x> parser run (contextOld) { if (contextOld.hasAnyError()) { return contextOld.convertError() } ParseContext<#x> context <- contextOld.run<#x>(parser) if (context.hasAnyError()) { return contextOld.setValue(context.getValue().convertError()) } else { return context.toState() } } create (parser) { return delegate -> #self } } concrete OrParser<#x> { @type create (Parser<#x>, Parser<#x>) -> (Parser<#x>) } define OrParser { refines Parser<#x> @value Parser<#x> parser1 @value Parser<#x> parser2 run (contextOld) { if (contextOld.hasAnyError()) { return contextOld.convertError() } ParseContext<#x> context <- contextOld.run<#x>(parser1) if (context.hasAnyError() && !context.hasBrokenInput()) { return contextOld.run<#x>(parser2).toState() } else { return context.toState() } } create (parser1, parser2) { return delegate -> #self } } concrete LeftParser<#x> { @type create (Parser<#x>, Parser) -> (Parser<#x>) } define LeftParser { refines Parser<#x> @value Parser<#x> parser1 @value Parser parser2 run (contextOld) { if (contextOld.hasAnyError()) { return contextOld.convertError() } ParseContext<#x> context <- contextOld.run<#x>(parser1) if (context.hasAnyError()) { return context.toState() } else { ParseContext context2 <- context.run(parser2) if (context2.hasAnyError()) { return context2.convertError() } else { return context2.setValue(context.getValue()) } } } create (parser1, parser2) { return delegate -> #self } } concrete RightParser<#x> { @type create (Parser, Parser<#x>) -> (Parser<#x>) } define RightParser { refines Parser<#x> @value Parser parser1 @value Parser<#x> parser2 run (contextOld) { if (contextOld.hasAnyError()) { return contextOld.convertError() } ParseContext context <- contextOld.run(parser1) if (context.hasAnyError()) { return context.convertError() } else { return context.run<#x>(parser2).toState() } } create (parser1, parser2) { return delegate -> #self } } define Parse { error (message) { return delegate -> `ErrorParser.create` } const (value) { return delegate -> `ConstParser<#x>.create` } try (parser) { return delegate -> `TryParser<#x>.create` } or (parser1, parser2) { return delegate -> `OrParser<#x>.create` } left (parser1, parser2) { return delegate -> `LeftParser<#x>.create` } right (parser1, parser2) { return delegate -> `RightParser<#x>.create` } }