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 scoped { Int index <- 0 } in while (index < match.readSize()) { if (context.atEof() || context.current() != match.readPosition(index)) { if (index > 0) { // Partial match => set error context. return context.setBrokenInput(message) } else { return context.setValue(ErrorOr$$error(message)) } } } update { index <- index+1 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 Builder builder <- String$builder() Int count <- 0 while (!context.atEof() && (max == 0 || count < max)) { Bool found <- false scoped { Int index <- 0 } in while (index < matches.readSize()) { if (context.current() == matches.readPosition(index)) { \ builder.append(matches.readPosition(index).formatted()) found <- true break } } update { index <- index+1 } if (!found) { break } } update { count <- count+1 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 ConstParser<#x>{ 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 TryParser<#x>{ 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 OrParser<#x>{ 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 LeftParser<#x>{ 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 RightParser<#x>{ 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) } }