@rightcapital/phpdoc-parser
Version:
TypeScript version of PHPDoc parser with support for intersection types and generics
147 lines (146 loc) • 8.26 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConstExprParser = void 0;
const const_expr_array_item_node_1 = require("../ast/const-expr/const-expr-array-item-node");
const const_expr_array_node_1 = require("../ast/const-expr/const-expr-array-node");
const const_expr_false_node_1 = require("../ast/const-expr/const-expr-false-node");
const const_expr_float_node_1 = require("../ast/const-expr/const-expr-float-node");
const const_expr_integer_node_1 = require("../ast/const-expr/const-expr-integer-node");
const const_expr_null_node_1 = require("../ast/const-expr/const-expr-null-node");
const const_expr_string_node_1 = require("../ast/const-expr/const-expr-string-node");
const const_expr_true_node_1 = require("../ast/const-expr/const-expr-true-node");
const const_fetch_node_1 = require("../ast/const-expr/const-fetch-node");
const quote_aware_const_expr_string_node_1 = require("../ast/const-expr/quote-aware-const-expr-string-node");
const types_1 = require("../ast/types");
const lexer_1 = require("../lexer/lexer");
const parser_exception_1 = require("./parser-exception");
const string_unescaper_1 = require("./string-unescaper");
class ConstExprParser {
constructor(unescapeStrings = false, quoteAwareConstExprString = false, usedAttributes = {}) {
var _a, _b;
this.unescapeStrings = unescapeStrings;
this.quoteAwareConstExprString = quoteAwareConstExprString;
this.useLinesAttributes = (_a = usedAttributes.lines) !== null && _a !== void 0 ? _a : false;
this.useIndexAttributes = (_b = usedAttributes.indexes) !== null && _b !== void 0 ? _b : false;
}
parse(tokens, trimStrings = false) {
const startLine = tokens.currentTokenLine();
const startIndex = tokens.currentTokenIndex();
if (tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_FLOAT)) {
const value = tokens.currentTokenValue();
tokens.next();
return this.enrichWithAttributes(tokens, new const_expr_float_node_1.ConstExprFloatNode(value.replaceAll('_', '')), startLine, startIndex);
}
if (tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_INTEGER)) {
const value = tokens.currentTokenValue();
tokens.next();
return this.enrichWithAttributes(tokens, new const_expr_integer_node_1.ConstExprIntegerNode(value.replaceAll('_', '')), startLine, startIndex);
}
if (tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_SINGLE_QUOTED_STRING, lexer_1.Lexer.TOKEN_DOUBLE_QUOTED_STRING)) {
let value = tokens.currentTokenValue();
const type = tokens.currentTokenType();
if (trimStrings) {
if (this.unescapeStrings) {
value = string_unescaper_1.StringUnescaper.unescapeString(value);
}
else {
value = value.substring(1, value.length - 1);
}
}
tokens.next();
if (this.quoteAwareConstExprString) {
return this.enrichWithAttributes(tokens, new quote_aware_const_expr_string_node_1.QuoteAwareConstExprStringNode(value, type === lexer_1.Lexer.TOKEN_SINGLE_QUOTED_STRING
? quote_aware_const_expr_string_node_1.QuoteAwareConstExprStringNode.SINGLE_QUOTED
: quote_aware_const_expr_string_node_1.QuoteAwareConstExprStringNode.DOUBLE_QUOTED), startLine, startIndex);
}
return this.enrichWithAttributes(tokens, new const_expr_string_node_1.ConstExprStringNode(value), startLine, startIndex);
}
if (tokens.isCurrentTokenType(lexer_1.Lexer.TOKEN_IDENTIFIER)) {
const identifier = tokens.currentTokenValue();
tokens.next();
switch (identifier.toLowerCase()) {
case 'true':
return this.enrichWithAttributes(tokens, new const_expr_true_node_1.ConstExprTrueNode(), startLine, startIndex);
case 'false':
return this.enrichWithAttributes(tokens, new const_expr_false_node_1.ConstExprFalseNode(), startLine, startIndex);
case 'null':
return this.enrichWithAttributes(tokens, new const_expr_null_node_1.ConstExprNullNode(), startLine, startIndex);
case 'array':
tokens.consumeTokenType(lexer_1.Lexer.TOKEN_OPEN_PARENTHESES);
return this.parseArray(tokens, lexer_1.Lexer.TOKEN_CLOSE_PARENTHESES, startIndex);
}
if (tokens.tryConsumeTokenType(lexer_1.Lexer.TOKEN_DOUBLE_COLON)) {
let classConstantName = '';
let lastType = null;
while (true) {
if (lastType !== lexer_1.Lexer.TOKEN_IDENTIFIER &&
tokens.currentTokenType() === lexer_1.Lexer.TOKEN_IDENTIFIER) {
classConstantName += tokens.currentTokenValue();
tokens.consumeTokenType(lexer_1.Lexer.TOKEN_IDENTIFIER);
lastType = lexer_1.Lexer.TOKEN_IDENTIFIER;
continue;
}
if (lastType !== lexer_1.Lexer.TOKEN_WILDCARD &&
tokens.tryConsumeTokenType(lexer_1.Lexer.TOKEN_WILDCARD)) {
classConstantName += '*';
lastType = lexer_1.Lexer.TOKEN_WILDCARD;
if (tokens.getSkippedHorizontalWhiteSpaceIfAny() !== '') {
break;
}
continue;
}
if (lastType === null) {
tokens.consumeTokenType(lexer_1.Lexer.TOKEN_WILDCARD);
}
break;
}
return this.enrichWithAttributes(tokens, new const_fetch_node_1.ConstFetchNode(identifier, classConstantName), startLine, startIndex);
}
return this.enrichWithAttributes(tokens, new const_fetch_node_1.ConstFetchNode('', identifier), startLine, startIndex);
}
if (tokens.tryConsumeTokenType(lexer_1.Lexer.TOKEN_OPEN_SQUARE_BRACKET)) {
return this.parseArray(tokens, lexer_1.Lexer.TOKEN_CLOSE_SQUARE_BRACKET, startIndex);
}
throw new parser_exception_1.ParserException(tokens.currentTokenValue(), tokens.currentTokenType(), tokens.currentTokenOffset(), lexer_1.Lexer.TOKEN_IDENTIFIER, null, tokens.currentTokenLine());
}
parseArray(tokens, endToken, startIndex) {
const items = [];
const startLine = tokens.currentTokenLine();
if (!tokens.tryConsumeTokenType(endToken)) {
do {
items.push(this.parseArrayItem(tokens));
} while (tokens.tryConsumeTokenType(lexer_1.Lexer.TOKEN_COMMA) &&
!tokens.isCurrentTokenType(endToken));
tokens.consumeTokenType(endToken);
}
return this.enrichWithAttributes(tokens, new const_expr_array_node_1.ConstExprArrayNode(items), startLine, startIndex);
}
parseArrayItem(tokens) {
const startLine = tokens.currentTokenLine();
const startIndex = tokens.currentTokenIndex();
const expr = this.parse(tokens);
let key;
let value;
if (tokens.tryConsumeTokenType(lexer_1.Lexer.TOKEN_DOUBLE_ARROW)) {
key = expr;
value = this.parse(tokens);
}
else {
key = null;
value = expr;
}
return this.enrichWithAttributes(tokens, new const_expr_array_item_node_1.ConstExprArrayItemNode(key, value), startLine, startIndex);
}
enrichWithAttributes(tokens, node, startLine, startIndex) {
if (this.useLinesAttributes) {
node.setAttribute(types_1.Attribute.START_LINE, startLine);
node.setAttribute(types_1.Attribute.END_LINE, tokens.currentTokenLine());
}
if (this.useIndexAttributes) {
node.setAttribute(types_1.Attribute.START_INDEX, startIndex);
node.setAttribute(types_1.Attribute.END_INDEX, tokens.endIndexOfLastRelevantToken());
}
return node;
}
}
exports.ConstExprParser = ConstExprParser;