UNPKG

13.5 kBTypeScriptView Raw
1/**
2 * @license
3 * Copyright Google LLC All Rights Reserved.
4 *
5 * Use of this source code is governed by an MIT-style license that can be
6 * found in the LICENSE file at https://angular.io/license
7 */
8import { InterpolationConfig } from '../ml_parser/interpolation_config';
9import { InterpolatedAttributeToken, InterpolatedTextToken } from '../ml_parser/tokens';
10import { AbsoluteSourceSpan, AST, ASTWithSource, BindingPipe, LiteralMap, ParserError, ParseSpan, TemplateBinding, TemplateBindingIdentifier } from './ast';
11import { Lexer, Token } from './lexer';
12export interface InterpolationPiece {
13 text: string;
14 start: number;
15 end: number;
16}
17export declare class SplitInterpolation {
18 strings: InterpolationPiece[];
19 expressions: InterpolationPiece[];
20 offsets: number[];
21 constructor(strings: InterpolationPiece[], expressions: InterpolationPiece[], offsets: number[]);
22}
23export declare class TemplateBindingParseResult {
24 templateBindings: TemplateBinding[];
25 warnings: string[];
26 errors: ParserError[];
27 constructor(templateBindings: TemplateBinding[], warnings: string[], errors: ParserError[]);
28}
29/**
30 * Represents the possible parse modes to be used as a bitmask.
31 */
32export declare const enum ParseFlags {
33 None = 0,
34 /**
35 * Whether an output binding is being parsed.
36 */
37 Action = 1,
38 /**
39 * Whether an assignment event is being parsed, i.e. an expression originating from
40 * two-way-binding aka banana-in-a-box syntax.
41 */
42 AssignmentEvent = 2
43}
44export declare class Parser {
45 private _lexer;
46 private errors;
47 constructor(_lexer: Lexer);
48 parseAction(input: string, isAssignmentEvent: boolean, location: string, absoluteOffset: number, interpolationConfig?: InterpolationConfig): ASTWithSource;
49 parseBinding(input: string, location: string, absoluteOffset: number, interpolationConfig?: InterpolationConfig): ASTWithSource;
50 private checkSimpleExpression;
51 parseSimpleBinding(input: string, location: string, absoluteOffset: number, interpolationConfig?: InterpolationConfig): ASTWithSource;
52 private _reportError;
53 private _parseBindingAst;
54 private _parseQuote;
55 /**
56 * Parse microsyntax template expression and return a list of bindings or
57 * parsing errors in case the given expression is invalid.
58 *
59 * For example,
60 * ```
61 * <div *ngFor="let item of items">
62 * ^ ^ absoluteValueOffset for `templateValue`
63 * absoluteKeyOffset for `templateKey`
64 * ```
65 * contains three bindings:
66 * 1. ngFor -> null
67 * 2. item -> NgForOfContext.$implicit
68 * 3. ngForOf -> items
69 *
70 * This is apparent from the de-sugared template:
71 * ```
72 * <ng-template ngFor let-item [ngForOf]="items">
73 * ```
74 *
75 * @param templateKey name of directive, without the * prefix. For example: ngIf, ngFor
76 * @param templateValue RHS of the microsyntax attribute
77 * @param templateUrl template filename if it's external, component filename if it's inline
78 * @param absoluteKeyOffset start of the `templateKey`
79 * @param absoluteValueOffset start of the `templateValue`
80 */
81 parseTemplateBindings(templateKey: string, templateValue: string, templateUrl: string, absoluteKeyOffset: number, absoluteValueOffset: number): TemplateBindingParseResult;
82 parseInterpolation(input: string, location: string, absoluteOffset: number, interpolatedTokens: InterpolatedAttributeToken[] | InterpolatedTextToken[] | null, interpolationConfig?: InterpolationConfig): ASTWithSource | null;
83 /**
84 * Similar to `parseInterpolation`, but treats the provided string as a single expression
85 * element that would normally appear within the interpolation prefix and suffix (`{{` and `}}`).
86 * This is used for parsing the switch expression in ICUs.
87 */
88 parseInterpolationExpression(expression: string, location: string, absoluteOffset: number): ASTWithSource;
89 private createInterpolationAst;
90 /**
91 * Splits a string of text into "raw" text segments and expressions present in interpolations in
92 * the string.
93 * Returns `null` if there are no interpolations, otherwise a
94 * `SplitInterpolation` with splits that look like
95 * <raw text> <expression> <raw text> ... <raw text> <expression> <raw text>
96 */
97 splitInterpolation(input: string, location: string, interpolatedTokens: InterpolatedAttributeToken[] | InterpolatedTextToken[] | null, interpolationConfig?: InterpolationConfig): SplitInterpolation;
98 wrapLiteralPrimitive(input: string | null, location: string, absoluteOffset: number): ASTWithSource;
99 private _stripComments;
100 private _commentStart;
101 private _checkNoInterpolation;
102 /**
103 * Finds the index of the end of an interpolation expression
104 * while ignoring comments and quoted content.
105 */
106 private _getInterpolationEndIndex;
107 /**
108 * Generator used to iterate over the character indexes of a string that are outside of quotes.
109 * @param input String to loop through.
110 * @param start Index within the string at which to start.
111 */
112 private _forEachUnquotedChar;
113}
114export declare class _ParseAST {
115 input: string;
116 location: string;
117 absoluteOffset: number;
118 tokens: Token[];
119 parseFlags: ParseFlags;
120 private errors;
121 private offset;
122 private rparensExpected;
123 private rbracketsExpected;
124 private rbracesExpected;
125 private context;
126 private sourceSpanCache;
127 index: number;
128 constructor(input: string, location: string, absoluteOffset: number, tokens: Token[], parseFlags: ParseFlags, errors: ParserError[], offset: number);
129 peek(offset: number): Token;
130 get next(): Token;
131 /** Whether all the parser input has been processed. */
132 get atEOF(): boolean;
133 /**
134 * Index of the next token to be processed, or the end of the last token if all have been
135 * processed.
136 */
137 get inputIndex(): number;
138 /**
139 * End index of the last processed token, or the start of the first token if none have been
140 * processed.
141 */
142 get currentEndIndex(): number;
143 /**
144 * Returns the absolute offset of the start of the current token.
145 */
146 get currentAbsoluteOffset(): number;
147 /**
148 * Retrieve a `ParseSpan` from `start` to the current position (or to `artificialEndIndex` if
149 * provided).
150 *
151 * @param start Position from which the `ParseSpan` will start.
152 * @param artificialEndIndex Optional ending index to be used if provided (and if greater than the
153 * natural ending index)
154 */
155 span(start: number, artificialEndIndex?: number): ParseSpan;
156 sourceSpan(start: number, artificialEndIndex?: number): AbsoluteSourceSpan;
157 advance(): void;
158 /**
159 * Executes a callback in the provided context.
160 */
161 private withContext;
162 consumeOptionalCharacter(code: number): boolean;
163 peekKeywordLet(): boolean;
164 peekKeywordAs(): boolean;
165 /**
166 * Consumes an expected character, otherwise emits an error about the missing expected character
167 * and skips over the token stream until reaching a recoverable point.
168 *
169 * See `this.error` and `this.skip` for more details.
170 */
171 expectCharacter(code: number): void;
172 consumeOptionalOperator(op: string): boolean;
173 expectOperator(operator: string): void;
174 prettyPrintToken(tok: Token): string;
175 expectIdentifierOrKeyword(): string | null;
176 expectIdentifierOrKeywordOrString(): string;
177 parseChain(): AST;
178 parsePipe(): AST;
179 parseExpression(): AST;
180 parseConditional(): AST;
181 parseLogicalOr(): AST;
182 parseLogicalAnd(): AST;
183 parseNullishCoalescing(): AST;
184 parseEquality(): AST;
185 parseRelational(): AST;
186 parseAdditive(): AST;
187 parseMultiplicative(): AST;
188 parsePrefix(): AST;
189 parseCallChain(): AST;
190 parsePrimary(): AST;
191 parseExpressionList(terminator: number): AST[];
192 parseLiteralMap(): LiteralMap;
193 parseAccessMember(readReceiver: AST, start: number, isSafe: boolean): AST;
194 parseCall(receiver: AST, start: number, isSafe: boolean): AST;
195 private consumeOptionalAssignment;
196 parseCallArguments(): BindingPipe[];
197 /**
198 * Parses an identifier, a keyword, a string with an optional `-` in between,
199 * and returns the string along with its absolute source span.
200 */
201 expectTemplateBindingKey(): TemplateBindingIdentifier;
202 /**
203 * Parse microsyntax template expression and return a list of bindings or
204 * parsing errors in case the given expression is invalid.
205 *
206 * For example,
207 * ```
208 * <div *ngFor="let item of items; index as i; trackBy: func">
209 * ```
210 * contains five bindings:
211 * 1. ngFor -> null
212 * 2. item -> NgForOfContext.$implicit
213 * 3. ngForOf -> items
214 * 4. i -> NgForOfContext.index
215 * 5. ngForTrackBy -> func
216 *
217 * For a full description of the microsyntax grammar, see
218 * https://gist.github.com/mhevery/d3530294cff2e4a1b3fe15ff75d08855
219 *
220 * @param templateKey name of the microsyntax directive, like ngIf, ngFor,
221 * without the *, along with its absolute span.
222 */
223 parseTemplateBindings(templateKey: TemplateBindingIdentifier): TemplateBindingParseResult;
224 parseKeyedReadOrWrite(receiver: AST, start: number, isSafe: boolean): AST;
225 /**
226 * Parse a directive keyword, followed by a mandatory expression.
227 * For example, "of items", "trackBy: func".
228 * The bindings are: ngForOf -> items, ngForTrackBy -> func
229 * There could be an optional "as" binding that follows the expression.
230 * For example,
231 * ```
232 * *ngFor="let item of items | slice:0:1 as collection".
233 * ^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
234 * keyword bound target optional 'as' binding
235 * ```
236 *
237 * @param key binding key, for example, ngFor, ngIf, ngForOf, along with its
238 * absolute span.
239 */
240 private parseDirectiveKeywordBindings;
241 /**
242 * Return the expression AST for the bound target of a directive keyword
243 * binding. For example,
244 * ```
245 * *ngIf="condition | pipe"
246 * ^^^^^^^^^^^^^^^^ bound target for "ngIf"
247 * *ngFor="let item of items"
248 * ^^^^^ bound target for "ngForOf"
249 * ```
250 */
251 private getDirectiveBoundTarget;
252 /**
253 * Return the binding for a variable declared using `as`. Note that the order
254 * of the key-value pair in this declaration is reversed. For example,
255 * ```
256 * *ngFor="let item of items; index as i"
257 * ^^^^^ ^
258 * value key
259 * ```
260 *
261 * @param value name of the value in the declaration, "ngIf" in the example
262 * above, along with its absolute span.
263 */
264 private parseAsBinding;
265 /**
266 * Return the binding for a variable declared using `let`. For example,
267 * ```
268 * *ngFor="let item of items; let i=index;"
269 * ^^^^^^^^ ^^^^^^^^^^^
270 * ```
271 * In the first binding, `item` is bound to `NgForOfContext.$implicit`.
272 * In the second binding, `i` is bound to `NgForOfContext.index`.
273 */
274 private parseLetBinding;
275 /**
276 * Consume the optional statement terminator: semicolon or comma.
277 */
278 private consumeStatementTerminator;
279 /**
280 * Records an error and skips over the token stream until reaching a recoverable point. See
281 * `this.skip` for more details on token skipping.
282 */
283 error(message: string, index?: number | null): void;
284 private locationText;
285 /**
286 * Records an error for an unexpected private identifier being discovered.
287 * @param token Token representing a private identifier.
288 * @param extraMessage Optional additional message being appended to the error.
289 */
290 private _reportErrorForPrivateIdentifier;
291 /**
292 * Error recovery should skip tokens until it encounters a recovery point.
293 *
294 * The following are treated as unconditional recovery points:
295 * - end of input
296 * - ';' (parseChain() is always the root production, and it expects a ';')
297 * - '|' (since pipes may be chained and each pipe expression may be treated independently)
298 *
299 * The following are conditional recovery points:
300 * - ')', '}', ']' if one of calling productions is expecting one of these symbols
301 * - This allows skip() to recover from errors such as '(a.) + 1' allowing more of the AST to
302 * be retained (it doesn't skip any tokens as the ')' is retained because of the '(' begins
303 * an '(' <expr> ')' production).
304 * The recovery points of grouping symbols must be conditional as they must be skipped if
305 * none of the calling productions are not expecting the closing token else we will never
306 * make progress in the case of an extraneous group closing symbol (such as a stray ')').
307 * That is, we skip a closing symbol if we are not in a grouping production.
308 * - '=' in a `Writable` context
309 * - In this context, we are able to recover after seeing the `=` operator, which
310 * signals the presence of an independent rvalue expression following the `=` operator.
311 *
312 * If a production expects one of these token it increments the corresponding nesting count,
313 * and then decrements it just prior to checking if the token is in the input.
314 */
315 private skip;
316}