/// <summary> /// Creates a new node using the given token and the current lexer state. /// </summary> /// <param name="token">The token to create a node for.</param> /// <returns>The newly created node.</returns> private ApexSyntaxNode CreateNode(Tokens token) { ApexSyntaxNode node = null; ApexTextSpan textSpan = new ApexTextSpan( tokPos, tokEPos, tokLin, tokCol + 1, tokELin, tokECol + 1); switch (token) { case Tokens.IDENTIFIER: case Tokens.LITERAL_DOUBLE: case Tokens.LITERAL_INTEGER: case Tokens.LITERAL_LONG: case Tokens.LITERAL_STRING: case Tokens.COMMENT_BLOCK: case Tokens.COMMENT_DOC: case Tokens.COMMENT_INLINE: case Tokens.WHITESPACE: node = new ApexSyntaxNode(token, textSpan, yytext); break; default: node = new ApexSyntaxNode(token, textSpan); break; } return(node); }
/// <summary> /// Returns symbols for the right shift operation. /// </summary> /// <returns>Symbols for the right shift operation.</returns> private int SymbolShiftRight() { yylloc = new ApexTextSpan(tokPos, tokEPos - 1, tokLin, tokCol + 1, tokELin, tokECol); yylval = new ApexSyntaxNode(Tokens.OPERATOR_GREATER_THAN_A, yylloc); _pushBackQueue.Enqueue(new ApexSyntaxNode( Tokens.OPERATOR_GREATER_THAN_B, new ApexTextSpan(tokPos + 1, tokEPos, tokLin, tokCol + 2, tokELin, tokECol + 1))); return((int)Tokens.OPERATOR_GREATER_THAN_A); }
/// <summary> /// Gets the symbols on the given stack that are within the node. /// </summary> /// <typeparam name="TType">The symbol type.</typeparam> /// <param name="node">The node to get the collected symbols for.</param> /// <param name="stack">The stack to get the symbols from.</param> /// <returns>The symbols that belong to the node.</returns> private TType[] GetSymbols<TType>(ApexSyntaxNode node, Stack<TType> stack) where TType : Symbol { List<TType> result = new List<TType>(); while (true) { if (stack.Count == 0 || !node.TextSpan.Contains(stack.Peek().Location)) break; result.Insert(0, stack.Pop()); } return result.ToArray(); }
/// <summary> /// Recursive method that gets all the nodes that have text. /// </summary> /// <param name="node">The current node to evaluate.</param> /// <param name="nodes">The list to added nodes to.</param> private void GetNodesWithText(ApexSyntaxNode node, IList <ApexSyntaxNode> nodes) { if (node != null) { if (node.Text != null) { nodes.Add(node); } foreach (ApexSyntaxNode n in node.Nodes) { GetNodesWithText(n, nodes); } } }
/// <summary> /// Get all the nodes within this branch that have the given token. /// </summary> /// <param name="token">The token to get nodes for.</param> /// <param name="node">The node to evaluate.</param> /// <param name="nodes">The list to add matching nodes to.</param> public void GetAllNodesWithToken(Tokens token, ApexSyntaxNode node, IList <ApexSyntaxNode> nodes) { if (node != null) { if (node.Token == token) { nodes.Add(node); } foreach (ApexSyntaxNode n in node.Nodes) { GetAllNodesWithToken(token, n, nodes); } } }
/// <summary> /// Get the leaves display text of the branch from the given node. /// </summary> /// <param name="sb">The string builder to add the display text to.</param> private void GetLeavesDisplayText(ApexSyntaxNode node, StringBuilder sb) { if (node != null) { if (node.Nodes.Count == 0) { sb.Append(node.DisplayText); } else { foreach (ApexSyntaxNode n in node.Nodes) { GetLeavesDisplayText(n, sb); } } } }
/// <summary> /// Get the leaves of the branch from the given node. /// </summary> /// <param name="leaves">The list to add the leaves to.</param> private void GetLeaves(ApexSyntaxNode node, IList <Tokens> leaves) { if (node != null) { if (node.Nodes.Count == 0) { leaves.Add(node.Token); } else { foreach (ApexSyntaxNode n in node.Nodes) { GetLeaves(n, leaves); } } } }
/// <summary> /// Pop the current state. If the state info shouldn't be discarded yylloc and yylval will be set. /// </summary> /// <returns>true if the state should not be discarded, false if it should.</returns> private bool PopState() { yy_pop_state(); ApexLexerStateInfo info = _stateStack.Pop(); if (info.Discard) { return(false); } yylloc = new ApexTextSpan( info.StartPosition, tokEPos, info.StartLine, info.StartColumn + 1, tokELin, tokECol + 1); yylval = new ApexSyntaxNode(info.Token, yylloc, info.Text.ToString()); return(true); }
/// <summary> /// Get the first node found within this branch that has the given token. /// </summary> /// <param name="token">The token to get a node for.</param> /// <param name="node">The current node to evaluate.</param> /// <returns>The node within this branch that has the given token.</returns> public ApexSyntaxNode GetNodeWithToken(Tokens token, ApexSyntaxNode node) { if (node != null) { if (node.Token == token) { return(node); } else { ApexSyntaxNode result = null; foreach (ApexSyntaxNode n in node.Nodes) { result = GetNodeWithToken(token, n); if (result != null) { return(result); } } } } return(null); }
/// <summary> /// Process the the given token. /// </summary> /// <param name="token">The token to process.</param> /// <param name="span">The text span of the given token.</param> /// <param name="nodes">The nodes that reduce to the given token.</param> /// <returns>The resulting node from the reduce operation.</returns> public ApexSyntaxNode Process(Tokens token, ApexTextSpan span, ApexSyntaxNode[] nodes) { ApexSyntaxNode node = new ApexSyntaxNode(token, span, nodes); switch (node.Token) { // type reference case Tokens.grammar_type: ApexSyntaxNode[] identifierNodes = node.GetNodesWithToken(Tokens.grammar_identifier); if (identifierNodes.Length > 0) { List<TextSpan> parts = new List<TextSpan>(); foreach (ApexSyntaxNode part in identifierNodes) if (part.Nodes[0].Token != Tokens.grammar_non_reserved_identifier) parts.Add(new TextSpan(part.TextSpan)); if (parts.Count > 0) _typeReferences.Add(new ReferenceTypeSymbol( new TextPosition(node.TextSpan), node.GetLeavesDisplayText(), new TextSpan(node.TextSpan), parts.ToArray())); } break; // local variable case Tokens.grammar_local_variable_declaration: string variableType = node.GetChildNodeWithToken(Tokens.grammar_type).GetLeavesDisplayText(); ApexSyntaxNode[] variableDeclarators = node.GetNodesWithToken(Tokens.grammar_local_variable_declarator); foreach (ApexSyntaxNode declarator in variableDeclarators) { _variables.Push(new Field( new TextPosition(declarator.Nodes[0].TextSpan), declarator.Nodes[0].GetLeavesDisplayText(), null, SymbolModifier.Private, variableType, true)); } break; // variable scope case Tokens.grammar_block: case Tokens.grammar_embedded_statement: _variableScopes.Push(new VariableScope( new TextSpan(node.TextSpan), GetSymbols<Field>(node, _variables))); break; // for statement case Tokens.grammar_for_statement: ApexSyntaxNode initNode = node.GetChildNodeWithToken(Tokens.grammar_for_initializer); if (initNode != null) { ApexSyntaxNode varInitNode = node.GetChildNodeWithToken(Tokens.grammar_local_variable_declaration); if (varInitNode != null) { List<Field> varFields = new List<Field>(); ApexSyntaxNode[] varNodes = varInitNode.GetNodesWithToken(Tokens.grammar_local_variable_declaration); foreach (ApexSyntaxNode varNode in varNodes) { ApexSyntaxNode varTypeNode = varNode.GetChildNodeWithToken(Tokens.grammar_type); string varTypeName = varTypeNode.GetLeavesDisplayText(); ApexSyntaxNode varNamesNode = varNode.GetChildNodeWithToken(Tokens.grammar_local_variable_declarators); foreach (ApexSyntaxNode varNameNode in varNamesNode.GetNodesWithToken(Tokens.grammar_local_variable_declarator)) { varFields.Add(new Field( new TextPosition(varNameNode.TextSpan), varNameNode.GetLeavesDisplayText(), null, SymbolModifier.Private, varTypeName, true)); } } if (varFields.Count > 0) { _variableScopes.Push(new VariableScope( new TextSpan(node.TextSpan), varFields.ToArray())); } } } break; // foreach statement case Tokens.grammar_foreach_statement: _variableScopes.Push(new VariableScope( new TextSpan(node.TextSpan), new Field[] { new Field( new TextPosition(node.Nodes[3].TextSpan), node.Nodes[3].GetLeavesDisplayText(), null, SymbolModifier.Private, node.Nodes[2].GetLeavesDisplayText(), true) })); break; // catch clause case Tokens.grammar_specific_catch_clause: ApexSyntaxNode classTypeNode = node.GetChildNodeWithToken(Tokens.grammar_class_type); ApexSyntaxNode identifierNode = node.GetChildNodeWithToken(Tokens.grammar_identifier); if (classTypeNode != null && identifierNode != null) { _variableScopes.Push(new VariableScope( new TextSpan(node.TextSpan), new Field[] { new Field( new TextPosition(identifierNode.TextSpan), identifierNode.GetLeavesDisplayText(), null, SymbolModifier.Private, classTypeNode.GetLeavesDisplayText(), true)})); _typeReferences.Add(new ReferenceTypeSymbol( new TextPosition(classTypeNode.TextSpan), classTypeNode.GetLeavesDisplayText(), null, new TextSpan[] { new TextSpan(classTypeNode.TextSpan) })); } break; // field case Tokens.grammar_field_declaration: SymbolModifier fieldVisibility = GetModifiers(node.GetNodesWithToken(Tokens.grammar_modifier)); string fieldType = node.GetChildNodeWithToken(Tokens.grammar_type).GetLeavesDisplayText(); ApexSyntaxNode[] fieldDeclarators = node.GetNodesWithToken(Tokens.grammar_variable_declarator); foreach (ApexSyntaxNode declarator in fieldDeclarators) { _fields.Push(new Field( new TextPosition(declarator.Nodes[0].TextSpan), declarator.Nodes[0].GetLeavesDisplayText(), null, fieldVisibility, fieldType, false)); } break; // enum member case Tokens.grammar_enum_member_declaration: _enumFields.Push(new Field( new TextPosition(node.TextSpan), node.GetLeavesDisplayText(), null, SymbolModifier.Final | SymbolModifier.Public | SymbolModifier.Static, "System.Object", false)); break; // property case Tokens.grammar_property_declaration: SymbolModifier propertyVisibility = GetModifiers(node.GetNodesWithToken(Tokens.grammar_modifier)); string propertyType = node.GetChildNodeWithToken(Tokens.grammar_type).GetLeavesDisplayText(); ApexSyntaxNode propertyName = node.GetChildNodeWithToken(Tokens.grammar_identifier); _properties.Push(new Property( new TextPosition(propertyName.TextSpan), propertyName.GetLeavesDisplayText(), new TextSpan(node.TextSpan), propertyVisibility, propertyType)); break; // constructor case Tokens.grammar_constructor_declaration: SymbolModifier constructorVisibility = GetModifiers(node.GetNodesWithToken(Tokens.grammar_modifier)); ApexSyntaxNode constructorName = node.GetNodeWithToken(Tokens.grammar_constructor_declarator).Nodes[0]; Parameter[] constructorParameters = GetParameters(node.GetNodesWithToken(Tokens.grammar_fixed_parameter)); _constructors.Push(new Constructor( new TextPosition(constructorName.TextSpan), constructorName.GetLeavesDisplayText(), new TextSpan(node.TextSpan), constructorVisibility, constructorParameters)); break; // method case Tokens.grammar_method_declaration: ApexSyntaxNode methodHeader = node.GetNodeWithToken(Tokens.grammar_method_header); SymbolModifier methodVisibility = GetModifiers(methodHeader.GetNodesWithToken(Tokens.grammar_modifier)); ApexSyntaxNode methodName = methodHeader.GetChildNodeWithToken(Tokens.grammar_identifier); Parameter[] methodParameters = GetParameters(methodHeader.GetNodesWithToken(Tokens.grammar_fixed_parameter)); string methodReturnType = (methodHeader.GetChildNodeWithToken(Tokens.KEYWORD_VOID) != null) ? "void" : methodHeader.GetChildNodeWithToken(Tokens.grammar_type).GetLeavesDisplayText(); _methods.Push(new Method( new TextPosition(methodName.TextSpan), methodName.GetLeavesDisplayText(), new TextSpan(node.TextSpan), methodVisibility, methodReturnType, methodParameters)); break; // interface method case Tokens.grammar_interface_method_declaration: ApexSyntaxNode interfaceMethodName = node.GetChildNodeWithToken(Tokens.grammar_identifier); Parameter[] interfaceMethodParameters = GetParameters(node.GetNodesWithToken(Tokens.grammar_fixed_parameter)); string interfaceMethodReturnType = (node.GetChildNodeWithToken(Tokens.KEYWORD_VOID) != null) ? "void" : node.GetChildNodeWithToken(Tokens.grammar_type).GetLeavesDisplayText(); _methods.Push(new Method( new TextPosition(interfaceMethodName.TextSpan), interfaceMethodName.GetLeavesDisplayText(), new TextSpan(node.TextSpan), SymbolModifier.Public, interfaceMethodReturnType, interfaceMethodParameters)); break; // class case Tokens.grammar_class_declaration: ApexSyntaxNode classModifiers = node.GetChildNodeWithToken(Tokens.grammar_modifiers); SymbolModifier classVisibility = SymbolModifier.Private; if (classModifiers != null) classVisibility = GetModifiers(classModifiers.GetNodesWithToken(Tokens.grammar_modifier)); ApexSyntaxNode className = node.GetChildNodeWithToken(Tokens.grammar_identifier); _typeReferences.Add(new ReferenceTypeSymbol( new TextPosition(className.TextSpan), className.GetLeavesDisplayText(), null, new TextSpan[] { new TextSpan(className.TextSpan) })); ApexSyntaxNode classBase = node.GetChildNodeWithToken(Tokens.grammar_class_base); List<string> classInterfaces = new List<string>(); string classExtends = null; if (classBase != null) { foreach (ApexSyntaxNode classInterface in classBase.GetNodesWithToken(Tokens.grammar_interface_type)) { string name = classInterface.GetLeavesDisplayText(); classInterfaces.Add(name); _typeReferences.Add(new ReferenceTypeSymbol( new TextPosition(classInterface.TextSpan), name, null, new TextSpan[] { new TextSpan(classInterface.TextSpan) })); } ApexSyntaxNode extends = classBase.GetChildNodeWithToken(Tokens.grammar_class_type); if (extends != null) { classExtends = extends.GetLeavesDisplayText(); _typeReferences.Add(new ReferenceTypeSymbol( new TextPosition(extends.TextSpan), classExtends, null, new TextSpan[] { new TextSpan(extends.TextSpan) })); } } List<string> attributeList = new List<string>(); ApexSyntaxNode attributes = node.GetChildNodeWithToken(Tokens.grammar_attributes); if (attributes != null) { foreach (ApexSyntaxNode attributeSection in attributes.GetNodesWithToken(Tokens.grammar_attribute_section)) { attributeList.Add(attributeSection.GetChildNodeWithToken(Tokens.grammar_identifier).GetLeavesDisplayText()); } } List<VariableScope> classScopes = new List<VariableScope>(); _classes.Push(new SymbolTable( new TextPosition(className.TextSpan), className.GetLeavesDisplayText(), new TextSpan(node.TextSpan), attributeList.ToArray(), classVisibility, SymbolTableType.Class, GetSymbols<VariableScope>(node, _variableScopes), GetSymbols<Field>(node, _fields), GetSymbols<Constructor>(node, _constructors), GetSymbols<Property>(node, _properties), GetSymbols<Method>(node, _methods), classExtends, classInterfaces.ToArray(), GetSymbols<SymbolTable>(node, _classes))); break; // interface case Tokens.grammar_interface_declaration: ApexSyntaxNode interfaceModifiers = node.GetChildNodeWithToken(Tokens.grammar_modifiers); SymbolModifier interfaceVisibility = SymbolModifier.Private; if (interfaceModifiers != null) interfaceVisibility = GetModifiers(interfaceModifiers.GetNodesWithToken(Tokens.grammar_modifier)); ApexSyntaxNode interfaceName = node.GetChildNodeWithToken(Tokens.grammar_identifier); _typeReferences.Add(new ReferenceTypeSymbol(new TextPosition(interfaceName.TextSpan), interfaceName.GetLeavesDisplayText(), null, null)); ApexSyntaxNode interfaceBase = node.GetChildNodeWithToken(Tokens.grammar_interface_base); List<string> interfaceBases = new List<string>(); string interfaceExtends = null; if (interfaceBase != null) { foreach (ApexSyntaxNode interfaceInterface in interfaceBase.GetNodesWithToken(Tokens.grammar_interface_type)) { string name = interfaceInterface.GetLeavesDisplayText(); interfaceBases.Add(interfaceInterface.GetLeavesDisplayText()); _typeReferences.Add(new ReferenceTypeSymbol( new TextPosition(interfaceInterface.TextSpan), name, null, new TextSpan[] { new TextSpan(interfaceInterface.TextSpan) })); } ApexSyntaxNode extends = interfaceBase.GetChildNodeWithToken(Tokens.grammar_class_type); if (extends != null) { interfaceExtends = extends.GetLeavesDisplayText(); _typeReferences.Add(new ReferenceTypeSymbol( new TextPosition(extends.TextSpan), interfaceExtends, null, new TextSpan[] { new TextSpan(extends.TextSpan) })); } } _classes.Push(new SymbolTable( new TextPosition(interfaceName.TextSpan), interfaceName.GetLeavesDisplayText(), new TextSpan(node.TextSpan), null, interfaceVisibility, SymbolTableType.Interface, null, null, null, null, GetSymbols<Method>(node, _methods), interfaceExtends, interfaceBases.ToArray(), GetSymbols<SymbolTable>(node, _classes))); break; // enum case Tokens.grammar_enum_declaration: ApexSyntaxNode enumModifiers = node.GetChildNodeWithToken(Tokens.grammar_modifiers); SymbolModifier enumVisibility = SymbolModifier.Private; if (enumModifiers != null) enumVisibility = GetModifiers(enumModifiers.GetNodesWithToken(Tokens.grammar_modifier)); ApexSyntaxNode enumName = node.GetChildNodeWithToken(Tokens.grammar_identifier); _typeReferences.Add(new ReferenceTypeSymbol( new TextPosition(enumName.TextSpan), enumName.GetLeavesDisplayText(), null, new TextSpan[] { new TextSpan(enumName.TextSpan) })); List<string> enumAttributeList = new List<string>(); ApexSyntaxNode enumAttributes = node.GetChildNodeWithToken(Tokens.grammar_attributes); if (enumAttributes != null) { foreach (ApexSyntaxNode attributeSection in enumAttributes.GetNodesWithToken(Tokens.grammar_attribute_section)) { enumAttributeList.Add(attributeSection.GetChildNodeWithToken(Tokens.grammar_identifier).GetLeavesDisplayText()); } } _classes.Push(new SymbolTable( new TextPosition(enumName.TextSpan), enumName.GetLeavesDisplayText(), new TextSpan(node.TextSpan), enumAttributeList.ToArray(), enumVisibility, SymbolTableType.Enum, null, GetSymbols<Field>(node, _enumFields), null, null, null, null, null, null)); break; // trigger case Tokens.grammar_trigger_declaration: ApexSyntaxNode headerNode = node.GetChildNodeWithToken(Tokens.grammar_trigger_header); ApexSyntaxNode triggerNameNode = headerNode.Nodes[1]; _classes.Push(new SymbolTable( new TextPosition(triggerNameNode.TextSpan), triggerNameNode.GetLeavesDisplayText(), new TextSpan(node.TextSpan), null, SymbolModifier.Private, SymbolTableType.Trigger, GetSymbols<VariableScope>(node, _variableScopes), null, null, null, null, null, null, null)); break; default: break; } return node; }