private static parseExpression()

in src/language/expressions/TLE.ts [995:1083]


    private static parseExpression(tokenizer: Tokenizer, errors: Issue[]): Value | undefined {
        let expression: Value;
        if (tokenizer.current) {
            let rootExpression: Value | undefined; // Initial expression

            let token = tokenizer.current;
            let tokenType = token.getType();
            if (tokenType === TokenType.Literal) {
                rootExpression = Parser.parseFunctionCall(tokenizer, errors);
            } else if (tokenType === TokenType.QuotedString) {
                if (!token.stringValue.endsWith(token.stringValue[0])) {
                    errors.push(new Issue(token.span, "A constant string is missing an end quote.", IssueKind.tleSyntax));
                }
                rootExpression = new StringValue(token);
                tokenizer.next();
            } else if (tokenType === TokenType.Number) {
                rootExpression = new NumberValue(token);
                tokenizer.next();
            } else if (tokenType !== TokenType.RightSquareBracket && tokenType !== TokenType.Comma) {
                errors.push(new Issue(token.span, "Template language expressions must start with a function.", IssueKind.tleSyntax));
                tokenizer.next();
            }

            if (!rootExpression) {
                return undefined;
            }

            expression = rootExpression;
        } else {
            return undefined;
        }

        // Check for property or array accesses off of the root expression
        while (<Token | undefined>tokenizer.current) {
            if (tokenizer.current.getType() === TokenType.Period) {
                let periodToken = tokenizer.current;
                tokenizer.next();

                let propertyNameToken: Token | undefined;
                let errorSpan: Span | undefined;

                if (<Token | undefined>tokenizer.current) {
                    if (tokenizer.current.getType() === TokenType.Literal) {
                        propertyNameToken = tokenizer.current;
                        tokenizer.next();
                    } else {
                        errorSpan = tokenizer.current.span;

                        let tokenType = tokenizer.current.getType();
                        if (tokenType !== TokenType.RightParenthesis
                            && tokenType !== TokenType.RightSquareBracket
                            && tokenType !== TokenType.Comma
                        ) {
                            tokenizer.next();
                        }
                    }
                } else {
                    errorSpan = periodToken.span;
                }

                if (!propertyNameToken) {
                    assert(errorSpan);
                    // tslint:disable-next-line: no-non-null-assertion // Asserted
                    errors.push(new Issue(errorSpan!, "Expected a literal value.", IssueKind.tleSyntax));
                }

                // We go ahead and create a property access expression whether the property name
                //   was correctly given or not, so we can have proper intellisense/etc.
                expression = new PropertyAccess(expression, periodToken, propertyNameToken);
            } else if (tokenizer.current.getType() === TokenType.LeftSquareBracket) {
                let leftSquareBracketToken: Token = tokenizer.current;
                tokenizer.next();

                let indexValue: Value | undefined = Parser.parseExpression(tokenizer, errors);

                let rightSquareBracketToken: Token | undefined;
                if (<Token | undefined>tokenizer.current && tokenizer.current.getType() === TokenType.RightSquareBracket) {
                    rightSquareBracketToken = tokenizer.current;
                    tokenizer.next();
                }

                expression = new ArrayAccessValue(expression, leftSquareBracketToken, indexValue, rightSquareBracketToken);
            } else {
                break;
            }
        }

        return expression;
    }