Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Arcsecond Article
const {
between,
many,
choice,
sequenceOf,
char,
whitespace,
anythingExcept,
possibly,
regex,
digits,
anyOfString,
str,
recursiveParser,
sepBy
} = require('arcsecond');
/***********************************
Type Containers
***********************************/
const makeBasicType = typeName => value => ({
type: typeName,
value,
toString: () => `${typeName}(${value})`
});
const makeMultiType = typeName => values => ({
type: typeName,
value: values,
toString: () => `${typeName}(${values.map(v => v.toString()).join(', ')})`
});
const stringType = makeBasicType('String');
const numberType = makeBasicType('Number');
const booleanType = makeBasicType('Boolean');
const arrayType = makeMultiType('Array');
const objectType = makeMultiType('Object');
const keyValuePair = (key, value) => ({
type: 'KeyValuePair',
value: [key, value],
toString: () => `KeyValuePair(${key.toString()}, ${value.toString()})`
});
const nullType = () => ({
type: 'Null',
value: null,
toString: () => 'Null'
});
/***********************************
Utility Parsers
***********************************/
const orEmptyString = parser => possibly (parser) .map(x => (x) ? x : '');
const joinedSequence = parsers => sequenceOf (parsers) .map(x => x.join(''));
const joinedMany = parser => many (parser) .map(x => x.join(''));
const whitespaceSurrounded = between (whitespace) (whitespace);
const betweenQuotes = between (char ('"')) (char ('"'));
const betweenSquareBrackets = between (char ('[')) (char (']'));
const betweenCurlyBrackets = between (whitespaceSurrounded (char ('{'))) (whitespaceSurrounded(char ('}')));
const commaSeparated = sepBy (whitespaceSurrounded (char (',')));
/***********************************
Main Recursive Parser
***********************************/
const jsonParser = recursiveParser(() => choice ([
nullParser,
trueParser,
falseParser,
numberParser,
stringParser,
arrayParser,
objectParser
]));
/***********************************
Strings
***********************************/
const stringParser = betweenQuotes (joinedMany (choice ([
joinedSequence ([
char ('\\'),
char ('"')
]),
anythingExcept (char ('"'))
]))) .map(stringType);
/***********************************
Numbers
***********************************/
const numberParser = joinedSequence ([
orEmptyString (char ('-')),
choice ([
char ('0'),
regex (/^[1-9][0-9]*/)
]),
orEmptyString (joinedSequence ([
char ('.'),
digits
])),
orEmptyString (joinedSequence([
anyOfString ('eE'),
orEmptyString (anyOfString ('-+')),
digits
]))
]) .map (x => numberType(Number(x)));
/***********************************
Nulls
***********************************/
const nullParser = str ('null') .map(nullType);
/***********************************
Booleans
***********************************/
const trueParser = str ('true') .map(booleanType);
const falseParser = str ('false') .map(booleanType);
/***********************************
Arrays
***********************************/
const arrayParser = betweenSquareBrackets (commaSeparated (jsonParser)) .map(arrayType);
const keyValuePairParser = sequenceOf ([
stringParser,
whitespaceSurrounded (char (':')),
jsonParser
]) .map(([key, _, value]) => keyValuePair(key, value));
/***********************************
Objects
***********************************/
const objectParser = betweenCurlyBrackets (commaSeparated (keyValuePairParser)) .map(objectType);
@craigmc08

This comment has been minimized.

Copy link

@craigmc08 craigmc08 commented Dec 27, 2018

Why does betweenSquareBrackets not allow whitespace around the square brackets?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment