UNPKG

pddl-workspace

Version:
407 lines 15.6 kB
"use strict"; /* -------------------------------------------------------------------------------------------- * Copyright (c) Jan Dolejsi. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.PddlBracketNode = exports.PddlSyntaxNode = void 0; const PddlTokenizer_1 = require("./PddlTokenizer"); /** Single node in the syntax tree that wraps one PDDL tokenizer token. */ class PddlSyntaxNode extends PddlTokenizer_1.TextRange { /** * Creates the syntax tree node. * @param token pddl token wrapped by this node * @param parent parent node, unless this is the root node */ constructor(token, parent) { super(); this.token = token; this.parent = parent; this.children = new Array(); if (parent === undefined) { if (token.type !== PddlTokenizer_1.PddlTokenType.Document) { throw new Error(`Node of type ${token.type} must have parent defined.`); } } this.maxChildEnd = token.getEnd(); } static createRoot() { return new PddlSyntaxNode(new PddlTokenizer_1.PddlToken(PddlTokenizer_1.PddlTokenType.Document, '', 0), undefined); } isRoot() { return this.parent === undefined; } getParent() { return this.parent; } isLeaveBracket() { return this.getNestedChildren().every(child => child.isNotType(PddlTokenizer_1.PddlTokenType.OpenBracket)); } getToken() { return this.token; } addChild(childNode) { this.children.push(childNode); this.recalculateEnd(childNode); } recalculateEnd(childNode) { this.maxChildEnd = Math.max(this.maxChildEnd, childNode.getEnd()); if (this.parent) { this.parent.recalculateEnd(this); } } getChildren() { return this.children; } getNestedChildren() { return this.getChildren(); } getSingleChild() { if (this.getNestedChildren().length !== 1) { throw new Error(`Failed assertion that node '${this.getText()}' has a single child.`); } return this.getNestedChildren()[0]; } getNonWhitespaceChildren() { return this.getNestedChildren().filter(c => c.getToken().type !== PddlTokenizer_1.PddlTokenType.Whitespace); } getNonWhitespaceNonCommentChildren() { return this.getNonWhitespaceChildren().filter(c => c.getToken().type !== PddlTokenizer_1.PddlTokenType.Comment); } getSingleNonWhitespaceChild() { const nonWhitespaceChildren = this.getNonWhitespaceChildren(); if (nonWhitespaceChildren.length !== 1) { throw new Error(`Failed assertion that node '${this.toString()}' has a single non-whitespace child.`); } return nonWhitespaceChildren[0]; } getChildrenOfType(type, pattern) { return this.children.filter(c => c.getToken().type === type) .filter(node => node.getToken().tokenText.match(pattern)); } getFirstChild(type, pattern) { return this.children.filter(c => c.getToken().type === type) .find(node => node.getToken().tokenText.match(pattern)); } getFirstChildOrThrow(type, pattern) { const matchingChild = this.getFirstChild(type, pattern); if (!matchingChild) { throw new Error(`No child element of type ${type} satisfying pattern ${pattern.source}.`); } return matchingChild; } getFirstOpenBracket(keyword) { return this.getFirstChild(PddlTokenizer_1.PddlTokenType.OpenBracketOperator, new RegExp('\\(\\s*' + keyword + '$', 'i')); } getFirstOpenBracketOrThrow(keyword) { const matchingNode = this.getFirstOpenBracket(keyword); if (!matchingNode) { throw new Error(`No child '${keyword}' open bracket.`); } return matchingNode; } getChildrenRecursively(test, callback) { this.getNestedChildren().forEach(child => { try { if (test(child)) { callback(child); } } catch (_e) { // swallow } finally { child.getChildrenRecursively(test, callback); } }); } /** * Finds the bracket nested inside the `:keyword`. * @param keyword keyword name e.g. 'precondition' to match ':precondition (*)' */ getKeywordOpenBracket(keyword) { const keywordNode = this.getFirstChild(PddlTokenizer_1.PddlTokenType.Keyword, new RegExp(":" + keyword + "$", "i")); if (!keywordNode) { return undefined; } const bracket = keywordNode.getNonWhitespaceChildren().find(child => (0, PddlTokenizer_1.isOpenBracket)(child.getToken())); if (bracket) { return bracket; } else { return undefined; } } /** * Get all keyword open brackets e.g. `(:action ...)` * @param keyword keyword name e.g. `action` to match `(:action ...)` */ getKeywordOpenBrackets(keyword) { return this.getChildrenOfType(PddlTokenizer_1.PddlTokenType.OpenBracketOperator, new RegExp("\\(\\s*:" + keyword + "$")) .map(node => node); } hasChildren() { return this.getNestedChildren().length > 0; } getNestedText() { let nestedText = ''; this.getNestedChildren() .forEach(node => { nestedText = nestedText + node.getText(); }); return nestedText; } getNestedNonCommentText() { let nestedText = ''; this.getNestedChildren() .filter(node => node.isNotType(PddlTokenizer_1.PddlTokenType.Comment)) .forEach(node => { nestedText = nestedText + node.getNonCommentText(); }); return nestedText; } getText() { return this.getToken().tokenText + this.getNestedText(); } getNonCommentText() { if (this.isNotType(PddlTokenizer_1.PddlTokenType.Comment)) { return this.getToken().tokenText + this.getNestedNonCommentText(); } else { return ''; } } getStart() { return this.token.getStart(); } getEnd() { return this.maxChildEnd; } /** @returns number of characters in this node (including its children) */ get length() { return this.getEnd() - this.getStart(); } findAncestor(type, pattern) { let parent = this.parent; while (parent && parent.isNotType(PddlTokenizer_1.PddlTokenType.Document)) { if (parent.isType(type) && pattern.test(parent.getToken().tokenText)) { return parent; } parent = parent.parent; } return undefined; } getAncestors(includeTypes, pattern = /.*/) { const ancestors = []; let parent = this.parent; while (parent && parent.isNotType(PddlTokenizer_1.PddlTokenType.Document)) { if (parent.isAnyOf(includeTypes) && pattern.test(parent.getToken().tokenText)) { ancestors.push(parent); } parent = parent.parent; } return ancestors; } findParametrisableScope(parameterName) { // eslint-disable-next-line @typescript-eslint/no-this-alias let node = this; while (!node.isDocument()) { node = PddlSyntaxNode.findParametrisableAncestor(node); if (!node) { return this.getParent(); } else if (node.declaresParameter(parameterName)) { return node; } } return undefined; } findAllParametrisableScopes() { const scopes = []; // eslint-disable-next-line @typescript-eslint/no-this-alias let node = this; while (node && !node.isDocument()) { node = PddlSyntaxNode.findParametrisableAncestor(node); if (node) { scopes.push(node); } } return scopes; } static findParametrisableAncestor(node) { return node.findAncestor(PddlTokenizer_1.PddlTokenType.OpenBracketOperator, /^\(\s*(:action|:durative-action|:process|:event|:derived|forall|sumall|exists)$/); } getParameterDefinition() { if (this.getToken().tokenText.match(/:action|:durative-action|:process|:event/)) { // this node is expected to have a :parameters keyword return this.getKeywordOpenBracket('parameters'); } else { // this node is expected to have parameters defined inside parentheses const nonWhitespaceChildren = this.getNonWhitespaceChildren(); if (nonWhitespaceChildren.length === 0) { return undefined; } const firstChild = nonWhitespaceChildren[0]; if (!(0, PddlTokenizer_1.isOpenBracket)(firstChild.getToken())) { return undefined; } return firstChild; } } /** * Checks whether this scope node defines given parameter. * @param parameterName parameter name without the `?` sign */ declaresParameter(parameterName) { const parametersNode = this.getParameterDefinition(); const parameterDefinition = parametersNode && parametersNode.getNestedText(); const pattern = new RegExp("\\?" + parameterName + "\\b"); return (parameterDefinition !== undefined) && pattern.test(parameterDefinition); } /** * Expands to the encompassing bracket pair, unless this node is the top level Document node. */ expand() { // eslint-disable-next-line @typescript-eslint/no-this-alias let node = this; while (node && !(0, PddlTokenizer_1.isOpenBracket)(node.getToken()) && !node.isDocument()) { const parentNode = node.getParent(); if (parentNode !== undefined) { node = parentNode; } else { break; } } return node; } /** * Gets all preceding siblings (in order of appearance, not backwards) * @param type node type filter * @param centralNode optional node from which the siblings are split to preceding/following (by default this node is `this` node) */ getPrecedingSiblings(type, centralNode) { const siblings = this.getSiblings(type); const centralNodeStart = (centralNode !== null && centralNode !== void 0 ? centralNode : this).getStart(); const precedingSiblings = siblings.filter(sibling => sibling.getStart() < centralNodeStart); return precedingSiblings; } /** * Gets all following siblings * @param type node type filter * @param centralNode optional node from which the siblings are split to preceding/following (by default this node is `this` node) */ getFollowingSiblings(type, centralNode) { const siblings = this.getSiblings(type); const centralNodeStart = (centralNode !== null && centralNode !== void 0 ? centralNode : this).getStart(); const followingSiblings = siblings.filter(sibling => sibling.getStart() > centralNodeStart); return followingSiblings; } /** * Gets the just preceding sibling, or `undefined`, if none. * @param type node type filter * @param centralNode optional node from which the siblings are split to preceding/following (by default this node is `this` node) */ getPrecedingSibling(type, centralNode) { const precedingSiblings = this.getPrecedingSiblings(type, centralNode); if (precedingSiblings.length > 0) { return precedingSiblings[precedingSiblings.length - 1]; } else { return undefined; } } /** * Gets the just following sibling, or `undefined`, if none. * @param type node type filter * @param centralNode optional node from which the siblings are split to preceding/following (by default this node is `this` node) */ getFollowingSibling(type, centralNode) { const followingSiblings = this.getFollowingSiblings(type, centralNode); if (followingSiblings.length > 0) { return followingSiblings[0]; } else { return undefined; } } /** * Gets the siblings of this node. * @param type optional node type filter * @param centralNode optional node from which the siblings are split to preceding/following (by default this node is `this` node) */ getSiblings(type, pattern = /.*/) { var _a, _b, _c, _d; if (this.isRoot()) { return []; } if (type) { return (_b = (_a = this.getParent()) === null || _a === void 0 ? void 0 : _a.getChildrenOfType(type, pattern)) !== null && _b !== void 0 ? _b : []; } else { return (_d = (_c = this.getParent()) === null || _c === void 0 ? void 0 : _c.getChildren().filter(node => node.getToken().tokenText.match(pattern))) !== null && _d !== void 0 ? _d : []; } } isDocument() { return this.isType(PddlTokenizer_1.PddlTokenType.Document); } isType(type) { return this.getToken().type === type; } isNotType(type) { return this.getToken().type !== type; } isAnyOf(types) { return types.includes(this.getToken().type); } isNoneOf(types) { return !this.isAnyOf(types); } isNumericExpression() { return ['(=', '(>', '(<', '(>=', '(<=', '(+', '(-', '(/', '(*'].includes(this.getToken().tokenText.replace(' ', '')); } isLogicalExpression() { return ['(and', '(or', '(not'].includes(this.getToken().tokenText.replace(' ', '')); } isTemporalExpression() { return ['(at start', '(at end', '(over all'].includes(this.getToken().tokenText.replace(/ /g, ' ')); } toString() { return `${this.token.type}: text: '${this.token.tokenText.split(/\r?\n/).join('\\n')}', range: ${this.getStart()}~${this.getEnd()}}`; } } exports.PddlSyntaxNode = PddlSyntaxNode; /** Specialized tree node for open/close bracket pair. */ class PddlBracketNode extends PddlSyntaxNode { constructor() { super(...arguments); this._isClosed = false; } /** * Sets the bracket close token. * @param token pddl bracket close token */ setCloseBracket(token) { this._isClosed = true; this.closeToken = token; this.addChild(new PddlSyntaxNode(token, this)); this.recalculateEnd(token); } getCloseBracket() { return this.closeToken; } get isClosed() { return this._isClosed; } getNestedChildren() { return this.getChildren() .filter(child => child.getToken() !== this.closeToken); } getText() { var _a, _b; return super.getText() + ((_b = (_a = this.closeToken) === null || _a === void 0 ? void 0 : _a.tokenText) !== null && _b !== void 0 ? _b : ''); } getNonCommentText() { var _a, _b; return super.getNonCommentText() + ((_b = (_a = this.closeToken) === null || _a === void 0 ? void 0 : _a.tokenText) !== null && _b !== void 0 ? _b : ''); } } exports.PddlBracketNode = PddlBracketNode; //# sourceMappingURL=PddlSyntaxNode.js.map