206 lines
7.3 KiB
JavaScript
Executable File
206 lines
7.3 KiB
JavaScript
Executable File
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.parse = void 0;
|
|
const debug_1 = __importDefault(require("debug"));
|
|
const debug = debug_1.default('cmd-ts:parser');
|
|
/**
|
|
* Create an AST from a token list
|
|
*
|
|
* @param tokens A token list, coming from `tokenizer.ts`
|
|
* @param forceFlag Keys to force as flag. {@see ForceFlag} to read more about it.
|
|
*/
|
|
function parse(tokens, forceFlag) {
|
|
if (debug.enabled) {
|
|
const registered = {
|
|
shortFlags: [...forceFlag.forceFlagShortNames],
|
|
longFlags: [...forceFlag.forceFlagLongNames],
|
|
shortOptions: [...forceFlag.forceOptionShortNames],
|
|
longOptions: [...forceFlag.forceOptionLongNames],
|
|
};
|
|
debug(`Registered:`, JSON.stringify(registered));
|
|
}
|
|
const nodes = [];
|
|
let index = 0;
|
|
let forcedPositional = false;
|
|
function getToken() {
|
|
return tokens[index++];
|
|
}
|
|
function peekToken() {
|
|
return tokens[index];
|
|
}
|
|
while (index < tokens.length) {
|
|
const currentToken = getToken();
|
|
if (!currentToken)
|
|
break;
|
|
if (currentToken.type === 'argumentDivider') {
|
|
continue;
|
|
}
|
|
if (forcedPositional) {
|
|
let str = currentToken.raw;
|
|
let nextToken = getToken();
|
|
while (nextToken && (nextToken === null || nextToken === void 0 ? void 0 : nextToken.type) !== 'argumentDivider') {
|
|
str += nextToken.raw;
|
|
nextToken = getToken();
|
|
}
|
|
nodes.push({
|
|
type: 'positionalArgument',
|
|
index: currentToken.index,
|
|
raw: str,
|
|
});
|
|
continue;
|
|
}
|
|
if (currentToken.type === 'char') {
|
|
let str = currentToken.raw;
|
|
let nextToken = getToken();
|
|
while (nextToken && (nextToken === null || nextToken === void 0 ? void 0 : nextToken.type) !== 'argumentDivider') {
|
|
str += nextToken.raw;
|
|
nextToken = getToken();
|
|
}
|
|
nodes.push({
|
|
type: 'positionalArgument',
|
|
index: currentToken.index,
|
|
raw: str,
|
|
});
|
|
continue;
|
|
}
|
|
if (currentToken.type === 'longPrefix') {
|
|
let nextToken = getToken();
|
|
if ((nextToken === null || nextToken === void 0 ? void 0 : nextToken.type) === 'argumentDivider') {
|
|
nodes.push({
|
|
type: 'forcePositional',
|
|
index: currentToken.index,
|
|
raw: '--',
|
|
});
|
|
forcedPositional = true;
|
|
continue;
|
|
}
|
|
let key = '';
|
|
while (nextToken &&
|
|
(nextToken === null || nextToken === void 0 ? void 0 : nextToken.raw) !== '=' &&
|
|
(nextToken === null || nextToken === void 0 ? void 0 : nextToken.type) !== 'argumentDivider') {
|
|
key += nextToken.raw;
|
|
nextToken = getToken();
|
|
}
|
|
const parsedValue = parseOptionValue({
|
|
key,
|
|
delimiterToken: nextToken,
|
|
forceFlag: forceFlag.forceFlagLongNames,
|
|
getToken,
|
|
peekToken,
|
|
forceOption: forceFlag.forceOptionLongNames,
|
|
});
|
|
let raw = `--${key}`;
|
|
if (parsedValue) {
|
|
raw += parsedValue.raw;
|
|
}
|
|
nodes.push({
|
|
type: 'longOption',
|
|
key,
|
|
index: currentToken.index,
|
|
raw,
|
|
value: parsedValue,
|
|
});
|
|
continue;
|
|
}
|
|
if (currentToken.type === 'shortPrefix') {
|
|
let keys = [];
|
|
let nextToken = getToken();
|
|
if ((nextToken === null || nextToken === void 0 ? void 0 : nextToken.type) === 'argumentDivider' || !nextToken) {
|
|
nodes.push({
|
|
type: 'positionalArgument',
|
|
index: currentToken.index,
|
|
raw: '-',
|
|
});
|
|
continue;
|
|
}
|
|
while (nextToken &&
|
|
(nextToken === null || nextToken === void 0 ? void 0 : nextToken.type) !== 'argumentDivider' &&
|
|
(nextToken === null || nextToken === void 0 ? void 0 : nextToken.raw) !== '=') {
|
|
keys.push(nextToken);
|
|
nextToken = getToken();
|
|
}
|
|
const lastKey = keys.pop();
|
|
const parsedValue = parseOptionValue({
|
|
key: lastKey.raw,
|
|
delimiterToken: nextToken,
|
|
forceFlag: forceFlag.forceFlagShortNames,
|
|
forceOption: forceFlag.forceOptionShortNames,
|
|
getToken,
|
|
peekToken,
|
|
});
|
|
const options = [];
|
|
for (const key of keys) {
|
|
options.push({
|
|
type: 'shortOption',
|
|
index: key.index,
|
|
raw: key.raw,
|
|
key: key.raw,
|
|
});
|
|
}
|
|
let lastKeyRaw = lastKey.raw;
|
|
if (parsedValue) {
|
|
lastKeyRaw += parsedValue.raw;
|
|
}
|
|
options.push({
|
|
type: 'shortOption',
|
|
index: lastKey.index,
|
|
raw: lastKeyRaw,
|
|
value: parsedValue,
|
|
key: lastKey.raw,
|
|
});
|
|
let optionsRaw = `-${keys.map((x) => x.raw).join('')}${lastKey.raw}`;
|
|
if (parsedValue) {
|
|
optionsRaw += parsedValue.raw;
|
|
}
|
|
const shortOptions = {
|
|
type: 'shortOptions',
|
|
index: currentToken.index,
|
|
raw: optionsRaw,
|
|
options,
|
|
};
|
|
nodes.push(shortOptions);
|
|
continue;
|
|
}
|
|
index++;
|
|
continue;
|
|
}
|
|
if (debug.enabled) {
|
|
const objectNodes = nodes.map((node) => ({ [node.type]: node.raw }));
|
|
debug(`Parsed items:`, JSON.stringify(objectNodes));
|
|
}
|
|
return nodes;
|
|
}
|
|
exports.parse = parse;
|
|
function parseOptionValue(opts) {
|
|
var _a;
|
|
let { getToken, delimiterToken, forceFlag, key, forceOption } = opts;
|
|
const shouldReadKeyAsOption = forceOption.has(key);
|
|
const shouldReadKeyAsFlag = !shouldReadKeyAsOption &&
|
|
(forceFlag.has(key) || ((_a = opts.peekToken()) === null || _a === void 0 ? void 0 : _a.type) !== 'char');
|
|
if (!delimiterToken || (delimiterToken.raw !== '=' && shouldReadKeyAsFlag)) {
|
|
return;
|
|
}
|
|
const delimiter = delimiterToken.raw === '=' ? '=' : ' ';
|
|
const delimiterIndex = delimiterToken.index;
|
|
let nextToken = getToken();
|
|
if (!nextToken) {
|
|
return;
|
|
}
|
|
let value = '';
|
|
const valueIndex = nextToken.index;
|
|
while (nextToken && (nextToken === null || nextToken === void 0 ? void 0 : nextToken.type) !== 'argumentDivider') {
|
|
value += nextToken.raw;
|
|
nextToken = getToken();
|
|
}
|
|
return {
|
|
type: 'optionValue',
|
|
index: delimiterToken.index,
|
|
delimiter: { type: 'delimiter', raw: delimiter, index: delimiterIndex },
|
|
node: { type: 'value', raw: value, index: valueIndex },
|
|
raw: `${delimiter}${value}`,
|
|
};
|
|
}
|
|
//# sourceMappingURL=parser.js.map
|