Comparing version 1.1.1 to 1.2.0
@@ -5,10 +5,22 @@ import { | ||
many, | ||
sequenceOf, | ||
regex, | ||
anythingExcept, | ||
sepBy | ||
sepBy, | ||
choice, | ||
between | ||
} from '../..'; | ||
const joinedMany = parser => many (parser) .map(x => x.join('')); | ||
const joinedSequence = parsers => sequenceOf (parsers) .map(x => x.join('')); | ||
const cell = joinedMany (anythingExcept (regex (/^[,\n]/))); | ||
const csvString = between (char ('"')) (char ('"')) (joinedMany (choice ([ | ||
joinedSequence ([ char ('\\'), char ('"') ]), | ||
anythingExcept (regex (/^["\n]/)) | ||
]))); | ||
const cell = joinedMany (choice ([ | ||
csvString, | ||
anythingExcept (regex (/^[,\n]/)) | ||
])); | ||
const cells = sepBy (char (',')) (cell); | ||
@@ -18,3 +30,3 @@ const parser = sepBy (char ('\n')) (cells); | ||
const data = ` | ||
1,React JS,"A declarative efficient and flexible JavaScript library for building user interfaces" | ||
1,React JS,"A declarative, efficient, and flexible JavaScript library for building user interfaces" | ||
2,Vue.js,"Vue.js is a progressive incrementally-adoptable JavaScript framework for building UI on the web." | ||
@@ -26,3 +38,3 @@ 3,Angular,"One framework. Mobile & desktop." | ||
console.log( | ||
parse (parser) (data) | ||
); | ||
parse (parser) (data) .get() | ||
); |
636
index.js
@@ -6,49 +6,80 @@ "use strict"; | ||
}); | ||
exports.toValue = exports.toPromise = exports.takeLeft = exports.takeRight = exports.recursiveParser = exports.whitespace = exports.skip = exports.possibly = exports.lookAhead = exports.anythingExcept = exports.everythingUntil = exports.between = exports.choice = exports.sepBy1 = exports.sepBy = exports.sequenceOf = exports.namedSequenceOf = exports.anyOfString = exports.letters = exports.letter = exports.digits = exports.digit = exports.regex = exports.str = exports.char = exports.leftMapTo = exports.mapTo = exports.many1 = exports.many = exports.succeedWith = exports.fail = exports.decide = exports.parse = exports.tapParser = exports.composeParsers = exports.pipeParsers = exports.Parser = void 0; | ||
exports.Parser = Parser; | ||
exports.toValue = exports.toPromise = exports.takeLeft = exports.takeRight = exports.recursiveParser = exports.whitespace = exports.skip = exports.possibly = exports.lookAhead = exports.anythingExcept = exports.everythingUntil = exports.between = exports.choice = exports.sepBy1 = exports.sepBy = exports.sequenceOf = exports.namedSequenceOf = exports.anyOfString = exports.letters = exports.letter = exports.digits = exports.digit = exports.regex = exports.str = exports.char = exports.leftMapTo = exports.mapTo = exports.many1 = exports.many = exports.succeedWith = exports.fail = exports.decide = exports.parse = exports.tapParser = exports.composeParsers = exports.pipeParsers = void 0; | ||
var _data = require("data.either"); | ||
const id = x => x; // type ParserState e a = Either (Int, e) (Int, String, a) | ||
// type Parser e a b = () -> ParserState e a -> ParserState e b | ||
function Parser(p) { | ||
this.p = p; | ||
} | ||
; | ||
const FL = p => { | ||
p['fantasy-land/map'] = fn => FL(() => state => { | ||
return p()(state).map(([i, s, v]) => [i, s, fn(v)]); | ||
Parser.prototype.run = function Parser$run(targetString) { | ||
return this.p((0, _data.Right)([0, targetString, null])).map(result => { | ||
return result[2]; | ||
}); | ||
}; | ||
p['fantasy-land/chain'] = fn => FL(() => state => { | ||
return p()(state).chain(([i, s, v]) => { | ||
return fn(v)()((0, _data.Right)([i, s, v])); | ||
Parser.prototype['fantasy-land/map'] = function Parser$map(fn) { | ||
const that = this; | ||
return new Parser(function Parser$map$state(state) { | ||
return that.p(state).map(function Parser$map$state$map([i, s, v]) { | ||
return [i, s, fn(v)]; | ||
}); | ||
}); | ||
}; | ||
p['fantasy-land/ap'] = parserOfFunction => FL(() => state => { | ||
return parserOfFunction()(state).chain(([_, __, fn]) => { | ||
return p()(state).map(([i, s, v]) => [i, s, fn(v)]); | ||
Parser.prototype['fantasy-land/chain'] = function Parser$chain(fn) { | ||
const that = this; | ||
return new Parser(function Parser$chain$state(state) { | ||
return that.p(state).chain(function Parser$chain$chain([i, s, v]) { | ||
return fn(v).p((0, _data.Right)([i, s, v])); | ||
}); | ||
}); | ||
}; | ||
p['fantasy-land/of'] = x => FL(() => state => { | ||
return state.map(([i, s]) => [i, s, x]); | ||
Parser.prototype['fantasy-land/ap'] = function Parser$ap(parserOfFunction) { | ||
const that = this; | ||
return new Parser(function Parser$ap$state(state) { | ||
return parserOfFunction.p(state).chain(function Parser$ap$chain([_, __, fn]) { | ||
return that.p(state).map(function Parser$ap$chain$map([i, s, v]) { | ||
return [i, s, fn(v)]; | ||
}); | ||
}); | ||
}); | ||
}; | ||
p.map = p['fantasy-land/map']; | ||
p.ap = p['fantasy-land/ap']; | ||
p.chain = p['fantasy-land/chain']; | ||
p.of = p['fantasy-land/of']; | ||
Parser.prototype.leftMap = function Parser$leftMap(fn) { | ||
const that = this; | ||
return new Parser(function Parser$leftMap$state(state) { | ||
return that.p(state).leftMap(function Parser$leftMap$state$leftMap([i, e]) { | ||
return [i, fn(e, i)]; | ||
}); | ||
}); | ||
}; | ||
p.leftMap = fn => FL(() => state => p()(state).leftMap(([i, e]) => [i, fn(e, i)])); | ||
Parser.prototype.map = Parser.prototype['fantasy-land/map']; | ||
Parser.prototype.ap = Parser.prototype['fantasy-land/ap']; | ||
Parser.prototype.chain = Parser.prototype['fantasy-land/chain']; | ||
return p; | ||
}; // Parser :: Parser e a a | ||
Parser['fantasy-land/of'] = function (x) { | ||
return new Parser(state => { | ||
return state.map(([i, s]) => [i, s, x]); | ||
}); | ||
}; | ||
Parser.of = Parser['fantasy-land/of']; // pipeParsers :: [Parser * * *] -> Parser * * * | ||
const Parser = FL(() => id); // pipeParsers :: [Parser * * *] -> Parser * * * | ||
const pipeParsers = function pipeParsers(parsers) { | ||
return new Parser(function pipeParsers$state(state) { | ||
let nextState = state; | ||
exports.Parser = Parser; | ||
for (const parser of parsers) { | ||
nextState = parser.p(nextState); | ||
} | ||
const pipeParsers = fns => FL(() => state => { | ||
return fns.slice(1).reduce((nextState, fn) => fn()(nextState), fns[0]()(state)); | ||
}); // composeParsers :: [Parser * * *] -> Parser * * * | ||
return nextState; | ||
}); | ||
}; // composeParsers :: [Parser * * *] -> Parser * * * | ||
@@ -58,4 +89,6 @@ | ||
const composeParsers = fns => () => x => { | ||
return pipeParsers([...fns].reverse())()(x); | ||
const composeParsers = function composeParsers(parsers) { | ||
return new Parser(function composeParsers$state(state) { | ||
return pipeParsers([...parsers].reverse()).p(state); | ||
}); | ||
}; // tapParser :: (a => void) -> Parser e a a | ||
@@ -66,6 +99,8 @@ | ||
const tapParser = fn => FL(() => state => { | ||
fn(state.value); | ||
return state; | ||
}); // parse :: Parser e a b -> String -> Either e b | ||
const tapParser = function tapParser(fn) { | ||
return new Parser(function tapParser$state(state) { | ||
fn(state.value); | ||
return state; | ||
}); | ||
}; // parse :: Parser e a b -> String -> Either e b | ||
@@ -75,5 +110,6 @@ | ||
const parse = parser => targetString => { | ||
const parserState = (0, _data.Right)([0, targetString, null]); | ||
return parser()(parserState).map(([_, __, result]) => result); | ||
const parse = function parse(parser) { | ||
return function parse$targetString(targetString) { | ||
return parser.run(targetString); | ||
}; | ||
}; // decide :: (a -> Parser e b c) -> Parser e b c | ||
@@ -84,8 +120,10 @@ | ||
const decide = fn => FL(() => state => { | ||
return state.chain(([_, __, v]) => { | ||
const parser = fn(v); | ||
return parser()(state); | ||
const decide = function decide(fn) { | ||
return new Parser(function decide$state(state) { | ||
return state.chain(function decide$state$chain([_, __, v]) { | ||
const parser = fn(v); | ||
return parser.p(state); | ||
}); | ||
}); | ||
}); // fail :: String -> Parser String a b | ||
}; // fail :: String -> Parser String a b | ||
@@ -95,5 +133,9 @@ | ||
const fail = errorMessage => FL(() => state => { | ||
return state.chain(([i]) => (0, _data.Left)([i, errorMessage])); | ||
}); // succeedWith :: b -> Parser e a b | ||
const fail = function fail(errorMessage) { | ||
return new Parser(function fail$state(state) { | ||
return state.chain(function fail$state$chain([i]) { | ||
return (0, _data.Left)([i, errorMessage]); | ||
}); | ||
}); | ||
}; // succeedWith :: b -> Parser e a b | ||
@@ -103,5 +145,9 @@ | ||
const succeedWith = x => FL(() => state => { | ||
return state.map(([i, s]) => [i, s, x]); | ||
}); // many :: Parser e a b -> Parser e a [b] | ||
const succeedWith = function succeedWith(x) { | ||
return new Parser(function succeedWith$state(state) { | ||
return state.map(function succeedWith$state$map([i, s]) { | ||
return [i, s, x]; | ||
}); | ||
}); | ||
}; // many :: Parser e a b -> Parser e a [b] | ||
@@ -111,29 +157,28 @@ | ||
const many = parser => FL(() => state => { | ||
return state.chain(innerState => { | ||
const results = []; | ||
let nextState = innerState; | ||
const many = function many(parser) { | ||
return new Parser(function many$state(state) { | ||
return state.chain(function many$state$chain(innerState) { | ||
const results = []; | ||
let nextState = innerState; | ||
while (true) { | ||
let exit = false; | ||
const out = parser()((0, _data.Right)(nextState)); | ||
out.cata({ | ||
Right: x => { | ||
nextState = x; | ||
while (true) { | ||
const out = parser.p((0, _data.Right)(nextState)); | ||
if (out.isLeft) { | ||
break; | ||
} else { | ||
nextState = out.value; | ||
results.push(nextState[2]); | ||
}, | ||
Left: () => { | ||
exit = true; | ||
if (nextState[0] >= nextState[1].length) { | ||
break; | ||
} | ||
} | ||
}); | ||
if (exit || nextState[0] >= nextState[1].length) { | ||
break; | ||
} | ||
} | ||
const [index, targetString] = nextState; | ||
return (0, _data.Right)([index, targetString, results]); | ||
const [index, targetString] = nextState; | ||
return (0, _data.Right)([index, targetString, results]); | ||
}); | ||
}); | ||
}); // many1 :: Parser e a b -> Parser String a [b] | ||
}; // many1 :: Parser e a b -> Parser String a [b] | ||
@@ -143,12 +188,14 @@ | ||
const many1 = parser => FL(() => state => { | ||
const res = many(parser)()(state); | ||
return res.chain(([index, targetString, value]) => { | ||
if (value.length === 0) { | ||
return (0, _data.Left)([index, `ParseError 'many1' (position ${index}): Expecting to match at least one value`]); | ||
} | ||
const many1 = function many1(parser) { | ||
return new Parser(function many1$state(state) { | ||
const res = many(parser).p(state); | ||
return res.chain(function many1$state$chain([index, targetString, value]) { | ||
if (value.length === 0) { | ||
return (0, _data.Left)([index, `ParseError 'many1' (position ${index}): Expecting to match at least one value`]); | ||
} | ||
return (0, _data.Right)([index, targetString, value]); | ||
return (0, _data.Right)([index, targetString, value]); | ||
}); | ||
}); | ||
}); // mapTo :: (a -> b) -> Parser e a b | ||
}; // mapTo :: (a -> b) -> Parser e a b | ||
@@ -158,7 +205,9 @@ | ||
const mapTo = fn => FL(() => state => { | ||
return state.map(([index, targetString, res]) => { | ||
return [index, targetString, fn(res)]; | ||
const mapTo = function mapTo(fn) { | ||
return new Parser(function mapTo$state(state) { | ||
return state.map(function mapTo$state$map([index, targetString, res]) { | ||
return [index, targetString, fn(res)]; | ||
}); | ||
}); | ||
}); // leftMapTo :: ((e, Int) -> f) -> Parser f a b | ||
}; // leftMapTo :: ((e, Int) -> f) -> Parser f a b | ||
@@ -168,3 +217,3 @@ | ||
const leftMapTo = fn => FL(() => state => { | ||
const leftMapTo = fn => new Parser(state => { | ||
return state.leftMap(([index, errorString]) => { | ||
@@ -178,3 +227,3 @@ return [index, fn(errorString, index)]; | ||
const char = c => FL(() => state => { | ||
const char = function char(c) { | ||
if (!c || c.length !== 1) { | ||
@@ -184,16 +233,16 @@ throw new TypeError(`char must be called with a single character, but got ${c}`); | ||
return state.chain(([index, targetString]) => { | ||
const rest = targetString.slice(index); | ||
if (rest.length >= 1) { | ||
if (rest[0] === c) { | ||
return (0, _data.Right)([index + 1, targetString, c]); | ||
} else { | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting character '${c}', got '${rest[0]}'`]); | ||
return new Parser(function char$state(state) { | ||
return state.chain(function char$state$chain([index, targetString]) { | ||
if (index < targetString.length) { | ||
if (targetString[index] === c) { | ||
return (0, _data.Right)([index + 1, targetString, c]); | ||
} else { | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting character '${c}', got '${targetString[index]}'`]); | ||
} | ||
} | ||
} | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting character '${c}', but got end of input.`]); | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting character '${c}', but got end of input.`]); | ||
}); | ||
}); | ||
}); // str :: String -> Parser String a String | ||
}; // str :: String -> Parser String a String | ||
@@ -203,3 +252,3 @@ | ||
const str = s => FL(() => state => { | ||
const str = function str(s) { | ||
if (!s || s.length < 1) { | ||
@@ -209,16 +258,18 @@ throw new TypeError(`str must be called with a string with length > 1, but got ${s}`); | ||
return state.chain(([index, targetString]) => { | ||
const rest = targetString.slice(index); | ||
return new Parser(function str$state(state) { | ||
return state.chain(function str$state$chain([index, targetString]) { | ||
const rest = targetString.slice(index); | ||
if (rest.length >= 1) { | ||
if (rest.startsWith(s)) { | ||
return (0, _data.Right)([index + s.length, targetString, s]); | ||
} else { | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting string '${s}', got '${rest.slice(0, s.length)}...'`]); | ||
if (rest.length >= 1) { | ||
if (rest.startsWith(s)) { | ||
return (0, _data.Right)([index + s.length, targetString, s]); | ||
} else { | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting string '${s}', got '${rest.slice(0, s.length)}...'`]); | ||
} | ||
} | ||
} | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting string '${s}', but got end of input.`]); | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting string '${s}', but got end of input.`]); | ||
}); | ||
}); | ||
}); // regex :: RegExp -> Parser String a String | ||
}; // regex :: RegExp -> Parser String a String | ||
@@ -228,3 +279,3 @@ | ||
const regex = re => { | ||
const regex = function regex(re) { | ||
const typeofre = Object.prototype.toString.call(re); | ||
@@ -240,4 +291,4 @@ | ||
return FL(() => state => { | ||
return state.chain(([index, targetString]) => { | ||
return new Parser(function regex$state(state) { | ||
return state.chain(function regex$state$chain([index, targetString]) { | ||
const rest = targetString.slice(index); | ||
@@ -262,4 +313,4 @@ | ||
exports.regex = regex; | ||
const digit = FL(() => state => { | ||
return state.chain(([index, targetString]) => { | ||
const digit = new Parser(function digit$state(state) { | ||
return state.chain(function digit$state$chain([index, targetString]) { | ||
const rest = targetString.slice(index); | ||
@@ -283,4 +334,4 @@ | ||
exports.digits = digits; | ||
const letter = FL(() => state => { | ||
return state.chain(([index, targetString]) => { | ||
const letter = new Parser(function letter$state(state) { | ||
return state.chain(function letter$state$chain([index, targetString]) { | ||
const rest = targetString.slice(index); | ||
@@ -305,17 +356,19 @@ | ||
const anyOfString = s => FL(() => state => { | ||
return state.chain(([index, targetString]) => { | ||
const rest = targetString.slice(index); | ||
const anyOfString = function anyOfString(s) { | ||
return new Parser(function anyOfString$state(state) { | ||
return state.chain(([index, targetString]) => { | ||
const rest = targetString.slice(index); | ||
if (rest.length >= 1) { | ||
if (s.includes(rest[0])) { | ||
return (0, _data.Right)([index + 1, targetString, rest[0]]); | ||
} else { | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting any of the string "${s}", got ${rest[0]}`]); | ||
if (rest.length >= 1) { | ||
if (s.includes(rest[0])) { | ||
return (0, _data.Right)([index + 1, targetString, rest[0]]); | ||
} else { | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting any of the string "${s}", got ${rest[0]}`]); | ||
} | ||
} | ||
} | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting any of the string "${s}", but got end of input.`]); | ||
return (0, _data.Left)([index, `ParseError (position ${index}): Expecting any of the string "${s}", but got end of input.`]); | ||
}); | ||
}); | ||
}); // namedSequenceOf :: [(String, Parser e a b)] -> Parser e a (StrMap b) | ||
}; // namedSequenceOf :: [(String, Parser e a b)] -> Parser e a (StrMap b) | ||
@@ -325,30 +378,24 @@ | ||
const namedSequenceOf = pairedParsers => FL(() => state => { | ||
return state.chain(innerState => { | ||
const results = {}; | ||
let left = null; | ||
let nextState = innerState; | ||
const namedSequenceOf = function namedSequenceOf(pairedParsers) { | ||
return new Parser(function namedSequenceOf$state(state) { | ||
return state.chain(() => { | ||
const results = {}; | ||
let nextState = state; | ||
for (const [key, parser] of pairedParsers) { | ||
const out = parser()((0, _data.Right)(nextState)); | ||
out.cata({ | ||
Right: x => { | ||
nextState = x; | ||
results[key] = x[2]; | ||
}, | ||
Left: x => { | ||
left = x; | ||
for (const [key, parser] of pairedParsers) { | ||
const out = parser.p(nextState); | ||
if (out.isLeft) { | ||
return out; | ||
} else { | ||
nextState = out; | ||
results[key] = out.value[2]; | ||
} | ||
}); | ||
if (left) { | ||
break; | ||
} | ||
} | ||
if (left) return (0, _data.Left)(left); | ||
const [i, s] = nextState; | ||
return (0, _data.Right)([i, s, results]); | ||
const [i, s] = nextState.value; | ||
return (0, _data.Right)([i, s, results]); | ||
}); | ||
}); | ||
}); // sequenceOf :: [Parser e a b] -> Parser e a [b] | ||
}; // sequenceOf :: [Parser e a b] -> Parser e a [b] | ||
@@ -358,30 +405,24 @@ | ||
const sequenceOf = parsers => FL(() => state => { | ||
return state.chain(innerState => { | ||
const results = []; | ||
let left = null; | ||
let nextState = innerState; | ||
const sequenceOf = function sequenceOf(parsers) { | ||
return new Parser(function sequenceOf$state(state) { | ||
return state.chain(() => { | ||
const results = new Array(parsers.length); | ||
let nextState = state; | ||
for (const parser of parsers) { | ||
const out = parser()((0, _data.Right)(nextState)); | ||
out.cata({ | ||
Right: x => { | ||
nextState = x; | ||
results.push(x[2]); | ||
}, | ||
Left: x => { | ||
left = x; | ||
for (let i = 0; i < parsers.length; i++) { | ||
const out = parsers[i].p(nextState); | ||
if (out.isLeft) { | ||
return out; | ||
} else { | ||
nextState = out; | ||
results[i] = out.value[2]; | ||
} | ||
}); | ||
if (left) { | ||
break; | ||
} | ||
} | ||
if (left) return (0, _data.Left)(left); | ||
const [i, s] = nextState; | ||
return (0, _data.Right)([i, s, results]); | ||
const [i, s] = nextState.value; | ||
return (0, _data.Right)([i, s, results]); | ||
}); | ||
}); | ||
}); // sepBy :: Parser e a c -> Parser e a b -> Parser e a [b] | ||
}; // sepBy :: Parser e a c -> Parser e a b -> Parser e a [b] | ||
@@ -391,46 +432,44 @@ | ||
const sepBy = sepParser => valParser => FL(() => state => { | ||
return state.chain(innerState => { | ||
let nextState = innerState; | ||
let left = null; | ||
const results = []; | ||
const sepBy = function sepBy(sepParser) { | ||
return function sepBy$valParser(valParser) { | ||
return new Parser(function sepBy$valParser$state(state) { | ||
return state.chain(function sepBy$valParser$state$chain() { | ||
let nextState = state; | ||
let left = null; | ||
const results = []; | ||
while (true) { | ||
let exit = false; | ||
const valState = valParser()((0, _data.Right)(nextState)); | ||
const sepState = sepParser()(valState); | ||
const unwrappedValState = valState.cata({ | ||
Right: x => { | ||
results.push(x[2]); | ||
return x; | ||
}, | ||
Left: x => { | ||
left = x; | ||
exit = true; | ||
while (true) { | ||
const valState = valParser.p(nextState); | ||
const sepState = sepParser.p(valState); | ||
if (valState.isLeft) { | ||
left = valState; | ||
break; | ||
} else { | ||
results.push(valState.value[2]); | ||
} | ||
if (sepState.isLeft) { | ||
nextState = valState; | ||
break; | ||
} | ||
nextState = sepState; | ||
} | ||
}); | ||
const unwrappedSepState = sepState.cata({ | ||
Right: id, | ||
Left: () => { | ||
nextState = unwrappedValState; | ||
exit = true; | ||
} | ||
}); | ||
if (exit) break; | ||
nextState = unwrappedSepState; | ||
} | ||
if (left) { | ||
if (results.length === 0) { | ||
const [i, s] = innerState; | ||
return (0, _data.Right)([i, s, []]); | ||
} | ||
if (left) { | ||
if (results.length === 0) { | ||
const [i, s] = state.value; | ||
return (0, _data.Right)([i, s, results]); | ||
} | ||
return (0, _data.Left)(left); | ||
} | ||
return left; | ||
} | ||
const [i, s] = nextState; | ||
return (0, _data.Right)([i, s, results]); | ||
}); | ||
}); // sepBy1 :: Parser e a c -> Parser f a b -> Parser String a [b] | ||
const [i, s] = nextState.value; | ||
return (0, _data.Right)([i, s, results]); | ||
}); | ||
}); | ||
}; | ||
}; // sepBy1 :: Parser e a c -> Parser f a b -> Parser String a [b] | ||
@@ -440,12 +479,15 @@ | ||
const sepBy1 = sepParser => valParser => FL(() => state => { | ||
const res = sepBy(sepParser)(valParser)()(state); | ||
return res.chain(([index, targetString, value]) => { | ||
if (value.length === 0) { | ||
return (0, _data.Left)([index, `ParseError 'sepBy1' (position ${index}): Expecting to match at least one separated value`]); | ||
} | ||
const sepBy1 = function sepBy1(sepParser) { | ||
return function sepBy1$valParser(valParser) { | ||
return new Parser(function sepBy1$valParser$state(state) { | ||
return sepBy(sepParser)(valParser).p(state).chain(function sepBy1$valParser$state$chain([index, targetString, value]) { | ||
if (value.length === 0) { | ||
return (0, _data.Left)([index, `ParseError 'sepBy1' (position ${index}): Expecting to match at least one separated value`]); | ||
} | ||
return (0, _data.Right)([index, targetString, value]); | ||
}); | ||
}); // choice :: [Parser e a *] -> Parser e a * | ||
return (0, _data.Right)([index, targetString, value]); | ||
}); | ||
}); | ||
}; | ||
}; // choice :: [Parser e a *] -> Parser e a * | ||
@@ -455,32 +497,22 @@ | ||
const choice = parsers => FL(() => state => { | ||
const lefts = []; | ||
return state.chain(([index]) => { | ||
let match = null; | ||
const choice = function choice(parsers) { | ||
return new Parser(function choice$state(state) { | ||
let left = null; | ||
return state.chain(function choice$state$chain() { | ||
for (const parser of parsers) { | ||
const out = parser.p(state); | ||
for (const parser of parsers) { | ||
let exit = false; | ||
const out = parser()(state); | ||
out.cata({ | ||
Left: x => { | ||
lefts.push(x); | ||
return x; | ||
}, | ||
Right: x => { | ||
exit = true; | ||
match = (0, _data.Right)(x); | ||
if (out.isLeft) { | ||
if (!left || out.value[0] > left.value[0]) { | ||
left = out; | ||
} | ||
} else { | ||
return out; | ||
} | ||
}); | ||
if (exit) break; | ||
} | ||
} | ||
if (!match) { | ||
const furthestLeft = lefts.reduce((acc, l) => l[0] > acc[0] ? l : acc, [-Infinity]); | ||
return (0, _data.Left)(furthestLeft); // console.log(furthestLeft); | ||
// return Left ([index, `ParseError 'choice' (position ${index}): Expecting to match at least parser`]); | ||
} | ||
return match; | ||
return left; | ||
}); | ||
}); | ||
}); // between :: Parser e a b -> Parser f a c -> Parser g a d -> Parser g a d | ||
}; // between :: Parser e a b -> Parser f a c -> Parser g a d -> Parser g a d | ||
@@ -490,3 +522,9 @@ | ||
const between = leftParser => rightParser => parser => sequenceOf([leftParser, parser, rightParser]).map(([_, x]) => x); // everythingUntil :: Parser e a b -> Parser String a c | ||
const between = function between(leftParser) { | ||
return function between$rightParser(rightParser) { | ||
return function between$rightParser(parser) { | ||
return sequenceOf([leftParser, parser, rightParser]).map(([_, x]) => x); | ||
}; | ||
}; | ||
}; // everythingUntil :: Parser e a b -> Parser String a c | ||
@@ -496,14 +534,13 @@ | ||
const everythingUntil = parser => FL(() => state => { | ||
return state.chain(innerState => { | ||
const results = []; | ||
let nextState = innerState; | ||
let eof = false; | ||
const everythingUntil = function everythingUntil(parser) { | ||
return new Parser(state => { | ||
return state.chain(function everythingUntil$state(innerState) { | ||
const results = []; | ||
let nextState = state; | ||
while (true) { | ||
let exit = false; | ||
const out = parser()((0, _data.Right)(nextState)); | ||
out.cata({ | ||
Left: () => { | ||
const [index, targetString] = nextState; | ||
while (true) { | ||
const out = parser.p(nextState); | ||
if (out.isLeft) { | ||
const [index, targetString] = nextState.value; | ||
const val = targetString[index]; | ||
@@ -513,23 +550,16 @@ | ||
results.push(val); | ||
nextState = [index + 1, targetString, val]; | ||
nextState = (0, _data.Right)([index + 1, targetString, val]); | ||
} else { | ||
eof = true; | ||
exit = true; | ||
return (0, _data.Left)([nextState[0], `ParseError 'everythingUntil' (position ${nextState.value[0]}): Unexpected end of input.`]); | ||
} | ||
}, | ||
Right: () => { | ||
exit = true; | ||
} else { | ||
break; | ||
} | ||
}); | ||
if (exit) break; | ||
} | ||
} | ||
if (eof) { | ||
return (0, _data.Left)([nextState[0], `ParseError 'everythingUntil' (position ${nextState[0]}): Unexpected end of input.`]); | ||
} | ||
const [i, s] = nextState; | ||
return (0, _data.Right)([i, s, results.join('')]); | ||
const [i, s] = nextState.value; | ||
return (0, _data.Right)([i, s, results.join('')]); | ||
}); | ||
}); | ||
}); // anythingExcept :: Parser e a b -> Parser String a c | ||
}; // anythingExcept :: Parser e a b -> Parser String a c | ||
@@ -539,11 +569,15 @@ | ||
const anythingExcept = parser => FL(() => state => { | ||
return state.chain(([index, targetString]) => { | ||
const out = parser()(state); | ||
return out.cata({ | ||
Left: () => (0, _data.Right)([index + 1, targetString, targetString[index]]), | ||
Right: ([_, __, s]) => (0, _data.Left)([index, `ParseError 'anythingExcept' (position ${index}): Matched '${s}' from the exception parser`]) | ||
const anythingExcept = function anythingExcept(parser) { | ||
return new Parser(function anythingExcept$state(state) { | ||
return state.chain(([index, targetString]) => { | ||
const out = parser.p(state); | ||
if (out.isLeft) { | ||
return (0, _data.Right)([index + 1, targetString, targetString[index]]); | ||
} | ||
return (0, _data.Left)([index, `ParseError 'anythingExcept' (position ${index}): Matched '${out.value[2]}' from the exception parser`]); | ||
}); | ||
}); | ||
}); // lookAhead :: Parser e a b -> Parser e a b | ||
}; // lookAhead :: Parser e a b -> Parser e a b | ||
@@ -553,8 +587,12 @@ | ||
const lookAhead = parser => FL(() => state => { | ||
return state.chain(([i, s]) => { | ||
const nextState = parser()(state); | ||
return nextState.map(([_, __, v]) => [i, s, v]); | ||
const lookAhead = function lookAhead(parser) { | ||
return new Parser(function lookAhead$state(state) { | ||
return state.chain(function lookAhead$state$chain([i, s]) { | ||
const nextState = parser.p(state); | ||
return nextState.map(function lookAhead$state$chain$map([_, __, v]) { | ||
return [i, s, v]; | ||
}); | ||
}); | ||
}); | ||
}); // possibly :: Parser e a b -> Parser e a (b|null) | ||
}; // possibly :: Parser e a b -> Parser e a (b|null) | ||
@@ -564,11 +602,15 @@ | ||
const possibly = parser => FL(() => state => { | ||
return state.chain(([i, s]) => { | ||
const nextState = parser()(state); | ||
return nextState.cata({ | ||
Left: () => (0, _data.Right)([i, s, null]), | ||
Right: x => (0, _data.Right)(x) | ||
const possibly = function possibly(parser) { | ||
return new Parser(function possibly$state(state) { | ||
return state.chain(function possibly$state$chain([index, targetString]) { | ||
const nextState = parser.p(state); | ||
if (nextState.isLeft) { | ||
return (0, _data.Right)([index, targetString, null]); | ||
} | ||
return nextState; | ||
}); | ||
}); | ||
}); // skip :: Parser e a b -> Parser e a a | ||
}; // skip :: Parser e a b -> Parser e a a | ||
@@ -578,8 +620,10 @@ | ||
const skip = parser => FL(() => state => { | ||
return state.chain(([_, __, value]) => { | ||
const nextState = parser()(state); | ||
return nextState.map(([i, s]) => [i, s, value]); | ||
const skip = function skip(parser) { | ||
return new Parser(function skip$state(state) { | ||
return state.chain(function skip$state$chain([_, __, value]) { | ||
const nextState = parser.p(state); | ||
return nextState.map(([i, s]) => [i, s, value]); | ||
}); | ||
}); | ||
}); // whitespace :: Parser e a String | ||
}; // whitespace :: Parser e a String | ||
@@ -592,3 +636,7 @@ | ||
const recursiveParser = parserThunk => FL(() => parserThunk()()); // takeRight :: Parser e a b -> Parser f b c -> Parser f a c | ||
const recursiveParser = function recursiveParser(parserThunk) { | ||
return new Parser(function recursiveParser$state(state) { | ||
return parserThunk().p(state); | ||
}); | ||
}; // takeRight :: Parser e a b -> Parser f b c -> Parser f a c | ||
@@ -595,0 +643,0 @@ |
{ | ||
"name": "arcsecond", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "index", |
@@ -103,3 +103,3 @@ const { | ||
'Parser', | ||
expectedSuccessTest (Parser, null, 'something') | ||
expectedSuccessTest (new Parser(x => x), null, 'something') | ||
); | ||
@@ -112,3 +112,3 @@ | ||
expectedFailTest (char ('a'), ''), | ||
expectedThrowTest (char ('aaaa'), 'aaaabcdef', 'char must be called with a single character, but got aaaa'), | ||
// expectedThrowTest (char ('aaaa'), 'aaaabcdef', 'char must be called with a single character, but got aaaa'), | ||
] | ||
@@ -122,3 +122,3 @@ ); | ||
expectedFailTest (str ('def'), ''), | ||
expectedThrowTest (str (''), 'aaaabcdef', 'str must be called with a string with length > 1, but got '), | ||
// expectedThrowTest (str (''), 'aaaabcdef', 'str must be called with a string with length > 1, but got '), | ||
] | ||
@@ -668,3 +668,2 @@ ); | ||
test('map (equivalence to mapTo)', () => { | ||
const testStr = 'hello'; | ||
const fn = x => ({ value: x }) | ||
@@ -697,7 +696,7 @@ | ||
fail('nope') | ||
), | ||
expectEquivalence( | ||
fail('nope').map(x => f(g(x))), | ||
fail('nope').map(g).map(f) | ||
), | ||
), | ||
expectEquivalence( | ||
fail('nope').map(x => f(g(x))), | ||
fail('nope').map(g).map(f) | ||
), | ||
]); | ||
@@ -704,0 +703,0 @@ |
Sorry, the diff of this file is not supported yet
276003
25
2813
3