Socket
Socket
Sign inDemoInstall

jsdoc-type-pratt-parser

Package Overview
Dependencies
Maintainers
2
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsdoc-type-pratt-parser - npm Package Compare versions

Comparing version 2.2.5 to 3.0.0

18

dist/src/lexer/Lexer.d.ts
import { Token } from './Token';
export declare class Lexer {
private text;
private current;
private next;
private previous;
lex(text: string): void;
token(): Token;
peek(): Token;
last(): Token | undefined;
advance(): void;
private read;
private readonly text;
readonly current: Token;
readonly next: Token;
readonly previous: Token | undefined;
static create(text: string): Lexer;
private constructor();
private static read;
advance(): Lexer;
}

@@ -1,2 +0,1 @@

import { TokenType } from './lexer/Token';
import { Lexer } from './lexer/Lexer';

@@ -7,16 +6,13 @@ import { Grammar } from './grammars/Grammar';

import { IntermediateResult } from './result/IntermediateResult';
interface ParserOptions {
grammar: Grammar;
lexer?: Lexer;
parent?: Parser;
}
import { TokenType } from './lexer/Token';
export declare class Parser {
private readonly grammar;
private readonly lexer;
private readonly parent?;
constructor({ grammar, lexer, parent }: ParserOptions);
private _lexer;
readonly parent?: Parser;
constructor(grammar: Grammar, textOrLexer: string | Lexer, parent?: Parser);
get lexer(): Lexer;
/**
* Parses a given string and throws an error if the parse ended before the end of the string.
*/
parseText(text: string): RootResult;
parse(): RootResult;
/**

@@ -27,6 +23,2 @@ * Parses with the current lexer and asserts that the result is a {@link RootResult}.

/**
* Tries to parse the current state with all parslets in the grammar and returns the first non null result.
*/
private tryParslets;
/**
* The main parsing function. First it tries to parse the current state in the prefix step, and then it continues

@@ -40,4 +32,8 @@ * to parse the state in the infix step.

*/
parseInfixIntermediateType(result: IntermediateResult, precedence: Precedence): IntermediateResult;
parseInfixIntermediateType(left: IntermediateResult, precedence: Precedence): IntermediateResult;
/**
* Tries to parse the current state with all parslets in the grammar and returns the first non null result.
*/
private tryParslets;
/**
* If the given type equals the current type of the {@link Lexer} advance the lexer. Return true if the lexer was

@@ -47,5 +43,3 @@ * advanced.

consume(types: TokenType | TokenType[]): boolean;
getLexer(): Lexer;
getParent(): Parser | undefined;
acceptLexerState(parser: Parser): void;
}
export {};
{
"name": "jsdoc-type-pratt-parser",
"version": "2.2.5",
"version": "3.0.0",
"description": "",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -173,50 +173,29 @@ import { Token, TokenType } from './Token'

export class Lexer {
private text: string = ''
private readonly text: string = ''
public readonly current: Token
public readonly next: Token
public readonly previous: Token | undefined
private current: Token | undefined
private next: Token | undefined
private previous: Token | undefined
public static create (text: string): Lexer {
const current = this.read(text)
text = current.text
const next = this.read(text)
text = next.text
return new Lexer(text, undefined, current.token, next.token)
}
lex (text: string): void {
private constructor (text: string, previous: Token | undefined, current: Token, next: Token) {
this.text = text
this.current = undefined
this.next = undefined
this.advance()
this.previous = previous
this.current = current
this.next = next
}
token (): Token {
if (this.current === undefined) {
throw new Error('Lexer not lexing')
}
return this.current
}
peek (): Token {
if (this.next === undefined) {
this.next = this.read()
}
return this.next
}
last (): Token | undefined {
return this.previous
}
advance (): void {
this.previous = this.current
if (this.next !== undefined) {
this.current = this.next
this.next = undefined
return
}
this.current = this.read()
}
private read (): Token {
const text = this.text.trim()
private static read (text: string): { text: string, token: Token } {
text = text.trim()
for (const rule of rules) {
const token = rule(text)
if (token !== null) {
this.text = text.slice(token.text.length)
return token
text = text.slice(token.text.length)
return { text, token }
}

@@ -226,2 +205,7 @@ }

}
advance (): Lexer {
const next = Lexer.read(this.text)
return new Lexer(next.text, this.current, this.next, next.token)
}
}

@@ -9,14 +9,2 @@ import { Parser } from './Parser'

const parsers = {
jsdoc: new Parser({
grammar: jsdocGrammar
}),
closure: new Parser({
grammar: closureGrammar
}),
typescript: new Parser({
grammar: typescriptGrammar
})
}
/**

@@ -28,3 +16,10 @@ * This function parses the given expression in the given mode and produces a {@link RootResult}.

export function parse (expression: string, mode: ParseMode): RootResult {
return parsers[mode].parseText(expression)
switch (mode) {
case 'closure':
return (new Parser(closureGrammar, expression)).parse()
case 'jsdoc':
return (new Parser(jsdocGrammar, expression)).parse()
case 'typescript':
return (new Parser(typescriptGrammar, expression)).parse()
}
}

@@ -43,3 +38,3 @@

try {
return parsers[mode].parseText(expression)
return parse(expression, mode)
} catch (e) {

@@ -46,0 +41,0 @@ error = e

import { EarlyEndOfParseError, NoParsletFoundError } from './errors'
import { TokenType } from './lexer/Token'
import { Lexer } from './lexer/Lexer'

@@ -9,21 +8,21 @@ import { Grammar } from './grammars/Grammar'

import { IntermediateResult } from './result/IntermediateResult'
import { TokenType } from './lexer/Token'
interface ParserOptions {
grammar: Grammar
lexer?: Lexer
parent?: Parser
}
export class Parser {
private readonly grammar: Grammar
private _lexer: Lexer
public readonly parent?: Parser
private readonly lexer: Lexer
private readonly parent?: Parser
constructor ({ grammar, lexer, parent }: ParserOptions) {
this.lexer = lexer ?? new Lexer()
constructor (grammar: Grammar, textOrLexer: string | Lexer, parent?: Parser) {
this.grammar = grammar
if (typeof textOrLexer === 'string') {
this._lexer = Lexer.create(textOrLexer)
} else {
this._lexer = textOrLexer
}
this.parent = parent
}
this.grammar = grammar
get lexer (): Lexer {
return this._lexer
}

@@ -34,7 +33,6 @@

*/
parseText (text: string): RootResult {
this.lexer.lex(text)
parse (): RootResult {
const result = this.parseType(Precedence.ALL)
if (this.lexer.token().type !== 'EOF') {
throw new EarlyEndOfParseError(this.lexer.token())
if (this.lexer.current.type !== 'EOF') {
throw new EarlyEndOfParseError(this.lexer.current)
}

@@ -52,15 +50,2 @@ return result

/**
* Tries to parse the current state with all parslets in the grammar and returns the first non null result.
*/
private tryParslets (precedence: Precedence, left: IntermediateResult | null): IntermediateResult | null {
for (const parslet of this.grammar) {
const result = parslet(this, precedence, left)
if (result !== null) {
return result
}
}
return null
}
/**
* The main parsing function. First it tries to parse the current state in the prefix step, and then it continues

@@ -70,6 +55,6 @@ * to parse the state in the infix step.

public parseIntermediateType (precedence: Precedence): IntermediateResult {
const result = this.tryParslets(precedence, null)
const result = this.tryParslets(null, precedence)
if (result === null) {
throw new NoParsletFoundError(this.lexer.token())
throw new NoParsletFoundError(this.lexer.current)
}

@@ -84,35 +69,46 @@

*/
public parseInfixIntermediateType (result: IntermediateResult, precedence: Precedence): IntermediateResult {
let newResult = this.tryParslets(precedence, result)
public parseInfixIntermediateType (left: IntermediateResult, precedence: Precedence): IntermediateResult {
let result = this.tryParslets(left, precedence)
while (newResult !== null) {
result = newResult
newResult = this.tryParslets(precedence, result)
while (result !== null) {
left = result
result = this.tryParslets(left, precedence)
}
return result
return left
}
/**
* Tries to parse the current state with all parslets in the grammar and returns the first non null result.
*/
private tryParslets (left: IntermediateResult | null, precedence: Precedence): IntermediateResult | null {
for (const parslet of this.grammar) {
const result = parslet(this, precedence, left)
if (result !== null) {
return result
}
}
return null
}
/**
* If the given type equals the current type of the {@link Lexer} advance the lexer. Return true if the lexer was
* advanced.
*/
public consume (types: TokenType|TokenType[]): boolean {
public consume (types: TokenType | TokenType[]): boolean {
if (!Array.isArray(types)) {
types = [types]
}
if (!types.includes(this.lexer.token().type)) {
if (types.includes(this.lexer.current.type)) {
this._lexer = this.lexer.advance()
return true
} else {
return false
}
this.lexer.advance()
return true
}
getLexer (): Lexer {
return this.lexer
public acceptLexerState (parser: Parser): void {
this._lexer = parser.lexer
}
getParent (): Parser | undefined {
return this.parent
}
}

@@ -41,3 +41,3 @@ import { composeParslet, ParsletFunction } from './Parslet'

const hasParenthesis = parser.getLexer().token().type === '('
const hasParenthesis = parser.lexer.current.type === '('

@@ -44,0 +44,0 @@ if (!hasParenthesis) {

@@ -30,6 +30,7 @@ import { composeParslet, ParsletFunction } from './Parslet'

// object parslet uses a special grammar and for the value we want to switch back to the parent
parser = parser.getParent() ?? parser
const parentParser = parser.parent ?? parser
parentParser.acceptLexerState(parser)
if (left.type === 'JsdocTypeNumber' || left.type === 'JsdocTypeName' || left.type === 'JsdocTypeStringValue') {
parser.consume(':')
parentParser.consume(':')

@@ -41,6 +42,9 @@ let quote

const right = parentParser.parseType(Precedence.KEY_VALUE)
parser.acceptLexerState(parentParser)
return {
type: 'JsdocTypeKeyValue',
key: left.value.toString(),
right: parser.parseType(Precedence.KEY_VALUE),
right: right,
optional: optional,

@@ -58,8 +62,11 @@ readonly: readonlyProperty,

parser.consume(':')
parentParser.consume(':')
const right = parentParser.parseType(Precedence.KEY_VALUE)
parser.acceptLexerState(parentParser)
return {
type: 'JsdocTypeKeyValue',
left: assertRootResult(left),
right: parser.parseType(Precedence.KEY_VALUE),
right: right,
meta: {

@@ -66,0 +73,0 @@ hasLeftSideExpression: true

@@ -11,3 +11,3 @@ import { TokenType } from '../lexer/Token'

parsePrefix: parser => {
const { type, text } = parser.getLexer().token()
const { type, text } = parser.lexer.current
parser.consume(type)

@@ -14,0 +14,0 @@

@@ -18,4 +18,4 @@ import { ParsletFunction } from './Parslet'

}
const type = parser.getLexer().token().type
const next = parser.getLexer().peek().type
const type = parser.lexer.current.type
const next = parser.lexer.next.type

@@ -46,9 +46,7 @@ const accept = (type === '.' && next !== '<') ||

const pathParser = pathGrammar !== null
? new Parser({
grammar: pathGrammar,
lexer: parser.getLexer()
})
? new Parser(pathGrammar, parser.lexer, parser)
: parser
const parsed = pathParser.parseIntermediateType(Precedence.NAME_PATH)
parser.acceptLexerState(pathParser)
let right: PropertyResult | SpecialNamePath<'event'>

@@ -96,3 +94,3 @@

if (brackets && !parser.consume(']')) {
const token = parser.getLexer().token()
const token = parser.lexer.current
throw new Error(`Unterminated square brackets. Next token is '${token.type}' ` +

@@ -99,0 +97,0 @@ `with text '${token.text}'`)

@@ -7,4 +7,4 @@ import { ParsletFunction } from './Parslet'

export const nullableParslet: ParsletFunction = (parser, precedence, left) => {
const type = parser.getLexer().token().type
const next = parser.getLexer().peek().type
const type = parser.lexer.current.type
const next = parser.lexer.next.type

@@ -11,0 +11,0 @@ const accept = ((left == null) && type === '?' && !isQuestionMarkUnknownType(next)) ||

@@ -7,3 +7,3 @@ import { composeParslet } from './Parslet'

parsePrefix: parser => {
const value = parseFloat(parser.getLexer().token().text)
const value = parseFloat(parser.lexer.current.text)
parser.consume('Number')

@@ -10,0 +10,0 @@ return {

@@ -28,12 +28,8 @@ import { composeParslet, ParsletFunction } from './Parslet'

const lexer = parser.getLexer()
const fieldParser = new Parser(objectFieldGrammar, parser.lexer, parser)
const fieldParser = new Parser({
grammar: objectFieldGrammar,
lexer: lexer,
parent: parser
})
while (true) {
fieldParser.acceptLexerState(parser)
let field = fieldParser.parseIntermediateType(Precedence.OBJECT)
parser.acceptLexerState(fieldParser)

@@ -79,3 +75,3 @@ if (field === undefined && allowKeyTypes) {

}
const type = parser.getLexer().token().type
const type = parser.lexer.current.type
if (type === '}') {

@@ -82,0 +78,0 @@ break

@@ -32,7 +32,7 @@ import { TokenType } from '../lexer/Token'

export function composeParslet (options: ComposeParsletOptions): ParsletFunction {
const parslet = (parser: Parser, curPrecedence: Precedence, left: IntermediateResult | null): IntermediateResult | null => {
const type = parser.getLexer().token().type
const next = parser.getLexer().peek().type
const parslet: ParsletFunction = (parser, curPrecedence, left) => {
const type = parser.lexer.current.type
const next = parser.lexer.next.type
if (left == null) {
if (left === null) {
if ('parsePrefix' in options) {

@@ -50,3 +50,2 @@ if (options.accept(type, next)) {

}
return null

@@ -53,0 +52,0 @@ }

@@ -17,3 +17,3 @@ import { composeParslet, ParsletFunction } from './Parslet'

parsePrefix: parser => {
const type = parser.getLexer().token().type as SpecialNamePathType
const type = parser.lexer.current.type as SpecialNamePathType
parser.consume(type)

@@ -28,10 +28,5 @@

const moduleParser = new Parser({
grammar: pathGrammar,
lexer: parser.getLexer()
})
let result: SpecialNamePath
let token = parser.getLexer().token()
let token = parser.lexer.current
if (parser.consume('StringValue')) {

@@ -51,3 +46,3 @@ result = {

value += token.text
token = parser.getLexer().token()
token = parser.lexer.current
}

@@ -64,5 +59,9 @@ result = {

return assertRootResult(moduleParser.parseInfixIntermediateType(result, Precedence.ALL))
const moduleParser = new Parser(pathGrammar, parser.lexer, parser)
const moduleResult = moduleParser.parseInfixIntermediateType(result, Precedence.ALL)
parser.acceptLexerState(moduleParser)
return assertRootResult(moduleResult)
}
})
}

@@ -33,4 +33,4 @@ import { composeParslet } from './Parslet'

throw new Error('Unacceptable token: ' + parser.getLexer().token().text)
throw new Error('Unacceptable token: ' + parser.lexer.current.text)
}
})

@@ -7,3 +7,3 @@ import { composeParslet } from './Parslet'

parsePrefix: parser => {
const text = parser.getLexer().token().text
const text = parser.lexer.current.text
parser.consume('StringValue')

@@ -10,0 +10,0 @@ return {

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc