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); }
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)); }
public override string ToString() { return(LiteralToken.ToString()); }
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})")); }
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 }); }
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 }); }