@angular/compiler
Version:
Angular - the compiler library
734 lines • 106 kB
JavaScript
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import * as chars from '../chars';
import { DEFAULT_INTERPOLATION_CONFIG } from '../ml_parser/interpolation_config';
import { escapeRegExp } from '../util';
import { ASTWithSource, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, NonNullAssert, ParseSpan, ParserError, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, TemplateBinding } from './ast';
import { EOF, TokenType, isIdentifier, isQuote } from './lexer';
export class SplitInterpolation {
constructor(strings, expressions, offsets) {
this.strings = strings;
this.expressions = expressions;
this.offsets = offsets;
}
}
export class TemplateBindingParseResult {
constructor(templateBindings, warnings, errors) {
this.templateBindings = templateBindings;
this.warnings = warnings;
this.errors = errors;
}
}
function _createInterpolateRegExp(config) {
const pattern = escapeRegExp(config.start) + '([\\s\\S]*?)' + escapeRegExp(config.end);
return new RegExp(pattern, 'g');
}
export class Parser {
constructor(_lexer) {
this._lexer = _lexer;
this.errors = [];
}
parseAction(input, location, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
this._checkNoInterpolation(input, location, interpolationConfig);
const sourceToLex = this._stripComments(input);
const tokens = this._lexer.tokenize(this._stripComments(input));
const ast = new _ParseAST(input, location, tokens, sourceToLex.length, true, this.errors, input.length - sourceToLex.length)
.parseChain();
return new ASTWithSource(ast, input, location, this.errors);
}
parseBinding(input, location, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
const ast = this._parseBindingAst(input, location, interpolationConfig);
return new ASTWithSource(ast, input, location, this.errors);
}
parseSimpleBinding(input, location, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
const ast = this._parseBindingAst(input, location, interpolationConfig);
const errors = SimpleExpressionChecker.check(ast);
if (errors.length > 0) {
this._reportError(`Host binding expression cannot contain ${errors.join(' ')}`, input, location);
}
return new ASTWithSource(ast, input, location, this.errors);
}
_reportError(message, input, errLocation, ctxLocation) {
this.errors.push(new ParserError(message, input, errLocation, ctxLocation));
}
_parseBindingAst(input, location, interpolationConfig) {
// Quotes expressions use 3rd-party expression language. We don't want to use
// our lexer or parser for that, so we check for that ahead of time.
const quote = this._parseQuote(input, location);
if (quote != null) {
return quote;
}
this._checkNoInterpolation(input, location, interpolationConfig);
const sourceToLex = this._stripComments(input);
const tokens = this._lexer.tokenize(sourceToLex);
return new _ParseAST(input, location, tokens, sourceToLex.length, false, this.errors, input.length - sourceToLex.length)
.parseChain();
}
_parseQuote(input, location) {
if (input == null)
return null;
const prefixSeparatorIndex = input.indexOf(':');
if (prefixSeparatorIndex == -1)
return null;
const prefix = input.substring(0, prefixSeparatorIndex).trim();
if (!isIdentifier(prefix))
return null;
const uninterpretedExpression = input.substring(prefixSeparatorIndex + 1);
return new Quote(new ParseSpan(0, input.length), prefix, uninterpretedExpression, location);
}
parseTemplateBindings(tplKey, tplValue, location) {
const tokens = this._lexer.tokenize(tplValue);
return new _ParseAST(tplValue, location, tokens, tplValue.length, false, this.errors, 0)
.parseTemplateBindings(tplKey);
}
parseInterpolation(input, location, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
const split = this.splitInterpolation(input, location, interpolationConfig);
if (split == null)
return null;
const expressions = [];
for (let i = 0; i < split.expressions.length; ++i) {
const expressionText = split.expressions[i];
const sourceToLex = this._stripComments(expressionText);
const tokens = this._lexer.tokenize(sourceToLex);
const ast = new _ParseAST(input, location, tokens, sourceToLex.length, false, this.errors, split.offsets[i] + (expressionText.length - sourceToLex.length))
.parseChain();
expressions.push(ast);
}
return new ASTWithSource(new Interpolation(new ParseSpan(0, input == null ? 0 : input.length), split.strings, expressions), input, location, this.errors);
}
splitInterpolation(input, location, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
const regexp = _createInterpolateRegExp(interpolationConfig);
const parts = input.split(regexp);
if (parts.length <= 1) {
return null;
}
const strings = [];
const expressions = [];
const offsets = [];
let offset = 0;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (i % 2 === 0) {
// fixed string
strings.push(part);
offset += part.length;
}
else if (part.trim().length > 0) {
offset += interpolationConfig.start.length;
expressions.push(part);
offsets.push(offset);
offset += part.length + interpolationConfig.end.length;
}
else {
this._reportError('Blank expressions are not allowed in interpolated strings', input, `at column ${this._findInterpolationErrorColumn(parts, i, interpolationConfig)} in`, location);
expressions.push('$implict');
offsets.push(offset);
}
}
return new SplitInterpolation(strings, expressions, offsets);
}
wrapLiteralPrimitive(input, location) {
return new ASTWithSource(new LiteralPrimitive(new ParseSpan(0, input == null ? 0 : input.length), input), input, location, this.errors);
}
_stripComments(input) {
const i = this._commentStart(input);
return i != null ? input.substring(0, i).trim() : input;
}
_commentStart(input) {
let outerQuote = null;
for (let i = 0; i < input.length - 1; i++) {
const char = input.charCodeAt(i);
const nextChar = input.charCodeAt(i + 1);
if (char === chars.$SLASH && nextChar == chars.$SLASH && outerQuote == null)
return i;
if (outerQuote === char) {
outerQuote = null;
}
else if (outerQuote == null && isQuote(char)) {
outerQuote = char;
}
}
return null;
}
_checkNoInterpolation(input, location, interpolationConfig) {
const regexp = _createInterpolateRegExp(interpolationConfig);
const parts = input.split(regexp);
if (parts.length > 1) {
this._reportError(`Got interpolation (${interpolationConfig.start}${interpolationConfig.end}) where expression was expected`, input, `at column ${this._findInterpolationErrorColumn(parts, 1, interpolationConfig)} in`, location);
}
}
_findInterpolationErrorColumn(parts, partInErrIdx, interpolationConfig) {
let errLocation = '';
for (let j = 0; j < partInErrIdx; j++) {
errLocation += j % 2 === 0 ?
parts[j] :
`${interpolationConfig.start}${parts[j]}${interpolationConfig.end}`;
}
return errLocation.length;
}
}
export class _ParseAST {
constructor(input, location, tokens, inputLength, parseAction, errors, offset) {
this.input = input;
this.location = location;
this.tokens = tokens;
this.inputLength = inputLength;
this.parseAction = parseAction;
this.errors = errors;
this.offset = offset;
this.rparensExpected = 0;
this.rbracketsExpected = 0;
this.rbracesExpected = 0;
this.index = 0;
}
peek(offset) {
const i = this.index + offset;
return i < this.tokens.length ? this.tokens[i] : EOF;
}
get next() { return this.peek(0); }
get inputIndex() {
return (this.index < this.tokens.length) ? this.next.index + this.offset :
this.inputLength + this.offset;
}
span(start) { return new ParseSpan(start, this.inputIndex); }
advance() { this.index++; }
optionalCharacter(code) {
if (this.next.isCharacter(code)) {
this.advance();
return true;
}
else {
return false;
}
}
peekKeywordLet() { return this.next.isKeywordLet(); }
peekKeywordAs() { return this.next.isKeywordAs(); }
expectCharacter(code) {
if (this.optionalCharacter(code))
return;
this.error(`Missing expected ${String.fromCharCode(code)}`);
}
optionalOperator(op) {
if (this.next.isOperator(op)) {
this.advance();
return true;
}
else {
return false;
}
}
expectOperator(operator) {
if (this.optionalOperator(operator))
return;
this.error(`Missing expected operator ${operator}`);
}
expectIdentifierOrKeyword() {
const n = this.next;
if (!n.isIdentifier() && !n.isKeyword()) {
this.error(`Unexpected token ${n}, expected identifier or keyword`);
return '';
}
this.advance();
return n.toString();
}
expectIdentifierOrKeywordOrString() {
const n = this.next;
if (!n.isIdentifier() && !n.isKeyword() && !n.isString()) {
this.error(`Unexpected token ${n}, expected identifier, keyword, or string`);
return '';
}
this.advance();
return n.toString();
}
parseChain() {
const exprs = [];
const start = this.inputIndex;
while (this.index < this.tokens.length) {
const expr = this.parsePipe();
exprs.push(expr);
if (this.optionalCharacter(chars.$SEMICOLON)) {
if (!this.parseAction) {
this.error('Binding expression cannot contain chained expression');
}
while (this.optionalCharacter(chars.$SEMICOLON)) {
} // read all semicolons
}
else if (this.index < this.tokens.length) {
this.error(`Unexpected token '${this.next}'`);
}
}
if (exprs.length == 0)
return new EmptyExpr(this.span(start));
if (exprs.length == 1)
return exprs[0];
return new Chain(this.span(start), exprs);
}
parsePipe() {
let result = this.parseExpression();
if (this.optionalOperator('|')) {
if (this.parseAction) {
this.error('Cannot have a pipe in an action expression');
}
do {
const name = this.expectIdentifierOrKeyword();
const args = [];
while (this.optionalCharacter(chars.$COLON)) {
args.push(this.parseExpression());
}
result = new BindingPipe(this.span(result.span.start), result, name, args);
} while (this.optionalOperator('|'));
}
return result;
}
parseExpression() { return this.parseConditional(); }
parseConditional() {
const start = this.inputIndex;
const result = this.parseLogicalOr();
if (this.optionalOperator('?')) {
const yes = this.parsePipe();
let no;
if (!this.optionalCharacter(chars.$COLON)) {
const end = this.inputIndex;
const expression = this.input.substring(start, end);
this.error(`Conditional expression ${expression} requires all 3 expressions`);
no = new EmptyExpr(this.span(start));
}
else {
no = this.parsePipe();
}
return new Conditional(this.span(start), result, yes, no);
}
else {
return result;
}
}
parseLogicalOr() {
// '||'
let result = this.parseLogicalAnd();
while (this.optionalOperator('||')) {
const right = this.parseLogicalAnd();
result = new Binary(this.span(result.span.start), '||', result, right);
}
return result;
}
parseLogicalAnd() {
// '&&'
let result = this.parseEquality();
while (this.optionalOperator('&&')) {
const right = this.parseEquality();
result = new Binary(this.span(result.span.start), '&&', result, right);
}
return result;
}
parseEquality() {
// '==','!=','===','!=='
let result = this.parseRelational();
while (this.next.type == TokenType.Operator) {
const operator = this.next.strValue;
switch (operator) {
case '==':
case '===':
case '!=':
case '!==':
this.advance();
const right = this.parseRelational();
result = new Binary(this.span(result.span.start), operator, result, right);
continue;
}
break;
}
return result;
}
parseRelational() {
// '<', '>', '<=', '>='
let result = this.parseAdditive();
while (this.next.type == TokenType.Operator) {
const operator = this.next.strValue;
switch (operator) {
case '<':
case '>':
case '<=':
case '>=':
this.advance();
const right = this.parseAdditive();
result = new Binary(this.span(result.span.start), operator, result, right);
continue;
}
break;
}
return result;
}
parseAdditive() {
// '+', '-'
let result = this.parseMultiplicative();
while (this.next.type == TokenType.Operator) {
const operator = this.next.strValue;
switch (operator) {
case '+':
case '-':
this.advance();
let right = this.parseMultiplicative();
result = new Binary(this.span(result.span.start), operator, result, right);
continue;
}
break;
}
return result;
}
parseMultiplicative() {
// '*', '%', '/'
let result = this.parsePrefix();
while (this.next.type == TokenType.Operator) {
const operator = this.next.strValue;
switch (operator) {
case '*':
case '%':
case '/':
this.advance();
let right = this.parsePrefix();
result = new Binary(this.span(result.span.start), operator, result, right);
continue;
}
break;
}
return result;
}
parsePrefix() {
if (this.next.type == TokenType.Operator) {
const start = this.inputIndex;
const operator = this.next.strValue;
let result;
switch (operator) {
case '+':
this.advance();
result = this.parsePrefix();
return new Binary(this.span(start), '-', result, new LiteralPrimitive(new ParseSpan(start, start), 0));
case '-':
this.advance();
result = this.parsePrefix();
return new Binary(this.span(start), operator, new LiteralPrimitive(new ParseSpan(start, start), 0), result);
case '!':
this.advance();
result = this.parsePrefix();
return new PrefixNot(this.span(start), result);
}
}
return this.parseCallChain();
}
parseCallChain() {
let result = this.parsePrimary();
while (true) {
if (this.optionalCharacter(chars.$PERIOD)) {
result = this.parseAccessMemberOrMethodCall(result, false);
}
else if (this.optionalOperator('?.')) {
result = this.parseAccessMemberOrMethodCall(result, true);
}
else if (this.optionalCharacter(chars.$LBRACKET)) {
this.rbracketsExpected++;
const key = this.parsePipe();
this.rbracketsExpected--;
this.expectCharacter(chars.$RBRACKET);
if (this.optionalOperator('=')) {
const value = this.parseConditional();
result = new KeyedWrite(this.span(result.span.start), result, key, value);
}
else {
result = new KeyedRead(this.span(result.span.start), result, key);
}
}
else if (this.optionalCharacter(chars.$LPAREN)) {
this.rparensExpected++;
const args = this.parseCallArguments();
this.rparensExpected--;
this.expectCharacter(chars.$RPAREN);
result = new FunctionCall(this.span(result.span.start), result, args);
}
else if (this.optionalOperator('!')) {
result = new NonNullAssert(this.span(result.span.start), result);
}
else {
return result;
}
}
}
parsePrimary() {
const start = this.inputIndex;
if (this.optionalCharacter(chars.$LPAREN)) {
this.rparensExpected++;
const result = this.parsePipe();
this.rparensExpected--;
this.expectCharacter(chars.$RPAREN);
return result;
}
else if (this.next.isKeywordNull()) {
this.advance();
return new LiteralPrimitive(this.span(start), null);
}
else if (this.next.isKeywordUndefined()) {
this.advance();
return new LiteralPrimitive(this.span(start), void 0);
}
else if (this.next.isKeywordTrue()) {
this.advance();
return new LiteralPrimitive(this.span(start), true);
}
else if (this.next.isKeywordFalse()) {
this.advance();
return new LiteralPrimitive(this.span(start), false);
}
else if (this.next.isKeywordThis()) {
this.advance();
return new ImplicitReceiver(this.span(start));
}
else if (this.optionalCharacter(chars.$LBRACKET)) {
this.rbracketsExpected++;
const elements = this.parseExpressionList(chars.$RBRACKET);
this.rbracketsExpected--;
this.expectCharacter(chars.$RBRACKET);
return new LiteralArray(this.span(start), elements);
}
else if (this.next.isCharacter(chars.$LBRACE)) {
return this.parseLiteralMap();
}
else if (this.next.isIdentifier()) {
return this.parseAccessMemberOrMethodCall(new ImplicitReceiver(this.span(start)), false);
}
else if (this.next.isNumber()) {
const value = this.next.toNumber();
this.advance();
return new LiteralPrimitive(this.span(start), value);
}
else if (this.next.isString()) {
const literalValue = this.next.toString();
this.advance();
return new LiteralPrimitive(this.span(start), literalValue);
}
else if (this.index >= this.tokens.length) {
this.error(`Unexpected end of expression: ${this.input}`);
return new EmptyExpr(this.span(start));
}
else {
this.error(`Unexpected token ${this.next}`);
return new EmptyExpr(this.span(start));
}
}
parseExpressionList(terminator) {
const result = [];
if (!this.next.isCharacter(terminator)) {
do {
result.push(this.parsePipe());
} while (this.optionalCharacter(chars.$COMMA));
}
return result;
}
parseLiteralMap() {
const keys = [];
const values = [];
const start = this.inputIndex;
this.expectCharacter(chars.$LBRACE);
if (!this.optionalCharacter(chars.$RBRACE)) {
this.rbracesExpected++;
do {
const quoted = this.next.isString();
const key = this.expectIdentifierOrKeywordOrString();
keys.push({ key, quoted });
this.expectCharacter(chars.$COLON);
values.push(this.parsePipe());
} while (this.optionalCharacter(chars.$COMMA));
this.rbracesExpected--;
this.expectCharacter(chars.$RBRACE);
}
return new LiteralMap(this.span(start), keys, values);
}
parseAccessMemberOrMethodCall(receiver, isSafe = false) {
const start = receiver.span.start;
const id = this.expectIdentifierOrKeyword();
if (this.optionalCharacter(chars.$LPAREN)) {
this.rparensExpected++;
const args = this.parseCallArguments();
this.expectCharacter(chars.$RPAREN);
this.rparensExpected--;
const span = this.span(start);
return isSafe ? new SafeMethodCall(span, receiver, id, args) :
new MethodCall(span, receiver, id, args);
}
else {
if (isSafe) {
if (this.optionalOperator('=')) {
this.error('The \'?.\' operator cannot be used in the assignment');
return new EmptyExpr(this.span(start));
}
else {
return new SafePropertyRead(this.span(start), receiver, id);
}
}
else {
if (this.optionalOperator('=')) {
if (!this.parseAction) {
this.error('Bindings cannot contain assignments');
return new EmptyExpr(this.span(start));
}
const value = this.parseConditional();
return new PropertyWrite(this.span(start), receiver, id, value);
}
else {
return new PropertyRead(this.span(start), receiver, id);
}
}
}
}
parseCallArguments() {
if (this.next.isCharacter(chars.$RPAREN))
return [];
const positionals = [];
do {
positionals.push(this.parsePipe());
} while (this.optionalCharacter(chars.$COMMA));
return positionals;
}
/**
* An identifier, a keyword, a string with an optional `-` in between.
*/
expectTemplateBindingKey() {
let result = '';
let operatorFound = false;
do {
result += this.expectIdentifierOrKeywordOrString();
operatorFound = this.optionalOperator('-');
if (operatorFound) {
result += '-';
}
} while (operatorFound);
return result.toString();
}
// Parses the AST for `<some-tag *tplKey=AST>`
parseTemplateBindings(tplKey) {
let firstBinding = true;
const bindings = [];
const warnings = [];
do {
const start = this.inputIndex;
let rawKey;
let key;
let isVar = false;
if (firstBinding) {
rawKey = key = tplKey;
firstBinding = false;
}
else {
isVar = this.peekKeywordLet();
if (isVar)
this.advance();
rawKey = this.expectTemplateBindingKey();
key = isVar ? rawKey : tplKey + rawKey[0].toUpperCase() + rawKey.substring(1);
this.optionalCharacter(chars.$COLON);
}
let name = null;
let expression = null;
if (isVar) {
if (this.optionalOperator('=')) {
name = this.expectTemplateBindingKey();
}
else {
name = '\$implicit';
}
}
else if (this.peekKeywordAs()) {
this.advance(); // consume `as`
name = rawKey;
key = this.expectTemplateBindingKey(); // read local var name
isVar = true;
}
else if (this.next !== EOF && !this.peekKeywordLet()) {
const start = this.inputIndex;
const ast = this.parsePipe();
const source = this.input.substring(start - this.offset, this.inputIndex - this.offset);
expression = new ASTWithSource(ast, source, this.location, this.errors);
}
bindings.push(new TemplateBinding(this.span(start), key, isVar, name, expression));
if (this.peekKeywordAs() && !isVar) {
const letStart = this.inputIndex;
this.advance(); // consume `as`
const letName = this.expectTemplateBindingKey(); // read local var name
bindings.push(new TemplateBinding(this.span(letStart), letName, true, key, null));
}
if (!this.optionalCharacter(chars.$SEMICOLON)) {
this.optionalCharacter(chars.$COMMA);
}
} while (this.index < this.tokens.length);
return new TemplateBindingParseResult(bindings, warnings, this.errors);
}
error(message, index = null) {
this.errors.push(new ParserError(message, this.input, this.locationText(index), this.location));
this.skip();
}
locationText(index = null) {
if (index == null)
index = this.index;
return (index < this.tokens.length) ? `at column ${this.tokens[index].index + 1} in` :
`at the end of the expression`;
}
// Error recovery should skip tokens until it encounters a recovery point. skip() treats
// the end of input and a ';' as unconditionally a recovery point. It also treats ')',
// '}' and ']' as conditional recovery points if one of calling productions is expecting
// one of these symbols. This allows skip() to recover from errors such as '(a.) + 1' allowing
// more of the AST to be retained (it doesn't skip any tokens as the ')' is retained because
// of the '(' begins an '(' <expr> ')' production). The recovery points of grouping symbols
// must be conditional as they must be skipped if none of the calling productions are not
// expecting the closing token else we will never make progress in the case of an
// extraneous group closing symbol (such as a stray ')'). This is not the case for ';' because
// parseChain() is always the root production and it expects a ';'.
// If a production expects one of these token it increments the corresponding nesting count,
// and then decrements it just prior to checking if the token is in the input.
skip() {
let n = this.next;
while (this.index < this.tokens.length && !n.isCharacter(chars.$SEMICOLON) &&
(this.rparensExpected <= 0 || !n.isCharacter(chars.$RPAREN)) &&
(this.rbracesExpected <= 0 || !n.isCharacter(chars.$RBRACE)) &&
(this.rbracketsExpected <= 0 || !n.isCharacter(chars.$RBRACKET))) {
if (this.next.isError()) {
this.errors.push(new ParserError(this.next.toString(), this.input, this.locationText(), this.location));
}
this.advance();
n = this.next;
}
}
}
class SimpleExpressionChecker {
constructor() {
this.errors = [];
}
static check(ast) {
const s = new SimpleExpressionChecker();
ast.visit(s);
return s.errors;
}
visitImplicitReceiver(ast, context) { }
visitInterpolation(ast, context) { }
visitLiteralPrimitive(ast, context) { }
visitPropertyRead(ast, context) { }
visitPropertyWrite(ast, context) { }
visitSafePropertyRead(ast, context) { }
visitMethodCall(ast, context) { }
visitSafeMethodCall(ast, context) { }
visitFunctionCall(ast, context) { }
visitLiteralArray(ast, context) { this.visitAll(ast.expressions); }
visitLiteralMap(ast, context) { this.visitAll(ast.values); }
visitBinary(ast, context) { }
visitPrefixNot(ast, context) { }
visitNonNullAssert(ast, context) { }
visitConditional(ast, context) { }
visitPipe(ast, context) { this.errors.push('pipes'); }
visitKeyedRead(ast, context) { }
visitKeyedWrite(ast, context) { }
visitAll(asts) { return asts.map(node => node.visit(this)); }
visitChain(ast, context) { }
visitQuote(ast, context) { }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL2V4cHJlc3Npb25fcGFyc2VyL3BhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEtBQUssS0FBSyxNQUFNLFVBQVUsQ0FBQztBQUNsQyxPQUFPLEVBQUMsNEJBQTRCLEVBQXNCLE1BQU0sbUNBQW1DLENBQUM7QUFDcEcsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUVyQyxPQUFPLEVBQU0sYUFBYSxFQUFjLE1BQU0sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQWlCLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBQyxNQUFNLE9BQU8sQ0FBQztBQUMvWCxPQUFPLEVBQUMsR0FBRyxFQUFnQixTQUFTLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUU1RSxNQUFNO0lBQ0osWUFBbUIsT0FBaUIsRUFBUyxXQUFxQixFQUFTLE9BQWlCO1FBQXpFLFlBQU8sR0FBUCxPQUFPLENBQVU7UUFBUyxnQkFBVyxHQUFYLFdBQVcsQ0FBVTtRQUFTLFlBQU8sR0FBUCxPQUFPLENBQVU7SUFBRyxDQUFDO0NBQ2pHO0FBRUQsTUFBTTtJQUNKLFlBQ1csZ0JBQW1DLEVBQVMsUUFBa0IsRUFDOUQsTUFBcUI7UUFEckIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFtQjtRQUFTLGFBQVEsR0FBUixRQUFRLENB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