예제 #1
0
        protected StringToken ParseString()
        {
            //System.Diagnostics.Debugger.Launch();
            LiteralToken stringToken = (LiteralToken)Eat(TokenType.Literal);

            if (stringToken.LiteralType != LiteralTokenType.String)
            {
                ReportError(Resources.ParserTokenUnexpected, stringToken.ToString());
                throw new NotSupportedException();
            }
            return((StringToken)stringToken);
        }
예제 #2
0
        protected float ParseNumber()
        {
            LiteralToken numberToken = (LiteralToken)Eat(TokenType.Literal);

            switch (numberToken.LiteralType)
            {
            case LiteralTokenType.Float:
                return(((FloatToken)numberToken).Value);

            case LiteralTokenType.Int:
                return(((IntToken)numberToken).Value);

            default:
                ReportError(Resources.ParserTokenUnexpected, numberToken.ToString());
                throw new NotSupportedException();
            }
        }
        private void Validate(
            ref LiteralToken literal,
            DefinitionInfo definition)
        {
            // Legal
            var literal2 = literal;

            if (definition.Get <ScalarDefinition>().Any(x => x.IsMatch(literal2)))
            {
                return;
            }

            // Not a string, convert
            if (literal.Type != TokenType.String)
            {
                var stringToken = new StringToken(literal.FileId, literal.Line, literal.Column, literal.ToString());

                // Legal
                if (definition.Get <StringDefinition>().Any(x => x.IsMatch(stringToken)))
                {
                    literal = stringToken;
                    return;
                }
            }

            // Illegal
            m_context.Error(literal, TemplateStrings.UnexpectedValue(literal));
        }
예제 #4
0
 public override string ToString()
 {
     return(LiteralToken.ToString());
 }
예제 #5
0
        private ScalarToken ParseScalar(
            LiteralToken token,
            String[] allowedContext)
        {
            // Not a string
            if (token.Type != TokenType.String)
            {
                return(token);
            }

            // Check if the value is definitely a literal
            var   raw = token.ToString();
            Int32 startExpression;

            if (String.IsNullOrEmpty(raw) ||
                (startExpression = raw.IndexOf(TemplateConstants.OpenExpression)) < 0) // Doesn't contain ${{
            {
                return(token);
            }

            // Break the value into segments of LiteralToken and ExpressionToken
            var segments = new List <ScalarToken>();
            var i        = 0;

            while (i < raw.Length)
            {
                // An expression starts here:
                if (i == startExpression)
                {
                    // Find the end of the expression - i.e. }}
                    startExpression = i;
                    var endExpression = -1;
                    var inString      = false;
                    for (i += TemplateConstants.OpenExpression.Length; i < raw.Length; i++)
                    {
                        if (raw[i] == '\'')
                        {
                            inString = !inString; // Note, this handles escaped single quotes gracefully. Ex. 'foo''bar'
                        }
                        else if (!inString && raw[i] == '}' && raw[i - 1] == '}')
                        {
                            endExpression = i;
                            i++;
                            break;
                        }
                    }

                    // Check if not closed
                    if (endExpression < startExpression)
                    {
                        m_context.Error(token, TemplateStrings.ExpressionNotClosed());
                        return(token);
                    }

                    // Parse the expression
                    var rawExpression = raw.Substring(
                        startExpression + TemplateConstants.OpenExpression.Length,
                        endExpression - startExpression + 1 - TemplateConstants.OpenExpression.Length - TemplateConstants.CloseExpression.Length);
                    var expression = ParseExpression(token.Line, token.Column, rawExpression, allowedContext, out Exception ex);

                    // Check for error
                    if (ex != null)
                    {
                        m_context.Error(token, ex);
                        return(token);
                    }

                    // Check if a directive was used when not allowed
                    if (!String.IsNullOrEmpty(expression.Directive) &&
                        ((startExpression != 0) || (i < raw.Length)))
                    {
                        m_context.Error(token, TemplateStrings.DirectiveNotAllowedInline(expression.Directive));
                        return(token);
                    }

                    // Add the segment
                    segments.Add(expression);

                    // Look for the next expression
                    startExpression = raw.IndexOf(TemplateConstants.OpenExpression, i);
                }
                // The next expression is further ahead:
                else if (i < startExpression)
                {
                    // Append the segment
                    AddString(segments, token.Line, token.Column, raw.Substring(i, startExpression - i));

                    // Adjust the position
                    i = startExpression;
                }
                // No remaining expressions:
                else
                {
                    AddString(segments, token.Line, token.Column, raw.Substring(i));
                    break;
                }
            }

            // Check if can convert to a literal
            // For example, the escaped expression: ${{ '{{ this is a literal }}' }}
            if (segments.Count == 1 &&
                segments[0] is BasicExpressionToken basicExpression &&
                IsExpressionString(basicExpression.Expression, out String str))
            {
                return(new StringToken(m_fileId, token.Line, token.Column, str));
            }

            // Check if only ony segment
            if (segments.Count == 1)
            {
                return(segments[0]);
            }

            // Build the new expression, using the format function
            var format   = new StringBuilder();
            var args     = new StringBuilder();
            var argIndex = 0;

            foreach (var segment in segments)
            {
                if (segment is StringToken literal)
                {
                    var text = ExpressionUtility.StringEscape(literal.Value) // Escape quotes
                               .Replace("{", "{{")                           // Escape braces
                               .Replace("}", "}}");
                    format.Append(text);
                }
                else
                {
                    format.Append("{" + argIndex.ToString(CultureInfo.InvariantCulture) + "}"); // Append formatter
                    argIndex++;

                    var expression = segment as BasicExpressionToken;
                    args.Append(", ");
                    args.Append(expression.Expression);
                }
            }

            return(new BasicExpressionToken(m_fileId, token.Line, token.Column, $"format('{format}'{args})"));
        }
예제 #6
0
        private VariableDeclarationNode ParseVariableDeclaration(bool allowInitialValue, bool requireInitialValue,
                                                                 bool allowArray, bool allowSemantic,
                                                                 TokenType?requiredDataType)
        {
            Token           dataType     = (requiredDataType != null) ? Eat(requiredDataType.Value) : EatDataType();
            IdentifierToken variableName = (IdentifierToken)Eat(TokenType.Identifier);

            bool   isArray   = false;
            string arraySize = null;

            if (allowArray && PeekType() == TokenType.OpenSquare)
            {
                isArray = true;

                Eat(TokenType.OpenSquare);
                switch (PeekType())
                {
                case TokenType.Literal:
                    LiteralToken arraySizeToken = (LiteralToken)Eat(TokenType.Literal);
                    if (arraySizeToken.LiteralType != LiteralTokenType.Int || ((IntToken)arraySizeToken).Value < 1)
                    {
                        ReportError(Resources.ParserArrayIndexExpected);
                        throw new NotSupportedException();
                    }
                    arraySize = arraySizeToken.ToString();
                    break;

                case TokenType.Identifier:
                    arraySize = Eat(TokenType.Identifier).ToString();
                    break;

                default:
                    ReportError(Resources.ParserArrayIndexExpected);
                    throw new NotSupportedException();
                }

                Eat(TokenType.CloseSquare);
            }

            string semantic = null;

            if (allowSemantic && PeekType() == TokenType.Colon)
            {
                Eat(TokenType.Colon);
                semantic = ((IdentifierToken)Eat(TokenType.Identifier)).Identifier;
            }

            string initialValue = null;

            if (requireInitialValue || PeekType() == TokenType.Equal)
            {
                if (!allowInitialValue)
                {
                    ReportError(Resources.ParserInitialValueUnexpected);
                }

                Eat(TokenType.Equal);
                {
                    bool isSamplerState = (PeekType() == TokenType.Identifier &&
                                           ((IdentifierToken)PeekToken()).Identifier == "sampler_state");
                    if (isSamplerState)
                    {
                        while (PeekType() != TokenType.CloseCurly)
                        {
                            initialValue += NextToken().ToString();
                        }
                        initialValue += NextToken().ToString();
                    }
                    else
                    {
                        while (PeekType() != TokenType.Semicolon)
                        {
                            initialValue += NextToken().ToString();
                        }
                    }
                }
            }

            Eat(TokenType.Semicolon);

            return(new VariableDeclarationNode
            {
                DataType = dataType.Type,
                Name = variableName.Identifier,
                IsArray = isArray,
                ArraySize = arraySize,
                Semantic = semantic,
                InitialValue = initialValue
            });
        }
예제 #7
0
        private TechniquePassNode ParseTechniquePass()
        {
            Eat(TokenType.Pass);

            IdentifierToken passIdentifier = (IdentifierToken)Eat(TokenType.Identifier);

            Eat(TokenType.OpenCurly);

            IdentifierToken fragmentsIdentifier = (IdentifierToken)Eat(TokenType.Identifier);

            if (fragmentsIdentifier.Identifier != "fragments")
            {
                ReportError(Resources.ParserTokenExpected, "fragments");
                throw new NotSupportedException();
            }

            Eat(TokenType.Equal);

            Eat(TokenType.OpenSquare);
            List <Token> fragments = new List <Token>();

            while (PeekType() != TokenType.CloseSquare)
            {
                switch (PeekType())
                {
                case TokenType.Identifier:
                    IdentifierToken fragmentIdentifier = (IdentifierToken)Eat(TokenType.Identifier);
                    fragments.Add(fragmentIdentifier);
                    break;

                case TokenType.Literal:
                    LiteralToken fragmentString = (LiteralToken)Eat(TokenType.Literal);
                    if (fragmentString.LiteralType != LiteralTokenType.String)
                    {
                        ReportError(Resources.ParserTokenUnexpected, fragmentString.ToString());
                        throw new NotSupportedException();
                    }
                    fragments.Add(fragmentString);
                    break;

                default:
                    ReportError(Resources.StitchedEffectParserStringLiteralOrIdentifierExpected);
                    throw new NotSupportedException();
                }

                if (PeekType() != TokenType.CloseSquare)
                {
                    Eat(TokenType.Comma);
                }
            }

            Eat(TokenType.CloseSquare);
            Eat(TokenType.Semicolon);
            Eat(TokenType.CloseCurly);

            return(new TechniquePassNode
            {
                Name = passIdentifier.Identifier,
                Fragments = fragments
            });
        }