zeolite-lang-0.7.0.0: example/parser/parse-text.0rx
define StringParser {
refines Parser<String>
@value String match
run (contextOld) {
if (contextOld.hasAnyError()) {
return contextOld.convertError()
}
String message <- "Failed to match \"" + match + "\" at " + contextOld.getPosition()
ParseContext<any> 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<String>
@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<any> context <- contextOld
Builder<String> 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<Char>
@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<all>)
}
define ErrorParser {
refines Parser<all>
@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<any>) -> (Parser<#x>)
}
define LeftParser {
refines Parser<#x>
@value Parser<#x> parser1
@value Parser<any> parser2
run (contextOld) {
if (contextOld.hasAnyError()) {
return contextOld.convertError()
}
ParseContext<#x> context <- contextOld.run<#x>(parser1)
if (context.hasAnyError()) {
return context.toState()
} else {
ParseContext<any> context2 <- context.run<any>(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<any>,Parser<#x>) -> (Parser<#x>)
}
define RightParser {
refines Parser<#x>
@value Parser<any> parser1
@value Parser<#x> parser2
run (contextOld) {
if (contextOld.hasAnyError()) {
return contextOld.convertError()
}
ParseContext<any> context <- contextOld.run<any>(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)
}
}