UNPKG

3h-ast

Version:
416 lines (353 loc) 12.1 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.HA = {})); }(this, (function (exports) { 'use strict'; var tokenizeDefaults = { normalSymbols: new Set('()[]{}<>+-*/\\?~!@#$%^&=|,.:;'), twoCharacterSymbols: new Set(['&&', '||', '??', '==', '>=', '<=', '!=', '<<', '>>', '++', '--', '**', '+=', '-=', '*=', '/=', '%=', '&=', '^=', '|=', '|>', '->', '=>', '..', '//', '/*', '*/']), threeCharacterSymbols: new Set(['&&=', '||=', '??=', '===', '!==', '<<=', '>>=', '**=', '...', '>>>']), fourCharacterSymbols: new Set(['>>>=']), globSymbols: new Set(['"', "'", '`']), numberCharacters: new Set('0123456789'), extendedNumberCharacters: new Set('.ABCDEF'), numberSuffixes: new Set(['D', 'B', 'O', 'H']), spaceCharacters: new Set(' \r\n\t') }; /** dts2md break */ /** * Split source code into tokens */ var tokenize = function tokenize(source, options) { var config = Object.assign({}, tokenizeDefaults, options); var normalSymbols = config.normalSymbols, twoCharacterSymbols = config.twoCharacterSymbols, threeCharacterSymbols = config.threeCharacterSymbols, fourCharacterSymbols = config.fourCharacterSymbols, globSymbols = config.globSymbols, numberCharacters = config.numberCharacters, extendedNumberCharacters = config.extendedNumberCharacters, numberSuffixes = config.numberSuffixes, spaceCharacters = config.spaceCharacters; var tokens = []; var tokenBuffer = source[0]; var globFlag = ''; var state = 0 /* ANY */ ; var escapeFlag = false; // init state if (globSymbols.has(tokenBuffer)) { globFlag = tokenBuffer; } else if (spaceCharacters.has(tokenBuffer)) { state = 1 /* SPACE */ ; } else if (numberCharacters.has(tokenBuffer)) { state = 2 /* NUMBER */ ; } else if (normalSymbols.has(tokenBuffer)) { tokens.push(tokenBuffer); tokenBuffer = ''; } for (var i = 1; i < source.length; i++) { var character = source[i]; if (globFlag) { tokenBuffer += character; if (escapeFlag) { escapeFlag = false; } else { if (character === globFlag) { tokens.push(tokenBuffer); tokenBuffer = ''; globFlag = ''; state = 0 /* ANY */ ; } else { escapeFlag = character === '\\'; } } continue; } if (globSymbols.has(character)) { if (tokenBuffer) { tokens.push(tokenBuffer); } tokenBuffer = character; globFlag = character; escapeFlag = false; continue; } if ((state === 2 /* NUMBER */ || state === 3 /* NUMBER_SUFFIX */ ) && numberSuffixes.has(character)) { tokenBuffer += character; state = 3 /* NUMBER_SUFFIX */ ; continue; } if (state === 0 /* ANY */ && !tokenBuffer && normalSymbols.has(character) && tokens.length) { var lastToken = tokens[tokens.length - 1]; if (lastToken.length === 1 && twoCharacterSymbols.has(lastToken + character)) { tokens[tokens.length - 1] += character; continue; } if (lastToken.length === 2 && threeCharacterSymbols.has(lastToken + character)) { tokens[tokens.length - 1] += character; continue; } if (lastToken.length === 3 && fourCharacterSymbols.has(lastToken + character)) { tokens[tokens.length - 1] += character; continue; } } var flag = 0 /* ANY */ ; if (spaceCharacters.has(character)) { flag = 1 /* SPACE */ ; } else if (numberCharacters.has(character) || state === 2 /* NUMBER */ && extendedNumberCharacters.has(character) && !tokenBuffer.includes('.')) { flag = 2 /* NUMBER */ ; } else if (normalSymbols.has(character)) { if (tokenBuffer) { tokens.push(tokenBuffer); } tokens.push(character); tokenBuffer = ''; state = 0 /* ANY */ ; continue; } if (state === flag) { tokenBuffer += character; } else if (state === 0 /* ANY */ && flag === 2 /* NUMBER */ ) { tokenBuffer += character; if (tokenBuffer.length > 1) { // \w+\d continue; } } else { if (tokenBuffer) { tokens.push(tokenBuffer); } tokenBuffer = character; } state = flag; } if (tokenBuffer) { tokens.push(tokenBuffer); } return tokens; }; /** dts2md break */ /** * Default span symbols: * '(' -> ')' * '[' -> ']' * '{' -> '}' */ var astDefaults = Object.assign({}, tokenizeDefaults, { spanSymbols: new Map([['(', ')'], ['[', ']'], ['{', '}']]), escapeCharacters: new Map([['t', '\t'], ['r', '\r'], ['n', '\n'], ['\n', ''], ['\\', '\\'], ['"', '"'], ["'", "'"], ['`', '`']]) }); /** dts2md break */ /** * Convert tokens to AST nodes */ var token2ast = function token2ast(tokens, options, initOffset, initLine, initColumn, cursorStart, cursorStop) { if (initOffset === void 0) { initOffset = 0; } if (initLine === void 0) { initLine = 1; } if (initColumn === void 0) { initColumn = 1; } if (cursorStart === void 0) { cursorStart = 0; } if (cursorStop === void 0) { cursorStop = tokens.length; } var config = Object.assign({}, astDefaults, options); var normalSymbols = config.normalSymbols, twoCharacterSymbols = config.twoCharacterSymbols, threeCharacterSymbols = config.threeCharacterSymbols, fourCharacterSymbols = config.fourCharacterSymbols, globSymbols = config.globSymbols, numberCharacters = config.numberCharacters, numberSuffixes = config.numberSuffixes, spaceCharacters = config.spaceCharacters, spanSymbols = config.spanSymbols, escapeCharacters = config.escapeCharacters; var result = new Array(); var offset = initOffset; var line = initLine; var column = initColumn; for (var mainCursor = cursorStart; mainCursor < cursorStop; mainCursor++) { var token = tokens[mainCursor]; if (spanSymbols.has(token)) { var spanStopSymbol = spanSymbols.get(token); var nested = 0; var spanStopPosition = mainCursor + 1; for (; spanStopPosition < tokens.length; spanStopPosition++) { if (tokens[spanStopPosition] === token) { nested++; continue; } if (tokens[spanStopPosition] === spanStopSymbol) { if (!nested) { break; } nested--; } } if (spanStopPosition === tokens.length) { throw new SyntaxError("missing " + spanStopSymbol + " for " + token + " at line " + line + " column " + column); } if (spanStopPosition === mainCursor + 1) { result.push({ type: 'span', start: token, stop: spanStopSymbol, body: [], offset: offset, line: line, column: column }); // stop symbol offset++; } else { var ast = token2ast(tokens, config, offset + 1, // +1 for start symbol line, column + 1, mainCursor + 1, spanStopPosition); var body = ast.ast; result.push({ type: 'span', start: token, stop: spanStopSymbol, body: body, offset: offset, line: line, column: column }); offset = ast.stopOffset; line = ast.stopLine; column = ast.stopColumn; } mainCursor = spanStopPosition; // mainCursor++ automatically goes here } else if (normalSymbols.has(token) || twoCharacterSymbols.has(token) || threeCharacterSymbols.has(token) || fourCharacterSymbols.has(token)) { result.push({ type: 'symbol', value: token, offset: offset, line: line, column: column }); } else if (globSymbols.has(token[0])) { var value = token[0]; var escapeFlag = false; for (var i = 1; i < token.length - 1; i++) { var character = token[i]; if (escapeFlag) { if (!escapeCharacters.has(character)) { if (character === '\r' && token[i + 1] === '\n') { continue; } throw new SyntaxError("unknown escape character: \\" + character); } value += escapeCharacters.get(character); escapeFlag = false; } else { if (character === '\\') { escapeFlag = true; continue; } value += character; } } if (escapeFlag || token[token.length - 1] !== token[0] || token.length === 1) { throw new SyntaxError("missing corresponding " + spanSymbols + " at line " + line + " column " + column); } value += token[0]; result.push({ type: 'glob', value: value, offset: offset, line: line, column: column }); } else if (numberCharacters.has(token[0])) { var suffixOffset = token.length - 1; for (; suffixOffset >= 0; suffixOffset--) { if (!numberSuffixes.has(token[suffixOffset])) { break; } } suffixOffset++; result.push({ type: 'number', value: token.slice(0, suffixOffset), suffix: token.slice(suffixOffset), offset: offset, line: line, column: column }); } else if (!spaceCharacters.has(token[0])) { result.push({ type: 'word', value: token, offset: offset, line: line, column: column }); } offset += token.length; for (var _i = 0; _i < token.length; _i++) { if (token[_i] === '\n') { line++; } } var lastNextLineIndex = token.lastIndexOf('\n'); if (~lastNextLineIndex) { column = token.length - lastNextLineIndex; } else { column += token.length; } } return { ast: result, stopOffset: offset, stopLine: line, stopColumn: column }; }; /** * Convert source code into AST nodes */ var parse = function parse(source, options) { return token2ast(tokenize(source, options), options); }; exports.astDefaults = astDefaults; exports.parse = parse; exports.token2ast = token2ast; exports.tokenize = tokenize; exports.tokenizeDefaults = tokenizeDefaults; Object.defineProperty(exports, '__esModule', { value: true }); })));