private void ParseStruct(LinkedListStream <IBaseToken> stream) { CppToken structKeywordToken = stream.Peek <CppToken>(); Debug.Assert(structKeywordToken.Kind == CppTokenKind.ReservedKeyword && ("struct".Equals(structKeywordToken.Value) || "union".Equals(structKeywordToken.Value))); var typedefResult = Search(stream.CurrentNode, SearchMode.Prev, (t) => t.Kind == CppTokenKind.ReservedKeyword && "typedef".Equals(t.Value)); bool isTypedef = typedefResult != null; stream.Next(); // There are multiple ways to define a struct in C // A = typedef struct { int a; } foo; // B = typedef struct foo { int a; } sFoo; (prefered style) // C = struct { int a; }; (Anonymous struct without a name) // D = struct { int a; } memberName; (Anonymous struct named as a member) // E = struct foo { int a; }; (C++ style) // B/E var identTokenResult = Search(stream, SearchMode.Current, CppTokenKind.IdentLiteral); if (identTokenResult != null) { var identToken = identTokenResult.Token; string structIdent = identToken.Value; stream.Next(); CppEntityKind kind = CppEntityKind.Struct; var terminatorTokenResult = Search(stream, SearchMode.Current, CppTokenKind.Semicolon, CppTokenKind.LeftBrace); if (terminatorTokenResult != null) { var terminatorToken = terminatorTokenResult.Token; if (terminatorToken.Kind == CppTokenKind.Semicolon) { kind = CppEntityKind.ForwardStruct; } stream.Next(); } CppEntity structEntity = new CppEntity(kind, identToken, structIdent) { DocumentationNode = FindDocumentationNode(identTokenResult.Node, 1), }; CppNode structNode = new CppNode(Top, structEntity); Add(structNode); SymbolCache.AddSource(Tag, structIdent, new SourceSymbol(SourceSymbolKind.CppStruct, identToken.Range, structNode)); } // @TODO(final): Parse struct members }
public CppEntity(CppEntityKind kind, IBaseToken token, string ident) : base(token.Range) { Kind = kind; Id = ident; }
private bool ParseFunction(LinkedListStream <IBaseToken> stream) { var functionIdentNode = stream.CurrentNode; CppToken functionIdentToken = functionIdentNode.Value as CppToken; Debug.Assert(functionIdentToken.Kind == CppTokenKind.IdentLiteral); var functionName = functionIdentToken.Value; CppTokenKind[] funcCallKinds = { CppTokenKind.EqOp, CppTokenKind.Comma, CppTokenKind.LeftParen, CppTokenKind.AddOp, CppTokenKind.AddAssign, CppTokenKind.SubOp, CppTokenKind.SubAssign, CppTokenKind.DivOp, CppTokenKind.DivAssign, CppTokenKind.MulAssign, CppTokenKind.XorOp, CppTokenKind.XorAssign, CppTokenKind.LeftShiftOp, CppTokenKind.LeftShiftAssign, CppTokenKind.RightShiftOp, CppTokenKind.RightShiftAssign, }; var funcCallResult = Search(stream, SearchMode.Prev, funcCallKinds); CppEntityKind kind = CppEntityKind.FunctionCall; // Skip ident stream.Next(); // Skip parameters CppToken openParenToken = stream.Peek <CppToken>(); Debug.Assert(openParenToken.Kind == CppTokenKind.LeftParen); stream.Next(); var closeParenResult = Search(stream, SearchMode.Forward, CppTokenKind.RightParen); if (closeParenResult == null) { AddError(openParenToken.Position, $"Unterminated function '{functionName}'", "Function", functionName); return(true); } stream.Seek(closeParenResult.Node); stream.Next(); if (funcCallResult == null) { var endingTokenResult = Search(stream, SearchMode.Current, CppTokenKind.Semicolon, CppTokenKind.LeftBrace); if (endingTokenResult != null) { stream.Next(); if (endingTokenResult.Token.Kind == CppTokenKind.LeftBrace) { kind = CppEntityKind.FunctionBody; if (Configuration.SkipFunctionBlocks) { return(true); } } else { kind = CppEntityKind.FunctionDefinition; } } } CppEntity functionEntity = new CppEntity(kind, functionIdentToken, functionName) { DocumentationNode = FindDocumentationNode(functionIdentNode, 1), }; CppNode functionNode = new CppNode(Top, functionEntity); Add(functionNode); if (kind == CppEntityKind.FunctionDefinition) { SymbolCache.AddSource(Tag, functionName, new SourceSymbol(SourceSymbolKind.CppFunctionDefinition, functionIdentToken.Range, functionNode)); } else if (kind == CppEntityKind.FunctionBody) { SymbolCache.AddSource(Tag, functionName, new SourceSymbol(SourceSymbolKind.CppFunctionBody, functionIdentToken.Range, functionNode)); } else if (Configuration.FunctionCallSymbolsEnabled) { SymbolCache.AddReference(Tag, functionName, new ReferenceSymbol(ReferenceSymbolKind.CppFunction, functionIdentToken.Range, functionNode)); } return(true); }
private void ParseTypedef(LinkedListStream <IBaseToken> stream) { CppToken typedefToken = stream.Peek <CppToken>(); Debug.Assert(typedefToken.Kind == CppTokenKind.ReservedKeyword && "typedef".Equals(typedefToken.Value)); stream.Next(); var reservedKeywordResult = Search(stream, SearchMode.Current, CppTokenKind.ReservedKeyword); if (reservedKeywordResult != null) { var reservedKeywordToken = reservedKeywordResult.Token; string keyword = reservedKeywordToken.Value; switch (keyword) { case "union": case "struct": ParseStruct(stream); return; case "enum": ParseEnum(stream, reservedKeywordToken.Position); return; } } // Normal typedef CppEntityKind kind = CppEntityKind.Typedef; var semicolonResult = Search(stream, SearchMode.Forward, CppTokenKind.Semicolon); if (semicolonResult != null) { stream.Seek(semicolonResult.Node); stream.Next(); SearchResult <CppToken> identResult = null; var prevResult = Search(semicolonResult, SearchMode.Prev, CppTokenKind.RightParen, CppTokenKind.IdentLiteral); if (prevResult != null) { if (prevResult.Token.Kind == CppTokenKind.RightParen) { // Function typedef var leftParenResult = Search(prevResult, SearchMode.Backward, CppTokenKind.LeftParen); if (leftParenResult != null) { var rightParentResult = Search(leftParenResult, SearchMode.Prev, CppTokenKind.RightParen); if (rightParentResult != null) { leftParenResult = Search(rightParentResult, SearchMode.Backward, CppTokenKind.LeftParen); if (leftParenResult != null) { identResult = Search(leftParenResult, SearchMode.Next, CppTokenKind.IdentLiteral); kind = CppEntityKind.FunctionTypedef; } } else { // Typedef on define // #define MY_TYPEDEF(name) // typedef MY_TYPEDEF(my_typedef); //Debug.WriteLine("Right paren not found!"); } } } else { // Type typedef Debug.Assert(prevResult.Token.Kind == CppTokenKind.IdentLiteral); identResult = prevResult; } } if (identResult != null) { var identToken = identResult.Token; string typedefIdent = identToken.Value; CppEntity typedefEntity = new CppEntity(kind, identToken, typedefIdent) { DocumentationNode = FindDocumentationNode(identResult.Node, 1), }; var typedefNode = new CppNode(Top, typedefEntity); Add(typedefNode); SymbolCache.AddSource(Tag, typedefIdent, new SourceSymbol(SourceSymbolKind.CppType, identToken.Range)); } } }
private void ParseEnum(LinkedListStream <IBaseToken> stream, TextPosition pos) { CppToken enumBaseToken = stream.Peek <CppToken>(); Debug.Assert(enumBaseToken.Kind == CppTokenKind.ReservedKeyword && "enum".Equals(enumBaseToken.Value)); stream.Next(); SearchResult <CppToken> enumIdentResult = null; var classKeywordResult = Search(stream, SearchMode.Current, CppTokenKind.ReservedKeyword); if (classKeywordResult != null) { string keyword = classKeywordResult.Token.Value; if ("class".Equals(keyword)) { // enum class stream.Next(); enumIdentResult = Search(stream, SearchMode.Current, CppTokenKind.IdentLiteral); if (enumIdentResult == null) { var token = stream.Peek <CppToken>(); AddError(pos, $"Expect identifier token, but got token kind {token?.Kind} for enum", "enum"); return; } } } if (enumIdentResult == null) { // Ident after enum var identAfterEnumResult = Search(stream, SearchMode.Current, CppTokenKind.IdentLiteral); if (identAfterEnumResult != null) { stream.Next(); enumIdentResult = identAfterEnumResult; } } if (enumIdentResult != null) { var braceOrSemiResult = Search(stream, SearchMode.Current, CppTokenKind.LeftBrace, CppTokenKind.Semicolon); if (braceOrSemiResult == null) { return; } var enumIdentToken = enumIdentResult.Token; string enumIdent = enumIdentToken.Value; CppEntityKind kind = braceOrSemiResult.Token.Kind == CppTokenKind.Semicolon ? CppEntityKind.ForwardEnum : CppEntityKind.Enum; CppEntity enumRootEntity = new CppEntity(kind, enumIdentToken, enumIdent) { DocumentationNode = FindDocumentationNode(enumIdentResult.Node, 1), }; CppNode enumRootNode = new CppNode(Top, enumRootEntity); Add(enumRootNode); SymbolCache.AddSource(Tag, enumIdent, new SourceSymbol(SourceSymbolKind.CppEnum, enumIdentToken.Range, enumRootNode)); if (braceOrSemiResult.Token.Kind == CppTokenKind.LeftBrace) { ParseEnumValues(stream, enumRootNode); } else { stream.Next(); } } else { var token = stream.Peek <CppToken>(); AddError(pos, $"Expect identifier token, but got token kind {token?.Kind} for enum", "enum"); return; } }