functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
51 lines (50 loc) • 2.37 kB
JavaScript
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);