Skip to content

Instantly share code, notes, and snippets.

@thoferon
Created January 13, 2020 08:34
Show Gist options
  • Save thoferon/bae3cc8812e2c4163d1f71943fc190bd to your computer and use it in GitHub Desktop.
Save thoferon/bae3cc8812e2c4163d1f71943fc190bd to your computer and use it in GitHub Desktop.
function numberField (key) {
return {
action: "numberField",
key,
}
}
function stringField (key) {
return {
action: "stringField",
key,
}
}
function objectField (key, parser) {
return {
action: "objectField",
key,
parser,
}
}
function pure (value) {
return {
action: "pure",
value,
}
}
// Return a new parser that executes both parsers and apply the result of the
// second one to the function returned by the first one.
function apply (parser1, parser2) {
return {
action: "apply",
parser1,
parser2,
}
}
// Map a function to the result of a parser.
function mapParser (parser, f) {
switch (parser.action) {
case "pure":
return pure(f(parser.value))
default:
return apply(pure(f), parser)
}
}
function interpret (parser, json) {
switch (parser.action) {
case "pure":
return parser.value
case "numberField":
if (typeof(json[parser.key]) === "number") {
return json[parser.key]
} else {
throw "ParsingError"
}
case "stringField":
if (typeof(json[parser.key]) === "string") {
return json[parser.key]
} else {
throw "ParsingError"
}
case "objectField":
if (typeof(json[parser.key]) === "object") {
return interpret(parser.parser, json[parser.key])
} else {
throw "ParsingError"
}
case "apply":
const f = interpret(parser.parser1, json)
const x = interpret(parser.parser2, json)
return f(x)
}
}
const someJson = {
database: {
port: 5432,
username: "myapp",
}
}
const parser =
objectField(
"database",
apply(
apply(
pure(function (port) {
return function (username) {
return `postgresql://${username}:secret@localhost:${port}/myapp`
}
}),
numberField("port")
),
stringField("username")
)
)
// To execute the parser, we would call:
// const result = interpret(parser, someJson)
// For later:
export default parser
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment