UNPKG

functionalscript

Version:

FunctionalScript is a purely functional subset of JavaScript

51 lines (50 loc) 2.37 kB
import { equal, isEmpty, fold, toArray, scan, foldScan, empty as emptyList } from "../types/list/module.f.js"; import { toRangeMap, union as byteSetUnion, one, empty, range } from "../types/byte_set/module.f.js"; import { intersect, union as sortedSetUnion } from "../types/sorted_set/module.f.js"; import { merge, get as rangeMapGet } from "../types/range_map/module.f.js"; import { unsafeCmp } from "../types/function/compare/module.f.js"; import { strictEqual } from "../types/function/operator/module.f.js"; import { stringify } from "../json/module.f.js"; import { identity } from "../types/function/module.f.js"; import { stringToList } from "../text/utf16/module.f.js"; const stringifyIdentity = stringify(identity); export const toRange = s => { const [b, e] = toArray(stringToList(s)); return range([b, e]); }; const toUnionOp = i => bs => byteSetUnion(bs)(one(i)); export const toUnion = s => { const codePoints = stringToList(s); return fold(toUnionOp)(empty)(codePoints); }; const mergeOp = { union: sortedSetUnion(unsafeCmp), equal: equal(strictEqual), def: [] }; const hasState = s => set => !isEmpty(intersect(unsafeCmp)([s])(set)); const foldOp = set => ([ruleIn, bs, ruleOut]) => rm => { if (hasState(ruleIn)(set)) { return merge(mergeOp)(rm)(toRangeMap(bs)(ruleOut)); } return rm; }; const stringifyOp = ([sortedSet, max]) => [[stringifyIdentity(sortedSet), max], stringifyOp]; const scanStringify = scan(stringifyOp); const fetchOp = ([item, _]) => [item, fetchOp]; const scanFetch = scan(fetchOp); const addEntry = grammar => set => dfa => { const s = stringifyIdentity(set); if (s in dfa) { return dfa; } const setMap = fold(foldOp(set))(emptyList)(grammar); const stringMap = toArray(scanStringify(setMap)); const newDfa = { ...dfa, [s]: stringMap }; const newStates = scanFetch(setMap); return fold(addEntry(grammar))(newDfa)(newStates); }; const emptyState = []; const emptyStateStringify = stringifyIdentity(emptyState); const initialState = ['']; const initialStateStringify = stringifyIdentity(initialState); export const dfa = grammar => addEntry(grammar)(initialState)({}); const get = rangeMapGet(emptyStateStringify); const runOp = dfa => input => s => get(input)(dfa[s]); export const run = (dfa) => (input) => foldScan(runOp(dfa))(initialStateStringify)(input);