1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
#ifndef CPP_EXTRACT_PARSER_H
#define CPP_EXTRACT_PARSER_H
#include "diagnostics.h"
#include "node.h"
#include "identifier-lookup.h"
#include "../../source/compiler-core/slang-lexer.h"
namespace CppExtract {
using namespace Slang;
class TypeSet : public RefObject
{
public:
/// This is the looked up name.
UnownedStringSlice m_macroName; ///< The name extracted from the macro SLANG_ABSTRACT_AST_CLASS -> AST
String m_typeName; ///< The enum type name associated with this type for AST it is ASTNode
String m_fileMark; ///< This 'mark' becomes of the output filename
List<ClassLikeNode*> m_baseTypes; ///< The base types for this type set
};
class SourceOrigin : public RefObject
{
public:
void addNode(Node* node)
{
if (auto classLike = as<ClassLikeNode>(node))
{
SLANG_ASSERT(classLike->m_origin == nullptr);
classLike->m_origin = this;
}
m_nodes.add(node);
}
SourceOrigin(SourceFile* sourceFile, const String& macroOrigin) :
m_sourceFile(sourceFile),
m_macroOrigin(macroOrigin)
{}
String m_macroOrigin; ///< The macro text is inserted into the macro to identify the origin. It is based on the filename
SourceFile* m_sourceFile; ///< The source file - also holds the path information
/// All of the nodes defined in this file in the order they were defined
/// Note that the same namespace may be listed multiple times.
List<RefPtr<Node> > m_nodes;
};
struct Options;
class IdentifierLookup;
/* NodeTree holds nodes that have been parsed into a tree rooted on the 'rootNode'.
Also contains other state associated with or useful to a node tree */
class NodeTree
{
public:
friend class Parser;
/// Get all of the parsed source origins
const List<RefPtr<SourceOrigin> >& getSourceOrigins() const { return m_sourceOrigins; }
TypeSet* getTypeSet(const UnownedStringSlice& slice);
TypeSet* getOrAddTypeSet(const UnownedStringSlice& slice);
SourceOrigin* addSourceOrigin(SourceFile* sourceFile, const Options& options);
/// Get all of the type sets
const List<RefPtr<TypeSet>>& getTypeSets() const { return m_typeSets; }
/// Get the root node
Node* getRootNode() const { return m_rootNode; }
/// When parsing we don't lookup all up super types/add derived types. This is because
/// we allow files to be processed in any order, so we have to do the type lookup as a separate operation
SlangResult calcDerivedTypes(DiagnosticSink* sink);
NodeTree(StringSlicePool* typePool, NamePool* namePool, IdentifierLookup* identifierLookup);
static String calcMacroOrigin(const String& filePath, const Options& options);
protected:
SlangResult _calcDerivedTypesRec(ScopeNode* node, DiagnosticSink* sink);
StringSlicePool m_typeSetPool; ///< Pool for type set names
List<RefPtr<TypeSet> > m_typeSets; ///< The type sets
IdentifierLookup* m_identifierLookup;
StringSlicePool* m_typePool; ///< Pool for just types
NamePool* m_namePool;
RefPtr<ScopeNode> m_rootNode; ///< The root scope
List<RefPtr<SourceOrigin>> m_sourceOrigins;
};
class Parser
{
public:
SlangResult expect(TokenType type, Token* outToken = nullptr);
bool advanceIfMarker(Token* outToken = nullptr);
bool advanceIfToken(TokenType type, Token* outToken = nullptr);
bool advanceIfStyle(IdentifierStyle style, Token* outToken = nullptr);
SlangResult pushAnonymousNamespace();
SlangResult pushScope(ScopeNode* node);
SlangResult consumeToClosingBrace(const Token* openBraceToken = nullptr);
SlangResult popScope();
/// Parse the contents of the source file
SlangResult parse(SourceOrigin* sourceOrigin, const Options* options);
Parser(NodeTree* nodeTree, DiagnosticSink* sink);
protected:
static Node::Type _toNodeType(IdentifierStyle style);
bool _isMarker(const UnownedStringSlice& name);
SlangResult _parsePreDeclare();
SlangResult _parseTypeSet();
SlangResult _maybeParseNode(Node::Type type);
SlangResult _maybeParseField();
SlangResult _maybeParseType(UnownedStringSlice& outType);
SlangResult _maybeParseType(UnownedStringSlice& outType, Index& ioTemplateDepth);
SlangResult _maybeParseTemplateArgs(Index& ioTemplateDepth);
SlangResult _maybeParseTemplateArg(Index& ioTemplateDepth);
/// Parse balanced - if a sink is set will report to that sink
SlangResult _parseBalanced(DiagnosticSink* sink);
/// Concatenate all tokens from start to the current position
UnownedStringSlice _concatTokens(TokenReader::ParsingCursor start);
void _consumeTypeModifiers();
SlangResult _consumeToSync();
TokenList m_tokenList;
TokenReader m_reader;
ScopeNode* m_currentScope; ///< The current scope being processed
SourceOrigin* m_sourceOrigin; ///< The source origin that all tokens are in
DiagnosticSink* m_sink; ///< Diagnostic sink
NodeTree* m_nodeTree; ///< Shared state between parses. Nodes will be added to this
const Options* m_options;
};
} // CppExtract
#endif
|