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 StringParser{ match } } } 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 <- empty 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).formatted()) 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 SequenceOfParser{ matches, min, max } } } 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 CharParser{ match } } } concrete ConstParser<#x> { @type create (#x) -> (Parser<#x>) } define ConstParser { refines Parser<#x> @value #x value run (contextOld) { return contextOld.setValue(ErrorOr:value(value)) } create (value) { return #self{ value } } } concrete ErrorParser { @type create (Formatted) -> (Parser) } define ErrorParser { refines Parser @value Formatted message run (contextOld) { return contextOld.setValue(ErrorOr:error(message)) } create (message) { return ErrorParser{ message } } } 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 #self{ parser } } } 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 #self{ parser1, parser2 } } } 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 #self{ parser1, parser2 } } } 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 #self{ parser1, parser2 } } } define Parse { const (value) { return ConstParser<#x>.create(value) } error (message) { return ErrorParser.create(message) } try (parser) { return TryParser<#x>.create(parser) } or (parser1,parser2) { return OrParser<#x>.create(parser1,parser2) } left (parser1,parser2) { return LeftParser<#x>.create(parser1,parser2) } right (parser1,parser2) { return RightParser<#x>.create(parser1,parser2) } }