UNPKG

jsdoc-type-pratt-parser

Version:

[![Npm Package](https://badgen.net/npm/v/jsdoc-type-pratt-parser)](https://www.npmjs.com/package/jsdoc-type-pratt-parser) [![Test Status](https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/actions/workflows/test.yml/badge.svg?branch=main)]

115 lines (103 loc) 3.55 kB
import type { ParsletFunction } from './Parslet.js' import { Precedence } from '../Precedence.js' import { assertRootResult } from '../assertTypes.js' import { Parser } from '../Parser.js' import type { NamePathResult, SpecialNamePath } from '../result/RootResult.js' import { UnexpectedTypeError } from '../errors.js' import type { PropertyResult, IndexedAccessIndexResult } from '../result/NonRootResult.js' import type { Grammar } from '../grammars/Grammar.js' export function createNamePathParslet ({ allowSquareBracketsOnAnyType, allowJsdocNamePaths, pathGrammar }: { allowJsdocNamePaths: boolean allowSquareBracketsOnAnyType: boolean pathGrammar: Grammar | null }): ParsletFunction { return function namePathParslet (parser, precedence, left) { if ((left == null) || precedence >= Precedence.NAME_PATH) { return null } const type = parser.lexer.current.type const next = parser.lexer.next.type const accept = (type === '.' && next !== '<') || (type === '[' && (allowSquareBracketsOnAnyType || left.type === 'JsdocTypeName')) || (allowJsdocNamePaths && (type === '~' || type === '#')) if (!accept) { return null } let pathType: NamePathResult['pathType'] let brackets = false if (parser.consume('.')) { pathType = 'property' } else if (parser.consume('[')) { pathType = 'property-brackets' brackets = true } else if (parser.consume('~')) { pathType = 'inner' } else { parser.consume('#') pathType = 'instance' } const pathParser = brackets && allowSquareBracketsOnAnyType ? parser : pathGrammar !== null ? new Parser(pathGrammar, parser.lexer, parser) : parser const parsed = pathParser.parseType(Precedence.NAME_PATH) parser.acceptLexerState(pathParser) let right: PropertyResult | SpecialNamePath<'event'> | IndexedAccessIndexResult switch (parsed.type) { case 'JsdocTypeName': right = { type: 'JsdocTypeProperty', value: parsed.value, meta: { quote: undefined } } break case 'JsdocTypeNumber': right = { type: 'JsdocTypeProperty', value: parsed.value.toString(10), meta: { quote: undefined } } break case 'JsdocTypeStringValue': right = { type: 'JsdocTypeProperty', value: parsed.value, meta: { quote: parsed.meta.quote } } break case 'JsdocTypeSpecialNamePath': if (parsed.specialType === 'event') { right = parsed as SpecialNamePath<'event'> } else { throw new UnexpectedTypeError(parsed, 'Type \'JsdocTypeSpecialNamePath\' is only allowed with specialType \'event\'') } break default: if (!brackets || !allowSquareBracketsOnAnyType) { throw new UnexpectedTypeError(parsed, 'Expecting \'JsdocTypeName\', \'JsdocTypeNumber\', \'JsdocStringValue\' or \'JsdocTypeSpecialNamePath\'') } right = { type: 'JsdocTypeIndexedAccessIndex', right: parsed } } if (brackets && !parser.consume(']')) { const token = parser.lexer.current throw new Error(`Unterminated square brackets. Next token is '${token.type}' ` + `with text '${token.text}'`) } return { type: 'JsdocTypeNamePath', left: assertRootResult(left), right, pathType } } }