private void ValidateAction(ParserContext parserContext, RuleAction action) { if (!action.Validate(validation)) { // Choose the first one and throw it. ValidationError error = Validator.Errors[0]; // Try to get the position, or just use zero if we can't. object errorObject = error.UserData[RuleUserDataKeys.ErrorObject]; int position = 0; parserContext.exprPositions.TryGetValue(errorObject, out position); throw new RuleSyntaxException(error.ErrorNumber, error.ErrorText, position); } }
internal override CodeBinaryOperatorExpression CreateBinaryExpression(CodeExpression left, CodeExpression right, int operatorPosition, Parser parser, ParserContext parserContext, bool assignIsEquality) { CodePrimitiveExpression falseExpr = new CodePrimitiveExpression(false); parserContext.exprPositions[falseExpr] = operatorPosition; // Compare the comperands using "value-equality" CodeBinaryOperatorExpression binaryExpr = new CodeBinaryOperatorExpression(left, CodeBinaryOperatorType.ValueEquality, right); parserContext.exprPositions[binaryExpr] = operatorPosition; // Compare the result of that with false to simulate "value-inequality" binaryExpr = new CodeBinaryOperatorExpression(binaryExpr, CodeBinaryOperatorType.ValueEquality, falseExpr); parserContext.exprPositions[binaryExpr] = operatorPosition; parser.ValidateExpression(parserContext, binaryExpr, assignIsEquality, ValueCheck.Read); return binaryExpr; }
// Parse: // array-spec --> type-name // --> type-name array-rank-specifiers // array-rank-specifiers --> [ binary-expression ] // --> [ ] private Type TryParseTypeSpecifierWithOptionalSize(ParserContext parserContext, bool assignIsEquality, out CodeExpression size) { Type type = null; size = null; Token currentToken = parserContext.CurrentToken; type = TryParseTypeName(parserContext, assignIsEquality); // see if size specified if ((type != null) && (parserContext.CurrentToken.TokenID == TokenID.LBracket)) { Token next = parserContext.NextToken(); // skip '[' // get the size, if specified if (next.TokenID != TokenID.RBracket) size = ParseBinaryExpression(parserContext, 0, false, ValueCheck.Read); else size = defaultSize; if (parserContext.CurrentToken.TokenID != TokenID.RBracket) throw new RuleSyntaxException(ErrorNumbers.Error_MissingCloseSquareBracket, Messages.Parser_MissingCloseSquareBracket1, parserContext.CurrentToken.StartPosition); parserContext.NextToken(); // Eat the ']' } return type; }
private void ValidateExpression(ParserContext parserContext, CodeExpression expression, bool assignIsEquality, ValueCheck check) { // If the current token is an assignment operator, then make sure the expression is validated // correctly (written-to). Note that because we allow "=" (Token.Assign) as a synonym for // "==" (Token.Equal), we need to distinguish whether we're parsing a condition vs an action. // In other words, we need to be sure that the "=" really is an "=". if (parserContext.CurrentToken.TokenID == TokenID.Assign && !assignIsEquality) check = ValueCheck.Write; // use value in check RuleExpressionInfo exprInfo = null; if ((check & ValueCheck.Read) != 0) { exprInfo = RuleExpressionWalker.Validate(Validator, expression, false); // check write if set and first validate succeeded if ((exprInfo != null) && ((check & ValueCheck.Write) != 0)) exprInfo = RuleExpressionWalker.Validate(Validator, expression, true); } else if ((check & ValueCheck.Write) != 0) exprInfo = RuleExpressionWalker.Validate(Validator, expression, true); if (exprInfo == null && Validator.Errors.Count > 0) { // Choose the first one and throw it. ValidationError error = Validator.Errors[0]; // Try to get the position, or just use zero if we can't. object errorObject = error.UserData[RuleUserDataKeys.ErrorObject]; int position = 0; parserContext.exprPositions.TryGetValue(errorObject, out position); throw new RuleSyntaxException(error.ErrorNumber, error.ErrorText, position); } }
private Type ParseGenericType(ParserContext parserContext, List<Type> candidateGenericTypes, string typeName) { System.Diagnostics.Debug.Assert(parserContext.CurrentToken.TokenID == TokenID.Less); Type[] typeArgs = ParseGenericTypeArgList(parserContext); foreach (Type candidateType in candidateGenericTypes) { Type[] genericArgs = candidateType.GetGenericArguments(); if (genericArgs.Length == typeArgs.Length) return candidateType.MakeGenericType(typeArgs); } // No valid candidate found. string message = string.Format(CultureInfo.CurrentCulture, Messages.Parser_BadTypeArgCount, typeName); throw new RuleSyntaxException(ErrorNumbers.Error_BadTypeArgCount, message, parserContext.CurrentToken.StartPosition); }
// Parse: // type-spec --> type-name // --> type-name rank-specifiers private Type TryParseTypeSpecifier(ParserContext parserContext, bool assignIsEquality) { Type type = TryParseTypeName(parserContext, assignIsEquality); if (type != null) type = ParseArrayType(parserContext, type); return type; }
// Parse: // primary-expression --> ( logical-expression ) // --> IDENTIFIER // --> IDENTIFIER method-call-arguments // --> type-name // --> object-creation-expression // --> array-creation-expression // --> integer-constant // --> decimal-constant // --> float-constant // --> character-constant // --> string-constant // --> NULL // --> THIS // --> TRUE // --> FALSE private CodeExpression ParsePrimaryExpression(ParserContext parserContext, bool assignIsEquality) { CodeExpression primaryExpr = null; Token token = parserContext.CurrentToken; switch (token.TokenID) { case TokenID.LParen: // A parenthesized subexpression parserContext.NextToken(); primaryExpr = ParseBinaryExpression(parserContext, 0, assignIsEquality, ValueCheck.Read); parserContext.exprPositions[primaryExpr] = token.StartPosition; token = parserContext.CurrentToken; if (token.TokenID != TokenID.RParen) throw new RuleSyntaxException(ErrorNumbers.Error_MissingRParenInSubexpression, Messages.Parser_MissingRParenInSubexpression, parserContext.CurrentToken.StartPosition); parserContext.NextToken(); // eat the ')' break; case TokenID.Identifier: primaryExpr = ParseRootIdentifier(parserContext, assignIsEquality); break; case TokenID.This: parserContext.NextToken(); // eat "this" primaryExpr = new CodeThisReferenceExpression(); parserContext.exprPositions[primaryExpr] = token.StartPosition; ValidateExpression(parserContext, primaryExpr, assignIsEquality, ValueCheck.Read); break; case TokenID.TypeName: parserContext.NextToken(); // eat the type name Type type = (Type)token.Value; CodeTypeReference typeRef = new CodeTypeReference(type); validation.AddTypeReference(typeRef, type); primaryExpr = new CodeTypeReferenceExpression(typeRef); parserContext.exprPositions[primaryExpr] = token.StartPosition; ValidateExpression(parserContext, primaryExpr, assignIsEquality, ValueCheck.Read); break; case TokenID.New: parserContext.NextToken(); // eat "new" primaryExpr = ParseObjectCreation(parserContext, assignIsEquality); break; case TokenID.IntegerLiteral: case TokenID.FloatLiteral: case TokenID.DecimalLiteral: case TokenID.CharacterLiteral: case TokenID.StringLiteral: case TokenID.True: case TokenID.False: case TokenID.Null: parserContext.NextToken(); // eat the literal primaryExpr = new CodePrimitiveExpression(token.Value); parserContext.exprPositions[primaryExpr] = token.StartPosition; ValidateExpression(parserContext, primaryExpr, assignIsEquality, ValueCheck.Read); break; case TokenID.EndOfInput: throw new RuleSyntaxException(ErrorNumbers.Error_MissingOperand, Messages.Parser_MissingOperand, token.StartPosition); default: throw new RuleSyntaxException(ErrorNumbers.Error_UnknownLiteral, Messages.Parser_UnknownLiteral, token.StartPosition); } return primaryExpr; }
internal abstract CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality);
private CodeExpression ParseUnadornedMethodInvoke(ParserContext parserContext, string methodName, bool assignIsEquality) { System.Diagnostics.Debug.Assert(parserContext.CurrentToken.TokenID == TokenID.LParen); Type thisType = Validator.ThisType; // Start of a method call parameter list. int lparenPosition = parserContext.CurrentToken.StartPosition; parserContext.NextToken(); if (parserContext.CurrentToken.TokenID == TokenID.EndOfInput && parserContext.provideIntellisense) { parserContext.SetMethodCompletions(thisType, thisType, methodName, true, true, validation); return null; } List<CodeExpression> arguments = ParseArgumentList(parserContext); // Binding flags include all public & non-public, all instance, and all static. // All are possible candidates for unadorned method references. BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Instance; ValidationError error = null; RuleMethodInvokeExpressionInfo methodInvokeInfo = validation.ResolveMethod(thisType, methodName, bindingFlags, arguments, out error); if (methodInvokeInfo == null) throw new RuleSyntaxException(error.ErrorNumber, error.ErrorText, lparenPosition); MethodInfo mi = methodInvokeInfo.MethodInfo; CodeExpression primaryExpr = null; if (mi.IsStatic) primaryExpr = new CodeTypeReferenceExpression(thisType); else primaryExpr = new CodeThisReferenceExpression(); CodeExpression postfixExpr = new CodeMethodInvokeExpression(primaryExpr, methodName, arguments.ToArray()); parserContext.exprPositions[postfixExpr] = lparenPosition; ValidateExpression(parserContext, postfixExpr, assignIsEquality, ValueCheck.Read); return postfixExpr; }
// Parse: // argument --> direction logical-expression // --> logical-expression // // direction --> IN // --> OUT // --> REF private CodeExpression ParseArgument(ParserContext parserContext, bool assignIsEquality) { CodeExpression argResult = null; Token token = parserContext.CurrentToken; int directionPosition = token.StartPosition; FieldDirection? direction = null; ValueCheck check = ValueCheck.Read; switch (token.TokenID) { case TokenID.In: direction = FieldDirection.In; parserContext.NextToken(); // eat the direction token break; case TokenID.Out: direction = FieldDirection.Out; parserContext.NextToken(); check = ValueCheck.Write; break; case TokenID.Ref: direction = FieldDirection.Ref; parserContext.NextToken(); check = ValueCheck.Read | ValueCheck.Write; break; } argResult = ParseBinaryExpression(parserContext, 0, true, check); if (direction != null) { argResult = new CodeDirectionExpression(direction.Value, argResult); parserContext.exprPositions[argResult] = directionPosition; ValidateExpression(parserContext, argResult, assignIsEquality, ValueCheck.Read); } return argResult; }
internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { return(parser.ParseUnadornedMemberIdentifier(parserContext, this, assignIsEquality)); }
internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { return(parser.ParseRootOverloadedTypeIdentifier(parserContext, this.TypeSymbols, assignIsEquality)); }
internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { // The root name is a type (might be generic or not). return(parser.ParseRootTypeIdentifier(parserContext, this, assignIsEquality)); }
internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { // The root name is a type (might be generic or not). return parser.ParseRootTypeIdentifier(parserContext, this, assignIsEquality); }
// Parse: // object-creation-expression --> NEW type-name method-call-arguments // array-creation-expression --> NEW array-spec // --> NEW array-spec array-initializer private CodeExpression ParseObjectCreation(ParserContext parserContext, bool assignIsEquality) { CodeExpression primaryExpr = null; Token token = parserContext.CurrentToken; CodeExpression size; Type type = TryParseTypeSpecifierWithOptionalSize(parserContext, assignIsEquality, out size); // handle intellisense, regardless of whether we get a type back or not if (parserContext.provideIntellisense && parserContext.CurrentToken.TokenID == TokenID.EndOfInput) { // if we have a type, get only nested classes for it // if we don't have a type, then take whatever is already set for completions if (type != null) parserContext.SetNestedClassCompletions(type, validation.ThisType); return null; } if (type == null) throw new RuleSyntaxException(ErrorNumbers.Error_InvalidTypeArgument, Messages.Parser_InvalidTypeArgument, token.StartPosition); if (size == null) { // must be an object-creation-expression if (parserContext.CurrentToken.TokenID != TokenID.LParen) { // [] are already handled by TryParseTypeSpecifierWithOptionalSize throw new RuleSyntaxException(ErrorNumbers.Error_InvalidTypeArgument, Messages.Parser_InvalidNew, token.StartPosition); } primaryExpr = ParseConstructorArguments(parserContext, type, assignIsEquality); } else { // it's an array List<CodeExpression> initializers = ParseArrayCreationArguments(parserContext); if (initializers != null) { if (size == defaultSize) primaryExpr = new CodeArrayCreateExpression(type, initializers.ToArray()); else { // both specified primaryExpr = new CodeArrayCreateExpression(type, size); ((CodeArrayCreateExpression)primaryExpr).Initializers.AddRange(initializers.ToArray()); } } else { // no initializers, so size matters if (size != defaultSize) primaryExpr = new CodeArrayCreateExpression(type, size); else { // neither specified, so error throw new RuleSyntaxException(ErrorNumbers.Error_NoArrayCreationSize, Messages.Parser_NoArrayCreationSize, parserContext.CurrentToken.StartPosition); } } ValidateExpression(parserContext, primaryExpr, assignIsEquality, ValueCheck.Read); } return primaryExpr; }
internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { return parser.ParseUnadornedMemberIdentifier(parserContext, this, assignIsEquality); }
private CodeExpression ParseConstructorArguments(ParserContext parserContext, Type type, bool assignIsEquality) { System.Diagnostics.Debug.Assert(parserContext.CurrentToken.TokenID == TokenID.LParen); // Start of a constructor parameter list. int lparenPosition = parserContext.CurrentToken.StartPosition; parserContext.NextToken(); if (parserContext.CurrentToken.TokenID == TokenID.EndOfInput && parserContext.provideIntellisense) { parserContext.SetConstructorCompletions(type, Validator.ThisType); return null; } List<CodeExpression> arguments = ParseArgumentList(parserContext); if ((type.IsValueType) && (arguments.Count == 0)) { // this is always allowed } else if (type.IsAbstract) { // this is not allowed string message = string.Format(CultureInfo.CurrentCulture, Messages.UnknownConstructor, RuleDecompiler.DecompileType(type)); throw new RuleSyntaxException(ErrorNumbers.Error_MethodNotExists, message, lparenPosition); } else { // Binding flags include all public & non-public, all instance, and all static. // All are possible candidates for unadorned method references. BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance; if (type.Assembly == validation.ThisType.Assembly) bindingFlags |= BindingFlags.NonPublic; ValidationError error = null; RuleConstructorExpressionInfo constructorInvokeInfo = validation.ResolveConstructor(type, bindingFlags, arguments, out error); if (constructorInvokeInfo == null) throw new RuleSyntaxException(error.ErrorNumber, error.ErrorText, lparenPosition); } CodeExpression postfixExpr = new CodeObjectCreateExpression(type, arguments.ToArray()); parserContext.exprPositions[postfixExpr] = lparenPosition; ValidateExpression(parserContext, postfixExpr, assignIsEquality, ValueCheck.Read); return postfixExpr; }
// Parse nested types. private Type ParseNestedType(ParserContext parserContext, Type currentType) { System.Diagnostics.Debug.Assert(parserContext.CurrentToken.TokenID == TokenID.Dot); Type nestedType = null; while (parserContext.CurrentToken.TokenID == TokenID.Dot) { // Save the state of the scanner. Since we can't tell if we're parsing a nested // type or a member, we'll need to backtrack if we go too far. int savedTokenState = parserContext.SaveCurrentToken(); Token token = parserContext.NextToken(); if (token.TokenID != TokenID.Identifier) { if (parserContext.provideIntellisense && token.TokenID == TokenID.EndOfInput) { parserContext.SetTypeMemberCompletions(currentType, validation.ThisType, true, validation); return null; } else { throw new RuleSyntaxException(ErrorNumbers.Error_MissingIdentifierAfterDot, Messages.Parser_MissingIdentifierAfterDot, parserContext.CurrentToken.StartPosition); } } string name = (string)token.Value; BindingFlags bindingFlags = BindingFlags.Public; if (currentType.Assembly == validation.ThisType.Assembly) bindingFlags |= BindingFlags.NonPublic; if (parserContext.NextToken().TokenID == TokenID.Less) { // Might be a generic type. List<Type> candidateGenericTypes = new List<Type>(); Type[] nestedTypes = currentType.GetNestedTypes(bindingFlags); string prefix = name + "`"; for (int i = 0; i < nestedTypes.Length; ++i) { Type candidateType = nestedTypes[i]; if (candidateType.Name.StartsWith(prefix, StringComparison.Ordinal)) candidateGenericTypes.Add(candidateType); } if (candidateGenericTypes.Count == 0) { // It wasn't a generic type. Reset the scanner to the saved state. parserContext.RestoreCurrentToken(savedTokenState); // Also reset the deepenst nested type. nestedType = currentType; break; } nestedType = ParseGenericType(parserContext, candidateGenericTypes, name); currentType = nestedType; } else { // Might be a non-generic type. MemberInfo[] mi = currentType.GetMember(name, bindingFlags); if (mi == null || mi.Length != 1 || (mi[0].MemberType != MemberTypes.NestedType && mi[0].MemberType != MemberTypes.TypeInfo)) { // We went too far, reset the state. parserContext.RestoreCurrentToken(savedTokenState); // Also reset the deepest nested type. nestedType = currentType; break; } nestedType = (Type)mi[0]; if (currentType.IsGenericType && nestedType.IsGenericTypeDefinition) { // The outer type was generic (and bound), but the nested type is not. We have // to re-bind the generic arguments. nestedType = nestedType.MakeGenericType(currentType.GetGenericArguments()); } currentType = nestedType; } } return nestedType; }
// Parse: // array-initializer --> { variable-initializer-list } // { } // variable-initializer-list --> variable-initializer variable-initializer-list-tail // --> variable-initializer // variable-initializer-list-tail --> , variable-initializer variable-initializer-list-tail // --> , variable-initializer private List<CodeExpression> ParseArrayCreationArguments(ParserContext parserContext) { // if there are no initializers, return null if (parserContext.CurrentToken.TokenID != TokenID.LCurlyBrace) return null; List<CodeExpression> initializers = new List<CodeExpression>(); parserContext.NextToken(); // skip '{' if (parserContext.CurrentToken.TokenID != TokenID.RCurlyBrace) { initializers.Add(ParseInitializer(parserContext, true)); while (parserContext.CurrentToken.TokenID == TokenID.Comma) { parserContext.NextToken(); // eat the comma initializers.Add(ParseInitializer(parserContext, true)); } if (parserContext.CurrentToken.TokenID != TokenID.RCurlyBrace) throw new RuleSyntaxException(ErrorNumbers.Error_MissingRCurlyAfterInitializers, Messages.Parser_MissingRCurlyAfterInitializers, parserContext.CurrentToken.StartPosition); } parserContext.NextToken(); // eat the '}' return initializers; }
private Type[] ParseGenericTypeArgList(ParserContext parserContext) { System.Diagnostics.Debug.Assert(parserContext.CurrentToken.TokenID == TokenID.Less); List<Type> typeArgs = new List<Type>(); Token token; do { // Eat the opening '<' or ','. token = parserContext.NextToken(); Type type = TryParseTypeSpecifier(parserContext, true); if (type == null) throw new RuleSyntaxException(ErrorNumbers.Error_InvalidTypeArgument, Messages.Parser_InvalidTypeArgument, token.StartPosition); typeArgs.Add(type); } while (parserContext.CurrentToken.TokenID == TokenID.Comma); if (parserContext.CurrentToken.TokenID != TokenID.Greater) throw new RuleSyntaxException(ErrorNumbers.Error_MissingCloseAngleBracket, Messages.Parser_MissingCloseAngleBracket, parserContext.CurrentToken.StartPosition); parserContext.NextToken(); // Eat the '>' return typeArgs.ToArray(); }
// Parse: // variable-initializer --> logical-expression private CodeExpression ParseInitializer(ParserContext parserContext, bool assignIsEquality) { // size we only handle 1 level arrays, initializers must be regular expressions return ParseBinaryExpression(parserContext, 0, assignIsEquality, ValueCheck.Read); }
private Type TryParseTypeName(ParserContext parserContext, bool assignIsEquality) { Type type = null; Token currentToken = parserContext.CurrentToken; if (currentToken.TokenID == TokenID.TypeName) { type = (Type)currentToken.Value; parserContext.NextToken(); // eat the type name } else if (currentToken.TokenID == TokenID.Identifier) { Symbol sym = null; if (globalUniqueSymbols.TryGetValue((string)currentToken.Value, out sym)) { CodeExpression identExpr = sym.ParseRootIdentifier(this, parserContext, assignIsEquality); if (identExpr is CodeTypeReferenceExpression) type = validation.ExpressionInfo(identExpr).ExpressionType; } } return type; }
// Parse a root identifier which may be: // 1. A field/property/method with an implicit "this." prepended to it. // 2. A nested type within the type of this. // 2. An unqualified type name // 3. A namespace name. private CodeExpression ParseRootIdentifier(ParserContext parserContext, bool assignIsEquality) { Token token = parserContext.CurrentToken; string name = (string)token.Value; Symbol sym = null; // Consult the local unique symbol list first. If we find a symbol here, that's the one. if (!localUniqueSymbols.TryGetValue(name, out sym)) { // Wasn't found in the local unique symbols, try the global unique symbols. globalUniqueSymbols.TryGetValue(name, out sym); } if (sym == null) { // We couldn't find it in either location. This is an error. string message = string.Format(CultureInfo.CurrentCulture, Messages.Parser_UnknownIdentifier, name); throw new RuleSyntaxException(ErrorNumbers.Error_UnknownIdentifier, message, token.StartPosition); } return sym.ParseRootIdentifier(this, parserContext, assignIsEquality); }
// Parse: // rank-specifiers --> rank-specifier rank-specifier-tail // --> rank-specifier // // rank-specifier-tail --> rank-specifier rank-specifier-tail // // rank-specifier --> [ dim-separators ] // --> [ ] // // dim-separators --> , dim-separators-tail // --> , // // dim-separators-tail --> , dim-separators-tail private static Type ParseArrayType(ParserContext parserContext, Type baseType) { Type type = baseType; while (parserContext.CurrentToken.TokenID == TokenID.LBracket) { int rank = 1; while (parserContext.NextToken().TokenID == TokenID.Comma) ++rank; if (parserContext.CurrentToken.TokenID == TokenID.RBracket) parserContext.NextToken(); // Eat the ']' else throw new RuleSyntaxException(ErrorNumbers.Error_MissingCloseSquareBracket, Messages.Parser_MissingCloseSquareBracket, parserContext.CurrentToken.StartPosition); if (rank == 1) type = type.MakeArrayType(); else type = type.MakeArrayType(rank); } return type; }
// Parser: // primary-expr --> ... // --> IDENTIFIER // --> IDENTIFIER method-call-arguments // --> ... internal CodeExpression ParseUnadornedMemberIdentifier(ParserContext parserContext, MemberSymbol symbol, bool assignIsEquality) { // This is an implicit member reference off "this", so add the "this". (Or an implicit // static member reference of the type of "this", so add the type name.) Token token = parserContext.CurrentToken; int namePosition = token.StartPosition; parserContext.NextToken(); // eat the identifier CodeExpression primaryExpr = null; if (parserContext.CurrentToken.TokenID == TokenID.LParen) primaryExpr = ParseUnadornedMethodInvoke(parserContext, symbol.Name, true); else primaryExpr = ParseUnadornedFieldOrProperty(parserContext, symbol.Name, namePosition, assignIsEquality); return primaryExpr; }
private void ValidateStatement(ParserContext parserContext, CodeStatement statement) { if (!CodeDomStatementWalker.Validate(Validator, statement) && Validator.Errors.Count > 0) { // Choose the first one and throw it. ValidationError error = Validator.Errors[0]; // Try to get the position, or just use zero if we can't. object errorObject = error.UserData[RuleUserDataKeys.ErrorObject]; int position = 0; parserContext.exprPositions.TryGetValue(errorObject, out position); throw new RuleSyntaxException(error.ErrorNumber, error.ErrorText, position); } }
// Parse: // namespace-qualified-type-name --> NAMESPACE-NAME namespace-qualifier-tail . TYPE-NAME // --> NAMESPACE-NAME . TYPE-NAME // --> TYPE-NAME // // namespace-qualifier-tail --> . NAMESPACE-NAME namespace-qualifier-tail internal CodeExpression ParseRootNamespaceIdentifier(ParserContext parserContext, NamespaceSymbol nsSym, bool assignIsEquality) { // Loop through all the namespace qualifiers until we find something that's not a namespace. Symbol nestedSym = null; while (nsSym != null) { Token token = parserContext.NextToken(); if (token.TokenID != TokenID.Dot) throw new RuleSyntaxException(ErrorNumbers.Error_MissingDotAfterNamespace, Messages.Parser_MissingDotAfterNamespace, token.StartPosition); token = parserContext.NextToken(); if (token.TokenID != TokenID.Identifier) { if (parserContext.provideIntellisense && token.TokenID == TokenID.EndOfInput) { parserContext.SetNamespaceCompletions(nsSym); return null; } else { throw new RuleSyntaxException(ErrorNumbers.Error_MissingIdentifierAfterDot, Messages.Parser_MissingIdentifierAfterDot, token.StartPosition); } } string name = (string)token.Value; nestedSym = nsSym.FindMember(name); if (nestedSym == null) { string message = string.Format(CultureInfo.CurrentCulture, Messages.Parser_UnknownNamespaceMember, name, nsSym.GetQualifiedName()); throw new RuleSyntaxException(ErrorNumbers.Error_UnknownNamespaceMember, message, token.StartPosition); } nsSym = nestedSym as NamespaceSymbol; } // We are sitting at a type (or overloaded type). return nestedSym.ParseRootIdentifier(this, parserContext, assignIsEquality); }
internal virtual CodeBinaryOperatorExpression CreateBinaryExpression(CodeExpression left, CodeExpression right, int operatorPosition, Parser parser, ParserContext parserContext, bool assignIsEquality) { CodeBinaryOperatorExpression binaryExpr = new CodeBinaryOperatorExpression(left, codeDomOperator, right); parserContext.exprPositions[binaryExpr] = operatorPosition; parser.ValidateExpression(parserContext, binaryExpr, assignIsEquality, ValueCheck.Read); return binaryExpr; }
internal CodeExpression ParseRootTypeIdentifier(ParserContext parserContext, TypeSymbol typeSym, bool assignIsEquality) { string message = null; int typePosition = parserContext.CurrentToken.StartPosition; Token token = parserContext.NextToken(); if (typeSym.GenericArgCount > 0 && token.TokenID != TokenID.Less) { // This is a generic type, but no argument list was provided. message = string.Format(CultureInfo.CurrentCulture, Messages.Parser_MissingTypeArguments, typeSym.Name); throw new RuleSyntaxException(ErrorNumbers.Error_MissingTypeArguments, message, token.StartPosition); } Type type = typeSym.Type; if (token.TokenID == TokenID.Less) { // Start of a generic argument list... the type had better be generic. if (typeSym.GenericArgCount == 0) { message = string.Format(CultureInfo.CurrentCulture, Messages.Parser_NotAGenericType, RuleDecompiler.DecompileType(type)); throw new RuleSyntaxException(ErrorNumbers.Error_NotAGenericType, message, token.StartPosition); } Type[] typeArgs = ParseGenericTypeArgList(parserContext); if (typeArgs.Length != typeSym.GenericArgCount) { message = string.Format(CultureInfo.CurrentCulture, Messages.Parser_BadTypeArgCount, RuleDecompiler.DecompileType(type)); throw new RuleSyntaxException(ErrorNumbers.Error_BadTypeArgCount, message, parserContext.CurrentToken.StartPosition); } // if we are creating generics with design-time types, then the generic needs to be // a wrapped type to create the generic properly, so we look up the generic to get back the wrapper type = Validator.ResolveType(type.AssemblyQualifiedName); type = type.MakeGenericType(typeArgs); } token = parserContext.CurrentToken; if (token.TokenID == TokenID.Dot) { Type nestedType = ParseNestedType(parserContext, type); if (nestedType != null) type = nestedType; } return ParseTypeRef(parserContext, type, typePosition, assignIsEquality); }
internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { return parser.ParseRootNamespaceIdentifier(parserContext, this, assignIsEquality); }
internal CodeExpression ParseRootOverloadedTypeIdentifier(ParserContext parserContext, List<TypeSymbol> candidateTypeSymbols, bool assignIsEquality) { Token token = parserContext.CurrentToken; string typeName = (string)token.Value; int namePosition = token.StartPosition; // Get the next token after the identifier. token = parserContext.NextToken(); Type type = null; if (token.TokenID == TokenID.Less) { // Choose from the generic candidates. List<Type> candidateTypes = new List<Type>(candidateTypeSymbols.Count); foreach (TypeSymbol typeSym in candidateTypeSymbols) { if (typeSym.GenericArgCount > 0) candidateTypes.Add(typeSym.Type); } type = ParseGenericType(parserContext, candidateTypes, typeName); } else { // See if there's a non-generic candidate. TypeSymbol typeSym = candidateTypeSymbols.Find(delegate(TypeSymbol s) { return s.GenericArgCount == 0; }); if (typeSym == null) { // No argument list was provided, but there's no non-generic overload. string message = string.Format(CultureInfo.CurrentCulture, Messages.Parser_MissingTypeArguments, typeName); throw new RuleSyntaxException(ErrorNumbers.Error_MissingTypeArguments, message, namePosition); } type = typeSym.Type; } if (parserContext.CurrentToken.TokenID == TokenID.Dot) { Type nestedType = ParseNestedType(parserContext, type); if (nestedType != null) type = nestedType; } return ParseTypeRef(parserContext, type, namePosition, assignIsEquality); }
internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { return parser.ParseRootOverloadedTypeIdentifier(parserContext, this.TypeSymbols, assignIsEquality); }
private CodeExpression ParseTypeRef(ParserContext parserContext, Type type, int typePosition, bool assignIsEquality) { CodeExpression result = null; if (parserContext.CurrentToken.TokenID == TokenID.LParen) { // A '(' after a typename is only valid if it's an IRuleExpression. if (TypeProvider.IsAssignable(typeof(IRuleExpression), type)) { int lparenPosition = parserContext.CurrentToken.StartPosition; parserContext.NextToken(); // Eat the '(' List<CodeExpression> arguments = ParseArgumentList(parserContext); result = (CodeExpression)ConstructCustomType(type, arguments, lparenPosition); parserContext.exprPositions[result] = lparenPosition; ValidateExpression(parserContext, result, assignIsEquality, ValueCheck.Read); return result; } } CodeTypeReference typeRef = new CodeTypeReference(type); validation.AddTypeReference(typeRef, type); result = new CodeTypeReferenceExpression(typeRef); parserContext.exprPositions[result] = typePosition; ValidateExpression(parserContext, result, assignIsEquality, ValueCheck.Read); return result; }
internal abstract CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality);
internal override CodeExpression ParseRootIdentifier(Parser parser, ParserContext parserContext, bool assignIsEquality) { return(parser.ParseRootNamespaceIdentifier(parserContext, this, assignIsEquality)); }