UNPKG

@petristation/renewjs

Version:

Parser for .rnw files

97 lines (78 loc) 3.4 kB
import {decycle, retrocycle} from './cycle.js' import {isDeepEqual} from './compare.js' import {makeTokenizer} from './tokenizer.js' import {makeReader} from './reader.js' import symbols from './symbols.js' import {makeParser} from './parser.js' import {makeSerializer} from './serializer.js' import {makeGrammar} from './grammar.js' import {makeHierarchy} from './hierarchy.js' export const tokenizer = makeTokenizer([ {name: "white", pattern: /\s+/my, cast: (v) => v}, {name: "float", pattern: /-?\d+\.\d+/, cast: (v) => parseFloat(v)}, {name: "int", pattern: /-?\d+/, cast: (v) => parseInt(v, 10)}, {name: "boolean", pattern: /(true|false|0|1)/, cast: (v) => v==="1" || v.toLowerCase() === "true"}, {name: "nil", pattern: /NULL/, cast: (v) => null}, {name: "ref", pattern: /\d+/, prefix: /REF\s+/, cast: (v) => parseInt(v, 10)}, {name: "className", pattern: /[_a-zA-Z]+(?:\.[_a-zA-Z][_a-zA-Z0-9]*)*/, cast: (v) => v}, {name: "string", pattern: /\"(?:(?:\\\\)*\\\"|[^\"])*\"/, cast: (v) => eval(v)}, ]) export const kindKey = symbols.kindKey export const selfKey = symbols.selfKey export const refKey = symbols.refKey export const refKeyMarker = symbols.refKeyMarker export {makeSerializer, makeParser, makeGrammar} export const reader = makeReader(tokenizer) export const parserV11 = makeParser(reader, makeGrammar(11)) export const serializerV11 = makeSerializer(makeGrammar(11)) export const hierarchyV11 = makeHierarchy(makeGrammar(11)) export const parserAutoDetect = function(inputString, autoDeref = true, metaKeys = {}) { const kindKey = metaKeys?.kindKey ?? symbols.kindKey const refKey = metaKeys?.refKey ?? symbols.refKey const selfKey = metaKeys?.selfKey ?? symbols.selfKey const refKeyMarker = metaKeys?.refKeyMarker ?? symbols.refKeyMarker const actualMetaKeys = { kindKey, refKey, selfKey, refKeyMarker, } const tokenStream = tokenizer(inputString); const r = reader(inputString) const version = r.readAny(["int","className"], true); if(version.type == 'int') { const parser = makeParser(reader, makeGrammar(version.value), autoDeref, actualMetaKeys) const p = parser(inputString) p.skipAny(["int"]) const drawing = p.parseStorable(null, true, false); p.parseWindowPositionMaybe(); p.expectFinish() return { version: p.version, doctype: tryDeref(drawing, p.refMap, [kindKey], actualMetaKeys), drawing, refMap: p.refMap, metaKeys: actualMetaKeys, }; } else { const parser = makeParser(reader, makeGrammar(-1), autoDeref, actualMetaKeys) const p = parser(inputString) const drawing = p.parseStorable(null, true, false); p.parseWindowPositionMaybe(); p.expectFinish() return { version: p.version, doctype: tryDeref(drawing, p.refMap, [kindKey], actualMetaKeys), drawing, refMap: p.refMap, metaKeys: actualMetaKeys, }; } } export const stringify = (x) => JSON.stringify(decycle(x), null, 2); export function tryDeref(refOrObject, refMap, path = [], metaKeys = {}) { const refKey = metaKeys?.refKey ?? symbols.refKey const refKeyMarker = metaKeys?.refKeyMarker ?? symbols.refKeyMarker const object = (refOrObject && refOrObject[refKeyMarker]) ? refMap[refOrObject[refKey]] : refOrObject return path.reduce((o, k) => o ? tryDeref(o[k], refMap, [], metaKeys) : null, object) }