UNPKG

functionalscript

Version:

FunctionalScript is a purely functional subset of JavaScript

172 lines (171 loc) 6.32 kB
import { stringify } from "../../json/module.f.js"; import { sort } from "../../types/object/module.f.js"; import { cp, str, range, remove, set, repeat0, join0, } from "./module.f.js"; const deterministic = () => { const wsSet = () => set('\t\n\r '); // 9,10,13,32 // {"empty":true,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32]]} const ws = repeat0(wsSet); // {"empty":true,"map":[[false,42],[true,43],[false,44],[true,45]]} const sign = () => [ [], ...set('+-'), // 43 ]; // {"empty":false,"map":[[false,48],[true,57]]} const onenine = () => [ [range('19')] ]; // {"empty":false,"map":[[false,47],[true,57]]} const digit = () => [ str('0'), [onenine], ]; // {"empty":true,"map":[[false,47],[true,57]]} const digits0 = repeat0(digit); // {"empty":false,"map":[[false,47],[true,57]]} const digits1 = () => [ [digit, digits0] ]; const e = () => set('Ee'); // 69, 101 // {"empty":true,"map":[[false,68],[true,69],[false,100],[true,101]]} const exponent = () => [ [], [e, sign, digits1], // 69 | 101 ]; // {"empty":true,"map":[[false,45],[true,46]]} const fraction = () => [ [], [cp('.'), digits1] // 46 ]; // {"empty":false,"map":[[false,47],[true,57]]} const unsignedInteger = () => [ str('0'), // 48 [onenine, digits0], // 49-57 ]; // {"empty":false,"map":[[false,44],[true,45],[false,47],[true,57]]} const integer = () => [ [unsignedInteger], // 48-57 [cp('-'), unsignedInteger], // 45 ]; // {"empty":false,"map":[[false,44],[true,45],[false,47],[true,57]]} const number = () => [ [integer, fraction, exponent] ]; // {"empty":false,"map":[[false,47],[true,57],[false,64],[true,70],[false,96],[true,102]]} const hex = () => [ [digit], // 48-57 [range('AF')], // A..F [range('af')], // a..f ]; // {"empty":false,"map":[[false,33],[true,34],[false,46],[true,47],[false,91],[true,92],[false,97],[true,98],[false,101],[true,102],[false,109],[true,110],[false,113],[true,114],[false,115],[true,117]]} const escape = () => [ ...set('"\\/bfnrt'), [cp('u'), hex, hex, hex, hex] // 117 ]; // {"empty":false,"map":[[false,31],[true,33],[false,34],[true,1114111]]} const character = () => [ ...remove([0x20, 0x10FFFF], [cp('"'), cp('\\')]), [cp('\\'), escape], // 92 ]; // {"empty":true,"map":[[false,31],[true,33],[false,34],[true,1114111]]} const characters = repeat0(character); // {"empty":false,"map":[[false,33],[true,34]]} const string = () => [ [cp('"'), characters, cp('"')] ]; const comma = () => [[cp(','), ws]]; // {"empty":false,"map":[[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]} const element = () => [ [value, ws] ]; const list = (open, rule, close) => () => [ [cp(open), ws, join0(rule, comma), cp(close)] ]; // {"empty":false,"map":[[false,90],[true,91]]} const array = list('[', element, ']'); // {"empty":false,"map":[[false,33],[true,34]]} const member = () => [ [string, ws, cp(':'), ws, element] ]; // {"empty":false,"map":[[false,122],[true,123]]} const object = list('{', member, '}'); // {"empty":false,"map":[[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]} const value = () => [ [object], // 123 [array], // 91 [string], // 34 [number], // 45, 48-57 str('true'), // 116 str('false'), // 102 str('null'), // 110 ]; // {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]} const json = [ws, element]; const _ = json; }; // const s = stringify(sort); export default { example: { module: () => { // Matches 'A-Z', 'a-z', and '0-9' const grammar = () => [ [range('AZ')], [range('az')], [range('09')], ]; const _ = grammar; }, types: () => { const alpha = range('AZ'); // Matches 'A-Z' const id2 = [alpha, alpha]; // Matches two uppercase letters const digit = range('09'); // Matches '0-9' // Matches two uppercase letters or one digit const id2OrDigit = [ id2, [digit], ]; // Matches 'true', 'false' const bool = () => [ str('true'), str('false'), ]; // zero or more alpha symbols const alpha0x = () => [ [], // Empty [alpha, alpha0x] // Recursive ]; const id = [alpha, alpha0x]; const _ = [id2OrDigit, bool, id]; }, str: () => { const ranges = str('abc'); // [[97, 97], [98, 98], [99, 99]] const result = s(ranges); if (result !== '[[97,97],[98,98],[99,99]]') { throw result; } }, cp: () => { const range = cp('A'); // [65, 65] const result = s(range); if (result !== '[65,65]') { throw result; } }, range: () => { const r = range('AZ'); // [65, 90] const result = s(r); if (result !== '[65,90]') { throw result; } }, remove: () => { const result = s(remove([65, 90], [cp('C'), cp('W')])); // [A..Z] w/o C and W if (result !== '[[[65,66]],[[68,86]],[[88,90]]]') { throw result; } } }, remove: () => { const _x = remove([0x20, 0x10FFFF], [cp('"'), cp('\\')]); } };