/// <summary> /// Reads the next variable declaration statement from the file and returns it. /// </summary> /// <param name="parentReference"> /// The parent code unit. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code being parsed resides in an unsafe code block. /// </param> /// <param name="variables"> /// Returns the list of variables defined in the statement. /// </param> /// <returns> /// Returns the statement. /// </returns> private VariableDeclarationStatement ParseVariableDeclarationStatement(Reference<ICodePart> parentReference, bool unsafeCode, VariableCollection variables) { Param.AssertNotNull(parentReference, "parentReference"); Param.Ignore(unsafeCode); Param.Ignore(variables); bool constant = false; // Get the first symbol and make sure it is an unknown word or a const. Symbol symbol = this.GetNextSymbol(parentReference); CsToken firstToken = null; Node<CsToken> firstTokenNode = null; Reference<ICodePart> statementReference = new Reference<ICodePart>(); if (symbol.SymbolType == SymbolType.Const) { constant = true; firstToken = new CsToken(symbol.Text, CsTokenType.Const, symbol.Location, statementReference, this.symbols.Generated); firstTokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Const, SymbolType.Const, statementReference)); symbol = this.GetNextSymbol(statementReference); } if (symbol.SymbolType != SymbolType.Other) { throw this.CreateSyntaxException(); } // Get the expression representing the type. LiteralExpression type = this.GetTypeTokenExpression(statementReference, unsafeCode, true); if (type == null || type.Tokens.First == null) { throw new SyntaxException(this.document.SourceCode, firstToken.LineNumber); } if (firstTokenNode == null) { firstTokenNode = type.Tokens.First; } // Get the rest of the declaration. VariableDeclarationExpression expression = this.GetVariableDeclarationExpression(type, ExpressionPrecedence.None, unsafeCode); // Get the closing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, statementReference)); // Add each of the variables defined in this statement to the variable list being returned. if (variables != null) { VariableModifiers modifiers = constant ? VariableModifiers.Const : VariableModifiers.None; foreach (VariableDeclaratorExpression declarator in expression.Declarators) { Variable variable = new Variable( expression.Type, declarator.Identifier.Token.Text, modifiers, CodeLocation.Join(expression.Type.Location, declarator.Identifier.Token.Location), statementReference, expression.Tokens.First.Value.Generated || declarator.Identifier.Token.Generated); // There might already be a variable in this scope with the same name. This can happen // in valid situation when there are ifdef's surrounding portions of the code. // Just accept the first variable and ignore others. if (!variables.Contains(declarator.Identifier.Token.Text)) { variables.Add(variable); } } } // Create the token list for the statement. CsTokenList partialTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); VariableDeclarationStatement statement = new VariableDeclarationStatement(partialTokens, constant, expression); statementReference.Target = statement; return statement; }
/// <summary> /// The save. /// </summary> /// <param name="localVariable"> /// The local variable. /// </param> private void Save(VariableDeclarationStatement localVariable) { var storesaveVariablesMode = this.saveVariablesMode; if (localVariable.Constant) { // must be static for C++ as well if (storesaveVariablesMode == SaveVariablesMode.DefaultSourceInitializers) { this.cppWriter.Write("const "); } else { this.cppWriter.Write("const static "); } } this.Save(localVariable.InnerExpression); this.saveVariablesMode = storesaveVariablesMode; }