/* Function: SetPrototypeParsingTypeBetween * Changes the <PrototypeParsingType> of all the tokens between the two passed iterators. The * token at the ending iterator will not be changed. */ public void SetPrototypeParsingTypeBetween(TokenIterator startingIterator, TokenIterator endingIterator, PrototypeParsingType type) { if (startingIterator.Tokenizer != this || endingIterator.Tokenizer != this) { throw new InvalidOperationException(); } SetPrototypeParsingTypeBetween(startingIterator.TokenIndex, endingIterator.TokenIndex, type); }
/* Function: SetPrototypeParsingTypeAt * Changes the <PrototypeParsingType> at the passed token index. */ public void SetPrototypeParsingTypeAt(int tokenIndex, PrototypeParsingType type) { if (prototypeParsingTypes == null) { prototypeParsingTypes = new PrototypeParsingType[tokenLengths.Count]; } if (tokenIndex < 0 || tokenIndex >= prototypeParsingTypes.Length) { throw new ArgumentOutOfRangeException(); } prototypeParsingTypes[tokenIndex] = type; }
/* Function: SetPrototypeParsingTypeBetween * Changes the <PrototypeParsingType> of all the tokens between the two passed indexes. The * token at the ending index will not be changed. */ public void SetPrototypeParsingTypeBetween(int startingIndex, int endingIndex, PrototypeParsingType type) { if (prototypeParsingTypes == null) { prototypeParsingTypes = new PrototypeParsingType[tokenLengths.Count]; } if (startingIndex < 0 || endingIndex > prototypeParsingTypes.Length) { throw new ArgumentOutOfRangeException(); } if (startingIndex > endingIndex) { throw new InvalidOperationException(); } for (int i = startingIndex; i < endingIndex; i++) { prototypeParsingTypes[i] = type; } }
/* Function: SetPrototypeParsingTypeByCharacters * * Changes the <PrototypeParsingType> of the tokens encompassed by the passed number of characters. * * This throws an exception if the number of characters does not evenly fall on a token boundary. It * is assumed that this function will primarily be used after a positive result from <MatchesAcrossTokens()> * or <TokensInCharacters()> which would cause this to not be an issue. */ public void SetPrototypeParsingTypeByCharacters(PrototypeParsingType newType, int characters) { int tokenCount = TokensInCharacters(characters); if (tokenCount == -1) { throw new InvalidOperationException(); } else if (tokenCount == 1) { PrototypeParsingType = newType; } else { TokenIterator iterator = this; while (tokenCount > 0) { iterator.PrototypeParsingType = newType; iterator.Next(); tokenCount--; } } }
/* Function: CalculateColumns * Fills in <columnIndexes> for the passed parameter. If the parameter doesn't exist it will return false. */ protected bool CalculateColumns(int parameterIndex) { TokenIterator startParam, endParam; if (parsedPrototype.GetParameter(parameterIndex, out startParam, out endParam) == false) { return(false); } if (columnIndexes == null) { columnIndexes = new int[NumberOfColumns]; } TokenIterator iterator = startParam; iterator.NextPastWhitespace(endParam); PrototypeParsingType type = iterator.PrototypeParsingType; if (parsedPrototype.Style == ParsedPrototype.ParameterStyle.C) { // ModifierQualifier int currentColumn = 0; columnIndexes[currentColumn] = iterator.TokenIndex; // Null covers whitespace and any random symbols we encountered that went unmarked. while (iterator < endParam && (type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.TypeQualifier || type == PrototypeParsingType.Null)) { iterator.Next(); type = iterator.PrototypeParsingType; } // Type currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; int typeNesting = 0; while (iterator < endParam && (type == PrototypeParsingType.Type || type == PrototypeParsingType.TypeSuffix || type == PrototypeParsingType.OpeningTypeSuffix || type == PrototypeParsingType.ClosingTypeSuffix || type == PrototypeParsingType.Null || typeNesting > 0)) { if (type == PrototypeParsingType.OpeningTypeSuffix) { typeNesting++; } else if (type == PrototypeParsingType.ClosingTypeSuffix) { typeNesting--; } iterator.Next(); type = iterator.PrototypeParsingType; } // NamePrefix currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; while (iterator < endParam && type == PrototypeParsingType.NamePrefix_PartOfType) { iterator.Next(); type = iterator.PrototypeParsingType; } // Name currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; // Include the parameter separator because there may not be a default value while (iterator < endParam && (type == PrototypeParsingType.Name || type == PrototypeParsingType.NameSuffix_PartOfType || type == PrototypeParsingType.ParamSeparator || type == PrototypeParsingType.Null)) { iterator.Next(); type = iterator.PrototypeParsingType; } // DefaultValueSeparator currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; while (iterator < endParam && type == PrototypeParsingType.DefaultValueSeparator) { iterator.Next(); type = iterator.PrototypeParsingType; } // DefaultValue currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; } else if (parsedPrototype.Style == ParsedPrototype.ParameterStyle.Pascal) { // NameModifier int currentColumn = 0; columnIndexes[currentColumn] = iterator.TokenIndex; // Null covers whitespace and any random symbols we encountered that went unmarked. while (iterator < endParam && (type == PrototypeParsingType.NameModifier_PartOfType || type == PrototypeParsingType.Null)) { iterator.Next(); type = iterator.PrototypeParsingType; } // Name currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; // Null covers whitespace and any random symbols we encountered that went unmarked. // Include the parameter separator because there may not be a type while (iterator < endParam && (type == PrototypeParsingType.Name || type == PrototypeParsingType.NamePrefix_PartOfType || type == PrototypeParsingType.NameSuffix_PartOfType || type == PrototypeParsingType.ParamSeparator || type == PrototypeParsingType.Null)) { iterator.Next(); type = iterator.PrototypeParsingType; } // TypeNameSeparator currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; while (iterator < endParam && type == PrototypeParsingType.NameTypeSeparator) { iterator.Next(); type = iterator.PrototypeParsingType; } // Type currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; int typeNesting = 0; // Include the parameter separator because there may not be a default value while (iterator < endParam && (type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.TypeQualifier || type == PrototypeParsingType.Type || type == PrototypeParsingType.TypeSuffix || type == PrototypeParsingType.OpeningTypeSuffix || type == PrototypeParsingType.ClosingTypeSuffix || type == PrototypeParsingType.ParamSeparator || type == PrototypeParsingType.Null || typeNesting > 0)) { if (type == PrototypeParsingType.OpeningTypeSuffix) { typeNesting++; } else if (type == PrototypeParsingType.ClosingTypeSuffix) { typeNesting--; } iterator.Next(); type = iterator.PrototypeParsingType; } // DefaultValueSeparator currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; while (iterator < endParam && type == PrototypeParsingType.DefaultValueSeparator) { iterator.Next(); type = iterator.PrototypeParsingType; } // DefaultValue currentColumn++; columnIndexes[currentColumn] = iterator.TokenIndex; } // End of parameter endOfColumnsIndex = endParam.TokenIndex; return(true); }
// Group: Support Functions // __________________________________________________________________________ /* Function: CalculateParameterTable * Fills in <parameterTableTokenIndexes>, <parameterTableColumnUsed>, and <symbolColumnWidth> for the * passed section. */ protected void CalculateParameterTable(Prototypes.ParameterSection section) { // // Check if this is a raw section with nothing other than parameter separators, meaning no name, type, etc. tokens // TokenIterator iterator = section.Start; TokenIterator endOfSection = section.End; bool isRaw = true; while (iterator < endOfSection) { var type = iterator.PrototypeParsingType; if (type != PrototypeParsingType.Null && type != PrototypeParsingType.StartOfPrototypeSection && type != PrototypeParsingType.StartOfParams && type != PrototypeParsingType.ParamSeparator && type != PrototypeParsingType.EndOfParams && type != PrototypeParsingType.EndOfPrototypeSection) { isRaw = false; break; } iterator.Next(); } // // Now fill in parameterTableTokenIndexes // parameterTableTokenIndexes = new int[section.NumberOfParameters, NumberOfColumns + 1]; for (int parameterIndex = 0; parameterIndex < section.NumberOfParameters; parameterIndex++) { TokenIterator startOfParam, endOfParam; section.GetParameterBounds(parameterIndex, out startOfParam, out endOfParam); iterator = startOfParam; iterator.NextPastWhitespace(endOfParam); // C-Style Parameters if (section.ParameterStyle == ParsedPrototype.ParameterStyle.C) { while (iterator < endOfParam && iterator.PrototypeParsingType == PrototypeParsingType.Null && iterator.FundamentalType == FundamentalType.Whitespace) { iterator.Next(); } // ModifierQualifier int currentColumn = 0; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; TokenIterator startOfType = iterator; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; // Null covers whitespace and any random symbols we encountered that went unmarked. if (type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.TypeQualifier || type == PrototypeParsingType.ParamModifier || type == PrototypeParsingType.Null) { iterator.Next(); } else if (type == PrototypeParsingType.OpeningTypeModifier || type == PrototypeParsingType.OpeningParamModifier) { SkipModifierBlock(ref iterator, endOfParam); } else { break; } } } // Type currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; // Allow this column to claim the contents of a raw prototype. They should all be null tokens. // We use the type column instead of the name column because the name column isn't fully syntax highlighted. while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; // The previous loop already got any modifiers before the type, so this will only cover the type // plus any modifiers following it. if (type == PrototypeParsingType.Type || type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.ParamModifier || (isRaw && type == PrototypeParsingType.ParamSeparator) || type == PrototypeParsingType.Null) { iterator.Next(); } else if (type == PrototypeParsingType.OpeningTypeModifier || type == PrototypeParsingType.OpeningParamModifier) { SkipModifierBlock(ref iterator, endOfParam); } else { break; } } // Symbols currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { // All symbols are part of the type column right now because they're marked as type or param // modifiers. Walk backwards to claim the symbols from the type column. if (iterator > startOfType) { TokenIterator lookbehind = iterator; lookbehind.Previous(); if (lookbehind.FundamentalType == FundamentalType.Symbol && lookbehind.Character != '_' && lookbehind.PrototypeParsingType != PrototypeParsingType.ClosingTypeModifier && lookbehind.PrototypeParsingType != PrototypeParsingType.ClosingParamModifier) { parameterTableTokenIndexes[parameterIndex, currentColumn] = lookbehind.TokenIndex; lookbehind.Previous(); while (lookbehind >= startOfType) { if (lookbehind.FundamentalType == FundamentalType.Symbol && lookbehind.Character != '_' && lookbehind.PrototypeParsingType != PrototypeParsingType.ClosingTypeModifier && lookbehind.PrototypeParsingType != PrototypeParsingType.ClosingParamModifier) { parameterTableTokenIndexes[parameterIndex, currentColumn] = lookbehind.TokenIndex; lookbehind.Previous(); } else { break; } } // Fix up any columns we stole from for (int i = 0; i < currentColumn; i++) { if (parameterTableTokenIndexes[parameterIndex, i] > parameterTableTokenIndexes[parameterIndex, currentColumn]) { parameterTableTokenIndexes[parameterIndex, i] = parameterTableTokenIndexes[parameterIndex, currentColumn]; } } } } } // Name currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; // Include the parameter separator because there may not be a default value. // Include modifiers because there still may be some after the name. if (type == PrototypeParsingType.Name || type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.ParamModifier || type == PrototypeParsingType.ParamSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else if (type == PrototypeParsingType.OpeningTypeModifier || type == PrototypeParsingType.OpeningParamModifier) { SkipModifierBlock(ref iterator, endOfParam); } else { break; } } } // PropertyValueSeparator currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; if (type == PrototypeParsingType.PropertyValueSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else { break; } } } // PropertyValue currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; if (type == PrototypeParsingType.PropertyValue || type == PrototypeParsingType.ParamSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else { break; } } } // DefaultValueSeparator currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; if (type == PrototypeParsingType.DefaultValueSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else { break; } } } // DefaultValue currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; // End of param currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = endOfParam.TokenIndex; } // Pascal-Style Parameters else if (section.ParameterStyle == ParsedPrototype.ParameterStyle.Pascal) { while (iterator < endOfParam && iterator.PrototypeParsingType == PrototypeParsingType.Null && iterator.FundamentalType == FundamentalType.Whitespace) { iterator.Next(); } // ModifierQualifier int currentColumn = 0; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; if (type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.ParamModifier || type == PrototypeParsingType.ParamSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else if (type == PrototypeParsingType.OpeningTypeModifier || type == PrototypeParsingType.OpeningParamModifier) { SkipModifierBlock(ref iterator, endOfParam); } else { break; } } } // Do we have a name-type separator? We may not, such as for SQL. bool hasNameTypeSeparator = false; TokenIterator lookahead = iterator; if (!isRaw) { while (lookahead < endOfParam) { if (lookahead.PrototypeParsingType == PrototypeParsingType.NameTypeSeparator) { hasNameTypeSeparator = true; break; } lookahead.Next(); } } // Name currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; // Include the parameter separator because there may not be a type. if (type == PrototypeParsingType.Name || type == PrototypeParsingType.ParamSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } // Include modifiers because there still may be some after the name, but only if there's a name-type separator. else if (hasNameTypeSeparator && (type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.ParamModifier)) { iterator.Next(); } else if (type == PrototypeParsingType.OpeningTypeModifier || type == PrototypeParsingType.OpeningParamModifier) { SkipModifierBlock(ref iterator, endOfParam); } else { break; } } } // TypeNameSeparator currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; if (type == PrototypeParsingType.NameTypeSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else { break; } } } // Symbols currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { if (iterator < endOfParam && iterator.FundamentalType == FundamentalType.Symbol && iterator.Character != '_') { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; if (( (iterator.FundamentalType == FundamentalType.Symbol && iterator.Character != '_') || (iterator.FundamentalType == FundamentalType.Whitespace) ) && (type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.ParamModifier || type == PrototypeParsingType.Null)) { iterator.Next(); } else { break; } } } } // Type currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; // Allow this column to claim the contents of a raw prototype. They should all be null tokens. // We use the type column instead of the name column because the name column isn't syntax highlighted. while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; // Include the parameter separator because there may not be a default value. if (type == PrototypeParsingType.Type || type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.TypeQualifier || type == PrototypeParsingType.ParamModifier || type == PrototypeParsingType.ParamSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else if (type == PrototypeParsingType.OpeningTypeModifier || type == PrototypeParsingType.OpeningParamModifier) { SkipModifierBlock(ref iterator, endOfParam); } else { break; } } // PropertyValueSeparator currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; if (type == PrototypeParsingType.PropertyValueSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else { break; } } } // PropertyValue currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; if (type == PrototypeParsingType.PropertyValue || type == PrototypeParsingType.ParamSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else { break; } } } // DefaultValueSeparator currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; if (!isRaw) { while (iterator < endOfParam) { PrototypeParsingType type = iterator.PrototypeParsingType; if (type == PrototypeParsingType.DefaultValueSeparator || type == PrototypeParsingType.Null) { iterator.Next(); } else { break; } } } // DefaultValue currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex; // End of param currentColumn++; parameterTableTokenIndexes[parameterIndex, currentColumn] = endOfParam.TokenIndex; } } // // Next fill in parameterTableColumnsUsed // // There's a very high likelihood of this array always being the same length so it's worth it to try to reuse the // memory and avoid a reallocation. if (parameterTableColumnsUsed != null && parameterTableColumnsUsed.Length == NumberOfColumns) { Array.Clear(parameterTableColumnsUsed, 0, NumberOfColumns); } else { parameterTableColumnsUsed = new bool[NumberOfColumns]; } for (int parameterIndex = 0; parameterIndex < section.NumberOfParameters; parameterIndex++) { for (int columnIndex = 0; columnIndex < NumberOfColumns; columnIndex++) { if (parameterTableTokenIndexes[parameterIndex, columnIndex] != parameterTableTokenIndexes[parameterIndex, columnIndex + 1]) { parameterTableColumnsUsed[columnIndex] = true; } } } // // Next determine the symbol column's width // symbolColumnWidth = 0; if (parameterTableColumnsUsed[SymbolsColumnIndex]) { for (int parameterIndex = 0; parameterIndex < section.NumberOfParameters; parameterIndex++) { int startTokenIndex = parameterTableTokenIndexes[parameterIndex, SymbolsColumnIndex]; int endTokenIndex = parameterTableTokenIndexes[parameterIndex, SymbolsColumnIndex + 1]; if (endTokenIndex > startTokenIndex) { TokenIterator start, end; section.GetParameterBounds(parameterIndex, out start, out end); start.Next(startTokenIndex - start.TokenIndex); end.Previous(end.TokenIndex - endTokenIndex); int paramColumnWidth = end.RawTextIndex - start.RawTextIndex; if (paramColumnWidth > symbolColumnWidth) { symbolColumnWidth = paramColumnWidth; } } } } }
/* Function: GetFullParameterType * * Returns the bounds of the type of the passed parameter, or false if it couldn't find it. This includes modifiers and type * suffixes. Since the type token may not be continuous, it returns separate start and end iterators for extra type modifiers * ("const" in "const x: integer") prefixes ("*" in "int *x") and suffixes ("[12]" in "int x[12]"). Regular modifiers attached to * the type ("unsigned" in "unsigned int x") will be accounted for by the main iterators. * * If the implied types flag is set this will return "int" for y in "int x, y". If it is not then it will return false for y. */ public bool GetFullParameterType(int index, out TokenIterator start, out TokenIterator end, out TokenIterator extraModifierStart, out TokenIterator extraModifierEnd, out TokenIterator prefixStart, out TokenIterator prefixEnd, out TokenIterator suffixStart, out TokenIterator suffixEnd, bool impliedTypes = true) { TokenIterator paramStart, paramEnd; if (!GetParameter(index, out paramStart, out paramEnd)) { start = paramEnd; end = paramEnd; extraModifierStart = paramEnd; extraModifierEnd = paramEnd; prefixStart = paramEnd; prefixEnd = paramEnd; suffixStart = paramEnd; suffixEnd = paramEnd; return(false); } // Find the beginning of the type by finding the first type token start = paramStart; PrototypeParsingType type = start.PrototypeParsingType; while (start < paramEnd && type != PrototypeParsingType.Type && type != PrototypeParsingType.TypeModifier && type != PrototypeParsingType.TypeQualifier && type != PrototypeParsingType.NameModifier_PartOfType) { start.Next(); type = start.PrototypeParsingType; } // If we're on a name modifier, get it and keep looking for the type if (type == PrototypeParsingType.NameModifier_PartOfType) { extraModifierStart = start; do { start.Next(); type = start.PrototypeParsingType; }while (start < paramEnd && type == PrototypeParsingType.NameModifier_PartOfType); extraModifierEnd = start; // Search for the start again after the extra modifier while (start < paramEnd && type != PrototypeParsingType.Type && type != PrototypeParsingType.TypeModifier && type != PrototypeParsingType.TypeQualifier) { start.Next(); type = start.PrototypeParsingType; } } else { extraModifierStart = paramEnd; extraModifierEnd = paramEnd; } // If we found one, find the end of the type bool foundType = (start < paramEnd); end = start; if (foundType) { int nestLevel = 0; do { if (end.PrototypeParsingType == PrototypeParsingType.OpeningTypeSuffix) { nestLevel++; } else if (end.PrototypeParsingType == PrototypeParsingType.ClosingTypeSuffix) { nestLevel--; } end.Next(); type = end.PrototypeParsingType; }while ((nestLevel > 0 || type == PrototypeParsingType.Type || type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.TypeQualifier || type == PrototypeParsingType.OpeningTypeSuffix || type == PrototypeParsingType.ClosingTypeSuffix || type == PrototypeParsingType.TypeSuffix || end.FundamentalType == FundamentalType.Whitespace) && end < paramEnd); end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start); } // See if we can fill it out with implied types if (impliedTypes) { if (Style == ParameterStyle.C) { // If there's no type for a C parameter, move backwards for "int x, y" if (!foundType) { TokenIterator ignoredA, ignoredB; for (int i = index - 1; i >= 0; i--) { if (GetFullParameterType(i, out start, out end, out ignoredA, out ignoredB, out prefixStart, out prefixEnd, out suffixStart, out suffixEnd, false)) { foundType = true; break; } } } } else // Style == ParameterStyle.Pascal { // If there's no type for a Pascal parameter, move forwards for "x, y: integer" if (!foundType) { TokenIterator ignoredA, ignoredB; for (int i = index + 1; i <= NumberOfParameters; i++) { if (GetFullParameterType(i, out start, out end, out ignoredA, out ignoredB, out prefixStart, out prefixEnd, out suffixStart, out suffixEnd, false)) { foundType = true; break; } } } // If there's no extra modifiers for a Pascal parameter, move backwards for "const x, y: integer" if (extraModifierEnd <= extraModifierStart) { TokenIterator prevParamIterator, prevParamEnd, prevExtraModifierStart, prevExtraModifierEnd; for (int i = index - 1; i >= 0; i--) { // We can't use GetFullParameterType() here because it won't return anything if it doesn't find a type with // implied types off, and turning implied types on means we can't detect when another type occurs which // would mean we wouldn't want to inherit its modifiers ("const x: integer; y: integer"). So we do it manually // with GetParameter(). GetParameter(i, out prevParamIterator, out prevParamEnd); prevExtraModifierStart = prevParamEnd; prevExtraModifierEnd = prevParamEnd; bool foundPrevExtraModifier = false; bool foundPrevType = false; while (prevParamIterator < prevParamEnd) { if (prevParamIterator.PrototypeParsingType == PrototypeParsingType.NameModifier_PartOfType) { if (!foundPrevExtraModifier) { prevExtraModifierStart = prevParamIterator; foundPrevExtraModifier = true; } prevParamIterator.Next(); prevExtraModifierEnd = prevParamIterator; } else if (prevParamIterator.PrototypeParsingType == PrototypeParsingType.Type) { foundPrevType = true; break; } else { prevParamIterator.Next(); } } if (foundPrevType) { break; } else if (foundPrevExtraModifier) { extraModifierStart = prevExtraModifierStart; extraModifierEnd = prevExtraModifierEnd; break; } } } } } // If we found a type, explicit or implied, find the prefix and suffix. We do this after checking for implied types because we // want "int a[12], b" to work. b should be int, not int[12]. In "int *x, y", y should be int, not int*. if (foundType) { prefixStart = paramStart; while (prefixStart < paramEnd && prefixStart.PrototypeParsingType != PrototypeParsingType.NamePrefix_PartOfType) { prefixStart.Next(); } prefixEnd = prefixStart; while (prefixEnd < paramEnd && prefixEnd.PrototypeParsingType == PrototypeParsingType.NamePrefix_PartOfType) { prefixEnd.Next(); } suffixStart = paramStart; while (suffixStart < paramEnd && suffixStart.PrototypeParsingType != PrototypeParsingType.NameSuffix_PartOfType) { suffixStart.Next(); } suffixEnd = suffixStart; while (suffixEnd < paramEnd && suffixEnd.PrototypeParsingType == PrototypeParsingType.NameSuffix_PartOfType) { suffixEnd.Next(); } return(true); } else // didn't find a type { start = paramEnd; end = paramEnd; extraModifierStart = paramEnd; extraModifierEnd = paramEnd; prefixStart = paramEnd; prefixEnd = paramEnd; suffixStart = paramEnd; suffixEnd = paramEnd; return(false); } }
/* Function: SetPrototypeParsingTypeBetween * Changes the <PrototypeParsingType> of all the tokens between the current position and the passed iterator. * The token the ending iterator is on will not be changed. */ public void SetPrototypeParsingTypeBetween(TokenIterator end, PrototypeParsingType type) { Tokenizer.SetPrototypeParsingTypeBetween(this, end, type); }
/* Function: GetFullParameterType * * Returns the bounds of the type of the passed parameter, or false if it couldn't find it. This includes modifiers and type * suffixes. Since the type token may not be continuous, it returns separate start and end iterators for type prefixes * (* in "int *x") and suffixes ("[12]" in "int x[12]"). * * If the implied types flag is set this will return "int" for y in "int x, y". If it is not then it will return false for y. */ public bool GetFullParameterType(int index, out TokenIterator start, out TokenIterator end, out TokenIterator prefixStart, out TokenIterator prefixEnd, out TokenIterator suffixStart, out TokenIterator suffixEnd, bool impliedTypes = true) { TokenIterator paramStart, paramEnd; if (!GetParameter(index, out paramStart, out paramEnd)) { start = paramEnd; end = paramEnd; prefixStart = paramEnd; prefixEnd = paramEnd; suffixStart = paramEnd; suffixEnd = paramEnd; return(false); } // Find the beginning of the type by finding the first type token start = paramStart; PrototypeParsingType type = start.PrototypeParsingType; while (start < paramEnd && type != PrototypeParsingType.Type && type != PrototypeParsingType.TypeModifier && type != PrototypeParsingType.TypeQualifier) { start.Next(); type = start.PrototypeParsingType; } // If we found one, find the end of the type bool foundType = (start < paramEnd); end = start; if (foundType) { int nestLevel = 0; do { if (end.PrototypeParsingType == PrototypeParsingType.OpeningTypeSuffix) { nestLevel++; } else if (end.PrototypeParsingType == PrototypeParsingType.ClosingTypeSuffix) { nestLevel--; } end.Next(); type = end.PrototypeParsingType; }while ((nestLevel > 0 || type == PrototypeParsingType.Type || type == PrototypeParsingType.TypeModifier || type == PrototypeParsingType.TypeQualifier || type == PrototypeParsingType.OpeningTypeSuffix || type == PrototypeParsingType.ClosingTypeSuffix || type == PrototypeParsingType.TypeSuffix || end.FundamentalType == FundamentalType.Whitespace) && end < paramEnd); end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start); } // If we didn't find a type, see if it's implied else if (impliedTypes) { if (Style == ParameterStyle.C) { // Move backwards for "int x, y" for (int i = index - 1; i >= 0; i--) { if (GetFullParameterType(i, out start, out end, out prefixStart, out prefixEnd, out suffixStart, out suffixEnd, false)) { foundType = true; break; } } } else // Style == ParameterStyle.Pascal { // Move forwards for "x, y: integer" for (int i = index + 1; i <= NumberOfParameters; i++) { if (GetFullParameterType(i, out start, out end, out prefixStart, out prefixEnd, out suffixStart, out suffixEnd, false)) { foundType = true; break; } } } } // If we found a type, explicit or implied, find the prefix and suffix. We do this after checking for implied types because we // want "int a[12], b" to work. b should be int, not int[12]. In "int *x, y", y should be int, not int*. if (foundType) { prefixStart = paramStart; while (prefixStart < paramEnd && prefixStart.PrototypeParsingType != PrototypeParsingType.NamePrefix_PartOfType) { prefixStart.Next(); } prefixEnd = prefixStart; while (prefixEnd < paramEnd && prefixEnd.PrototypeParsingType == PrototypeParsingType.NamePrefix_PartOfType) { prefixEnd.Next(); } suffixStart = paramStart; while (suffixStart < paramEnd && suffixStart.PrototypeParsingType != PrototypeParsingType.NameSuffix_PartOfType) { suffixStart.Next(); } suffixEnd = suffixStart; while (suffixEnd < paramEnd && suffixEnd.PrototypeParsingType == PrototypeParsingType.NameSuffix_PartOfType) { suffixEnd.Next(); } return(true); } else // didn't find a type { start = paramEnd; end = paramEnd; prefixStart = paramEnd; prefixEnd = paramEnd; suffixStart = paramEnd; suffixEnd = paramEnd; return(false); } }