zeolite-lang-0.6.0.0: example/parser/parser.0rx
define ParseState {
// This internal inheritance takes advantage of function merging.
//
// Notice that several functions (e.g., run, hasAnyError) appear to be
// declared separately in ParseState and ParseContext in parser.0rp. Since the
// function types are compatible, the compiler automatically merges them. This
// allows ParseState to expose a subset of ParseContext without needing a
// superfluous interface that both categories refine.
refines ParseContext<#x>
@value String data
@value Int index
@value Int line
@value Int char
@value ErrorOr<#x> value
@value optional Formatted error
new (data) {
return ParseState<any>{ data, 0, 0, 0, ErrorOr$$value<Void>(Void$void()), empty }
}
run (parser) {
return parser.run(self)
}
runAndGet (parser) {
ParseState<#y> context <- parser.run(self)
return context, context.getValue()
}
convertError () {
return ParseState<#y>{ data, index, line, char, ErrorOr$$error(getError()), error }
}
getValue () {
if (present(error)) {
return ErrorOr$$error(require(error))
} else {
return value
}
}
setValue (value2) {
if (hasBrokenInput()) {
return convertError<#y>()
} else {
return ParseState<#y>{ data, index, line, char, value2, error }
}
}
setBrokenInput (message) {
return ParseState<all>{ data, index, line, char, ErrorOr$$error(message), message }
}
toState () {
return self
}
getPosition () {
return String$builder()
.append("(")
.append(line.formatted())
.append(",")
.append(char.formatted())
.append(")")
.build()
}
atEof () {
return index >= data.readSize()
}
hasAnyError () {
return present(error) || value.isError()
}
hasBrokenInput () {
return present(error)
}
current () {
\ sanityCheck()
return data.readPosition(index)
}
advance () {
\ sanityCheck()
if (data.readPosition(index) == '\n') {
return ParseState<#x>{ data, index+1, line+1, 0, value, error }
} else {
return ParseState<#x>{ data, index+1, line, char+1, value, error }
}
}
getError () {
if (present(error)) {
return require(error)
} else {
return value.getError()
}
}
@value sanityCheck () -> ()
sanityCheck () {
if (hasBrokenInput()) {
\ LazyStream<Formatted>$new()
.append("Error at ")
.append(getPosition())
.append(": ")
.append(getError())
.writeTo(SimpleOutput$error())
}
if (atEof()) {
\ LazyStream<Formatted>$new()
.append("Reached end of input at ")
.append(getPosition())
.writeTo(SimpleOutput$error())
}
}
}