jsdoc-type-pratt-parser
Advanced tools
Comparing version 2.0.0 to 2.0.1
@@ -1,2 +0,2 @@ | ||
import { GrammarFactory } from './Grammar'; | ||
export declare const baseGrammar: GrammarFactory; | ||
import { Grammar } from './Grammar'; | ||
export declare const baseGrammar: Grammar; |
@@ -1,2 +0,2 @@ | ||
import { GrammarFactory } from './Grammar'; | ||
export declare const closureGrammar: GrammarFactory; | ||
import { Grammar } from './Grammar'; | ||
export declare const closureGrammar: Grammar; |
import { InfixParslet, PrefixParslet } from '../parslets/Parslet'; | ||
export interface Grammar { | ||
export declare type Grammar = () => { | ||
prefixParslets: PrefixParslet[]; | ||
infixParslets: InfixParslet[]; | ||
} | ||
export declare type GrammarFactory = () => Grammar; | ||
}; |
@@ -1,2 +0,2 @@ | ||
import { GrammarFactory } from './Grammar'; | ||
export declare const jsdocGrammar: GrammarFactory; | ||
import { Grammar } from './Grammar'; | ||
export declare const jsdocGrammar: Grammar; |
@@ -1,2 +0,2 @@ | ||
import { GrammarFactory } from './Grammar'; | ||
export declare const moduleGrammar: GrammarFactory; | ||
import { Grammar } from './Grammar'; | ||
export declare const moduleGrammar: Grammar; |
@@ -1,2 +0,2 @@ | ||
import { GrammarFactory } from './Grammar'; | ||
export declare const typescriptGrammar: GrammarFactory; | ||
import { Grammar } from './Grammar'; | ||
export declare const typescriptGrammar: Grammar; |
@@ -8,2 +8,7 @@ import { Token, TokenType } from './lexer/Token'; | ||
import { IntermediateResult } from './result/IntermediateResult'; | ||
interface ParserOptions { | ||
grammar: Grammar; | ||
lexer?: Lexer; | ||
parent?: Parser; | ||
} | ||
export declare class Parser { | ||
@@ -13,3 +18,4 @@ private readonly prefixParslets; | ||
private readonly lexer; | ||
constructor(grammar: Grammar, lexer?: Lexer); | ||
private readonly parent?; | ||
constructor({ grammar, lexer, parent }: ParserOptions); | ||
parseText(text: string): TerminalResult; | ||
@@ -22,3 +28,3 @@ getPrefixParslet(): PrefixParslet | undefined; | ||
parseInfixIntermediateType(result: IntermediateResult, precedence: Precedence): IntermediateResult; | ||
consume(type: TokenType): boolean; | ||
consume(types: TokenType | TokenType[]): boolean; | ||
getToken(): Token; | ||
@@ -28,2 +34,4 @@ peekToken(): Token; | ||
getLexer(): Lexer; | ||
getParent(): Parser | undefined; | ||
} | ||
export {}; |
@@ -6,8 +6,11 @@ import { PrefixParslet } from './Parslet'; | ||
import { TerminalResult } from '../result/TerminalResult'; | ||
import { Grammar } from '../grammars/Grammar'; | ||
interface ObjectParsletOptions { | ||
objectFieldGrammar: Grammar; | ||
allowKeyTypes: boolean; | ||
} | ||
export declare class ObjectParslet implements PrefixParslet { | ||
private readonly objectFieldGrammar; | ||
private readonly allowKeyTypes; | ||
constructor(opts: ObjectParsletOptions); | ||
constructor({ objectFieldGrammar, allowKeyTypes }: ObjectParsletOptions); | ||
accepts(type: TokenType): boolean; | ||
@@ -14,0 +17,0 @@ getPrecedence(): Precedence; |
@@ -135,3 +135,3 @@ import { JsdocObjectKeyValueResult, KeyValueResult, PropertyResult } from './NonTerminalResult'; | ||
meta: { | ||
separator: 'comma' | 'semicolon'; | ||
separator: 'comma' | 'semicolon' | undefined; | ||
}; | ||
@@ -138,0 +138,0 @@ } |
@@ -7,2 +7,9 @@ import 'mocha'; | ||
export interface Fixture { | ||
/** | ||
* The input that should be parsed | ||
*/ | ||
input: string; | ||
/** | ||
* The {@link ParseMode}s that the expression is expected to get parsed in. In all other modes it is expected to fail. | ||
*/ | ||
modes: ParseMode[]; | ||
@@ -15,10 +22,23 @@ jtp?: { | ||
}; | ||
/** | ||
* The expected parse result object. If you expect different parse results for different parse modes please use | ||
* `diffExpected`. | ||
*/ | ||
expected?: TerminalResult; | ||
/** | ||
* The expected parse results objects for different modes. If a mode is included in `modes` and as a key of | ||
* `diffExpected` the object in `diffExpected` is used over the result in `expected`. | ||
*/ | ||
diffExpected?: { | ||
[K in ParseMode]?: TerminalResult; | ||
}; | ||
input: string; | ||
/** | ||
* If the stringified output differs from the input it can be provided here. These are mostly whitespace differences. | ||
*/ | ||
stringified?: string; | ||
} | ||
/** | ||
* Function to run all relevant tests for a {@link Fixture}. | ||
*/ | ||
export declare function testFixture(fixture: Fixture): void; | ||
export {}; |
{ | ||
"name": "jsdoc-type-pratt-parser", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -32,2 +32,5 @@ [![Npm Package](https://badgen.net/npm/v/jsdoc-type-pratt-parser)](https://www.npmjs.com/package/jsdoc-type-pratt-parser) | ||
Transforms | ||
---------- | ||
This library supports compatibility modes for catharsis and jsdoctypeparser. The provided transform functions attempt to | ||
@@ -34,0 +37,0 @@ transform the output to the expected output of the target library. This will not always be the same as some types are |
@@ -1,2 +0,1 @@ | ||
import { GrammarFactory } from './Grammar' | ||
import { UnionParslet } from '../parslets/UnionParslets' | ||
@@ -11,4 +10,5 @@ import { SpecialTypesParslet } from '../parslets/SpecialTypesParslet' | ||
import { NotNullableParslet } from '../parslets/NotNullableParslet' | ||
import { Grammar } from './Grammar' | ||
export const baseGrammar: GrammarFactory = () => { | ||
export const baseGrammar: Grammar = () => { | ||
return { | ||
@@ -15,0 +15,0 @@ prefixParslets: [ |
@@ -1,2 +0,1 @@ | ||
import { GrammarFactory } from './Grammar' | ||
import { baseGrammar } from './baseGrammar' | ||
@@ -12,14 +11,36 @@ import { FunctionParslet } from '../parslets/FunctionParslet' | ||
import { SymbolParslet } from '../parslets/SymbolParslet' | ||
import { combineGrammars } from './combineGrammars' | ||
import { NullableInfixParslet, NullablePrefixParslet } from '../parslets/NullableParslets' | ||
import { Grammar } from './Grammar' | ||
import { StringValueParslet } from '../parslets/StringValueParslet' | ||
import { NumberParslet } from '../parslets/NumberParslet' | ||
import { OptionalParslet } from '../parslets/OptionalParslet' | ||
export const closureGrammar: GrammarFactory = () => { | ||
const { | ||
prefixParslets, | ||
infixParslets | ||
} = baseGrammar() | ||
export const closureGrammar = combineGrammars(baseGrammar, () => { | ||
const objectFieldGrammar: Grammar = () => ({ | ||
prefixParslets: [ | ||
new NameParslet({ | ||
allowedAdditionalTokens: ['module', 'keyof', 'event', 'external'] | ||
}), | ||
new NullablePrefixParslet(), | ||
new OptionalParslet(), | ||
new StringValueParslet(), | ||
new NumberParslet() | ||
], | ||
infixParslets: [ | ||
new NullableInfixParslet(), | ||
new OptionalParslet(), | ||
new KeyValueParslet({ | ||
allowKeyTypes: false, | ||
allowOptional: false, | ||
allowReadonly: false | ||
}) | ||
] | ||
}) | ||
return { | ||
prefixParslets: [ | ||
...prefixParslets, | ||
new ObjectParslet({ | ||
allowKeyTypes: false | ||
allowKeyTypes: false, | ||
objectFieldGrammar | ||
}), | ||
@@ -38,2 +59,3 @@ new NameParslet({ | ||
}), | ||
// additional name parslet is needed for some special cases | ||
new NameParslet({ | ||
@@ -47,3 +69,2 @@ allowedAdditionalTokens: ['keyof'] | ||
infixParslets: [ | ||
...infixParslets, | ||
new NamePathParslet({ | ||
@@ -60,2 +81,2 @@ allowJsdocNamePaths: true | ||
} | ||
} | ||
}) |
import { InfixParslet, PrefixParslet } from '../parslets/Parslet' | ||
export interface Grammar { | ||
export type Grammar = () => { | ||
prefixParslets: PrefixParslet[] | ||
infixParslets: InfixParslet[] | ||
} | ||
export type GrammarFactory = () => Grammar |
@@ -1,2 +0,1 @@ | ||
import { GrammarFactory } from './Grammar' | ||
import { SymbolParslet } from '../parslets/SymbolParslet' | ||
@@ -13,15 +12,8 @@ import { ArrayBracketsParslet } from '../parslets/ArrayBracketsParslet' | ||
import { ObjectParslet } from '../parslets/ObjectParslet' | ||
import { combineGrammars } from './combineGrammars' | ||
import { Grammar } from './Grammar' | ||
export const jsdocGrammar: GrammarFactory = () => { | ||
const { | ||
prefixParslets, | ||
infixParslets | ||
} = baseGrammar() | ||
return { | ||
export const jsdocGrammar: Grammar = () => { | ||
const jsdocBaseGrammar = combineGrammars(baseGrammar, () => ({ | ||
prefixParslets: [ | ||
...prefixParslets, | ||
new ObjectParslet({ | ||
allowKeyTypes: true | ||
}), | ||
new FunctionParslet({ | ||
@@ -44,3 +36,2 @@ allowWithoutParenthesis: true, | ||
infixParslets: [ | ||
...infixParslets, | ||
new SymbolParslet(), | ||
@@ -60,3 +51,22 @@ new ArrayBracketsParslet(), | ||
] | ||
} | ||
})) | ||
return combineGrammars(jsdocBaseGrammar, () => ({ | ||
prefixParslets: [ | ||
new ObjectParslet({ | ||
// jsdoc syntax allows full types as keys, so we need to pull in the full grammar here | ||
// we leave out the object type deliberately | ||
objectFieldGrammar: combineGrammars(() => ({ | ||
prefixParslets: [ | ||
new NameParslet({ | ||
allowedAdditionalTokens: ['module'] | ||
}) | ||
], | ||
infixParslets: [] | ||
}), jsdocBaseGrammar), | ||
allowKeyTypes: true | ||
}) | ||
], | ||
infixParslets: [] | ||
}))() | ||
} |
@@ -1,2 +0,2 @@ | ||
import { GrammarFactory } from './Grammar' | ||
import { Grammar } from './Grammar' | ||
import { SpecialNamePathParslet } from '../parslets/SpecialNamePathParslet' | ||
@@ -8,3 +8,3 @@ import { NamePathParslet } from '../parslets/NamePathParslet' | ||
export const moduleGrammar: GrammarFactory = () => ({ | ||
export const moduleGrammar: Grammar = () => ({ | ||
prefixParslets: [ | ||
@@ -11,0 +11,0 @@ new SpecialNamePathParslet({ |
import { TupleParslet } from '../parslets/TupleParslet' | ||
import { GrammarFactory } from './Grammar' | ||
import { ArrayBracketsParslet } from '../parslets/ArrayBracketsParslet' | ||
@@ -19,22 +18,37 @@ import { baseGrammar } from './baseGrammar' | ||
import { ObjectParslet } from '../parslets/ObjectParslet' | ||
import { moduleGrammar } from './moduleGrammar' | ||
import { SpecialNamePathParslet } from '../parslets/SpecialNamePathParslet' | ||
import { ReadonlyPropertyParslet } from '../parslets/ReadonlyPropertyParslet' | ||
import { combineGrammars } from './combineGrammars' | ||
import { Grammar } from './Grammar' | ||
import { NullableInfixParslet, NullablePrefixParslet } from '../parslets/NullableParslets' | ||
import { NumberParslet } from '../parslets/NumberParslet' | ||
import { OptionalParslet } from '../parslets/OptionalParslet' | ||
export const typescriptGrammar: GrammarFactory = () => { | ||
const { | ||
prefixParslets, | ||
infixParslets | ||
} = baseGrammar() | ||
export const typescriptGrammar = combineGrammars(baseGrammar, () => { | ||
const objectFieldGrammar: Grammar = () => ({ | ||
prefixParslets: [ | ||
new NameParslet({ | ||
allowedAdditionalTokens: ['module', 'event', 'keyof', 'event', 'external'] | ||
}), | ||
new NullablePrefixParslet(), | ||
new OptionalParslet(), | ||
new StringValueParslet(), | ||
new NumberParslet() | ||
], | ||
infixParslets: [ | ||
new NullableInfixParslet(), | ||
new OptionalParslet(), | ||
new KeyValueParslet({ | ||
allowKeyTypes: false, | ||
allowOptional: true, | ||
allowReadonly: true | ||
}) | ||
] | ||
}) | ||
// module seems not to be supported | ||
return { | ||
parallel: [ | ||
moduleGrammar() | ||
], | ||
prefixParslets: [ | ||
...prefixParslets, | ||
new ObjectParslet({ | ||
allowKeyTypes: false | ||
allowKeyTypes: false, | ||
objectFieldGrammar | ||
}), | ||
@@ -65,3 +79,2 @@ new TypeOfParslet(), | ||
infixParslets: [ | ||
...infixParslets, | ||
new ArrayBracketsParslet(), | ||
@@ -80,2 +93,2 @@ new ArrowFunctionParslet(), | ||
} | ||
} | ||
}) |
@@ -10,5 +10,11 @@ import { Parser } from './Parser' | ||
const parsers = { | ||
jsdoc: new Parser(jsdocGrammar()), | ||
closure: new Parser(closureGrammar()), | ||
typescript: new Parser(typescriptGrammar()) | ||
jsdoc: new Parser({ | ||
grammar: jsdocGrammar | ||
}), | ||
closure: new Parser({ | ||
grammar: closureGrammar | ||
}), | ||
typescript: new Parser({ | ||
grammar: typescriptGrammar | ||
}) | ||
} | ||
@@ -15,0 +21,0 @@ |
@@ -11,2 +11,8 @@ import { EarlyEndOfParseError, NoParsletFoundError } from './errors' | ||
interface ParserOptions { | ||
grammar: Grammar | ||
lexer?: Lexer | ||
parent?: Parser | ||
} | ||
export class Parser { | ||
@@ -17,10 +23,13 @@ private readonly prefixParslets: PrefixParslet[] | ||
private readonly lexer: Lexer | ||
private readonly parent?: Parser | ||
constructor (grammar: Grammar, lexer?: Lexer) { | ||
constructor ({ grammar, lexer, parent }: ParserOptions) { | ||
this.lexer = lexer ?? new Lexer() | ||
this.parent = parent | ||
const { | ||
prefixParslets, | ||
infixParslets | ||
} = grammar | ||
} = grammar() | ||
@@ -35,3 +44,3 @@ this.prefixParslets = prefixParslets | ||
const result = this.parseType(Precedence.ALL) | ||
if (!this.consume('EOF')) { | ||
if (this.getToken().type !== 'EOF') { | ||
throw new EarlyEndOfParseError(this.getToken()) | ||
@@ -83,4 +92,7 @@ } | ||
public consume (type: TokenType): boolean { | ||
if (this.lexer.token().type !== type) { | ||
public consume (types: TokenType|TokenType[]): boolean { | ||
if (!Array.isArray(types)) { | ||
types = [types] | ||
} | ||
if (!types.includes(this.lexer.token().type)) { | ||
return false | ||
@@ -107,2 +119,6 @@ } | ||
} | ||
getParent (): Parser | undefined { | ||
return this.parent | ||
} | ||
} |
@@ -49,2 +49,5 @@ import { InfixParslet } from './Parslet' | ||
// object parslet uses a special grammar and for the value we want to switch back to the parent | ||
parser = parser.getParent() ?? parser | ||
if (left.type === 'JsdocTypeNumber' || left.type === 'JsdocTypeName' || left.type === 'JsdocTypeStringValue') { | ||
@@ -51,0 +54,0 @@ parser.consume(':') |
@@ -23,3 +23,4 @@ import { InfixParslet } from './Parslet' | ||
'StringValue', | ||
'Number' | ||
'Number', | ||
'module' | ||
] | ||
@@ -26,0 +27,0 @@ } |
@@ -7,4 +7,6 @@ import { PrefixParslet } from './Parslet' | ||
import { ObjectResult, TerminalResult } from '../result/TerminalResult' | ||
import { Grammar } from '../grammars/Grammar' | ||
interface ObjectParsletOptions { | ||
objectFieldGrammar: Grammar | ||
allowKeyTypes: boolean | ||
@@ -14,6 +16,8 @@ } | ||
export class ObjectParslet implements PrefixParslet { | ||
private readonly objectFieldGrammar: Grammar | ||
private readonly allowKeyTypes: boolean | ||
constructor (opts: ObjectParsletOptions) { | ||
this.allowKeyTypes = opts.allowKeyTypes | ||
constructor ({ objectFieldGrammar, allowKeyTypes }: ObjectParsletOptions) { | ||
this.objectFieldGrammar = objectFieldGrammar | ||
this.allowKeyTypes = allowKeyTypes | ||
} | ||
@@ -42,5 +46,17 @@ | ||
const lexer = parser.getLexer() | ||
const fieldParser = new Parser({ | ||
grammar: this.objectFieldGrammar, | ||
lexer: lexer, | ||
parent: parser | ||
}) | ||
while (true) { | ||
let field = parser.parseIntermediateType(Precedence.OBJECT) | ||
let field = fieldParser.parseIntermediateType(Precedence.OBJECT) | ||
if (field === undefined && this.allowKeyTypes) { | ||
field = parser.parseIntermediateType(Precedence.OBJECT) | ||
} | ||
let optional = false | ||
@@ -83,3 +99,3 @@ if (field.type === 'JsdocTypeNullable') { | ||
result.meta.separator = separator ?? 'comma' | ||
result.meta.separator = separator ?? 'comma' // TODO: use undefined here | ||
@@ -86,0 +102,0 @@ if (!parser.consume('}')) { |
@@ -38,3 +38,6 @@ import { PrefixParslet } from './Parslet' | ||
const moduleParser = new Parser(moduleGrammar(), parser.getLexer()) | ||
const moduleParser = new Parser({ | ||
grammar: moduleGrammar, | ||
lexer: parser.getLexer() | ||
}) | ||
@@ -41,0 +44,0 @@ let result: SpecialNamePath |
@@ -175,3 +175,3 @@ import { JsdocObjectKeyValueResult, KeyValueResult, PropertyResult } from './NonTerminalResult' | ||
meta: { | ||
separator: 'comma' | 'semicolon' | ||
separator: 'comma' | 'semicolon' | undefined | ||
} | ||
@@ -178,0 +178,0 @@ } |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
237217
117
6721
146