c-next 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +726 -0
- package/bin/cnext.js +5 -0
- package/grammar/C.g4 +1112 -0
- package/grammar/CNext.g4 +817 -0
- package/grammar/CPP14Lexer.g4 +282 -0
- package/grammar/CPP14Parser.g4 +1072 -0
- package/package.json +85 -0
- package/src/analysis/DivisionByZeroAnalyzer.ts +378 -0
- package/src/analysis/FunctionCallAnalyzer.ts +526 -0
- package/src/analysis/InitializationAnalyzer.ts +725 -0
- package/src/analysis/NullCheckAnalyzer.ts +427 -0
- package/src/analysis/types/IDivisionByZeroError.ts +25 -0
- package/src/analysis/types/IFunctionCallError.ts +17 -0
- package/src/analysis/types/IInitializationError.ts +55 -0
- package/src/analysis/types/INullCheckError.ts +25 -0
- package/src/codegen/CodeGenerator.ts +7945 -0
- package/src/codegen/CommentExtractor.ts +240 -0
- package/src/codegen/CommentFormatter.ts +155 -0
- package/src/codegen/HeaderGenerator.ts +265 -0
- package/src/codegen/TypeResolver.ts +365 -0
- package/src/codegen/types/ECommentType.ts +10 -0
- package/src/codegen/types/IComment.ts +21 -0
- package/src/codegen/types/ICommentError.ts +15 -0
- package/src/codegen/types/TOverflowBehavior.ts +6 -0
- package/src/codegen/types/TParameterInfo.ts +13 -0
- package/src/codegen/types/TTypeConstants.ts +94 -0
- package/src/codegen/types/TTypeInfo.ts +22 -0
- package/src/index.ts +518 -0
- package/src/lib/IncludeDiscovery.ts +131 -0
- package/src/lib/InputExpansion.ts +121 -0
- package/src/lib/PlatformIODetector.ts +162 -0
- package/src/lib/transpiler.ts +439 -0
- package/src/lib/types/ITranspileResult.ts +80 -0
- package/src/parser/c/grammar/C.interp +338 -0
- package/src/parser/c/grammar/C.tokens +229 -0
- package/src/parser/c/grammar/CLexer.interp +415 -0
- package/src/parser/c/grammar/CLexer.tokens +229 -0
- package/src/parser/c/grammar/CLexer.ts +750 -0
- package/src/parser/c/grammar/CListener.ts +976 -0
- package/src/parser/c/grammar/CParser.ts +9663 -0
- package/src/parser/c/grammar/CVisitor.ts +626 -0
- package/src/parser/cpp/grammar/CPP14Lexer.interp +478 -0
- package/src/parser/cpp/grammar/CPP14Lexer.tokens +264 -0
- package/src/parser/cpp/grammar/CPP14Lexer.ts +848 -0
- package/src/parser/cpp/grammar/CPP14Parser.interp +492 -0
- package/src/parser/cpp/grammar/CPP14Parser.tokens +264 -0
- package/src/parser/cpp/grammar/CPP14Parser.ts +19961 -0
- package/src/parser/cpp/grammar/CPP14ParserListener.ts +2120 -0
- package/src/parser/cpp/grammar/CPP14ParserVisitor.ts +1354 -0
- package/src/parser/grammar/CNext.interp +340 -0
- package/src/parser/grammar/CNext.tokens +214 -0
- package/src/parser/grammar/CNextLexer.interp +374 -0
- package/src/parser/grammar/CNextLexer.tokens +214 -0
- package/src/parser/grammar/CNextLexer.ts +668 -0
- package/src/parser/grammar/CNextListener.ts +1020 -0
- package/src/parser/grammar/CNextParser.ts +9239 -0
- package/src/parser/grammar/CNextVisitor.ts +654 -0
- package/src/preprocessor/Preprocessor.ts +301 -0
- package/src/preprocessor/ToolchainDetector.ts +225 -0
- package/src/preprocessor/types/IPreprocessResult.ts +39 -0
- package/src/preprocessor/types/IToolchain.ts +27 -0
- package/src/project/FileDiscovery.ts +236 -0
- package/src/project/Project.ts +425 -0
- package/src/project/types/IProjectConfig.ts +64 -0
- package/src/symbols/CNextSymbolCollector.ts +326 -0
- package/src/symbols/CSymbolCollector.ts +457 -0
- package/src/symbols/CppSymbolCollector.ts +362 -0
- package/src/symbols/SymbolTable.ts +312 -0
- package/src/symbols/types/IConflict.ts +20 -0
- package/src/types/ESourceLanguage.ts +10 -0
- package/src/types/ESymbolKind.ts +20 -0
- package/src/types/ISymbol.ts +45 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C Symbol Collector
|
|
3
|
+
* Extracts symbols from C parse trees for the unified symbol table
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
CompilationUnitContext,
|
|
8
|
+
ExternalDeclarationContext,
|
|
9
|
+
FunctionDefinitionContext,
|
|
10
|
+
DeclarationContext,
|
|
11
|
+
DeclarationSpecifiersContext,
|
|
12
|
+
InitDeclaratorListContext,
|
|
13
|
+
StructOrUnionSpecifierContext,
|
|
14
|
+
EnumSpecifierContext,
|
|
15
|
+
} from "../parser/c/grammar/CParser";
|
|
16
|
+
import ISymbol from "../types/ISymbol";
|
|
17
|
+
import ESymbolKind from "../types/ESymbolKind";
|
|
18
|
+
import ESourceLanguage from "../types/ESourceLanguage";
|
|
19
|
+
import SymbolTable from "./SymbolTable";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Collects symbols from a C parse tree
|
|
23
|
+
*/
|
|
24
|
+
class CSymbolCollector {
|
|
25
|
+
private sourceFile: string;
|
|
26
|
+
|
|
27
|
+
private symbols: ISymbol[] = [];
|
|
28
|
+
|
|
29
|
+
private symbolTable: SymbolTable | null;
|
|
30
|
+
|
|
31
|
+
constructor(sourceFile: string, symbolTable?: SymbolTable) {
|
|
32
|
+
this.sourceFile = sourceFile;
|
|
33
|
+
this.symbolTable = symbolTable ?? null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Collect all symbols from a C compilation unit
|
|
38
|
+
*/
|
|
39
|
+
collect(tree: CompilationUnitContext): ISymbol[] {
|
|
40
|
+
this.symbols = [];
|
|
41
|
+
|
|
42
|
+
const translationUnit = tree.translationUnit();
|
|
43
|
+
if (!translationUnit) {
|
|
44
|
+
return this.symbols;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
for (const extDecl of translationUnit.externalDeclaration()) {
|
|
48
|
+
this.collectExternalDeclaration(extDecl);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return this.symbols;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private collectExternalDeclaration(
|
|
55
|
+
extDecl: ExternalDeclarationContext,
|
|
56
|
+
): void {
|
|
57
|
+
// Function definition
|
|
58
|
+
const funcDef = extDecl.functionDefinition();
|
|
59
|
+
if (funcDef) {
|
|
60
|
+
this.collectFunctionDefinition(funcDef);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Declaration (typedef, struct, variable, function prototype)
|
|
65
|
+
const decl = extDecl.declaration();
|
|
66
|
+
if (decl) {
|
|
67
|
+
this.collectDeclaration(decl);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private collectFunctionDefinition(funcDef: FunctionDefinitionContext): void {
|
|
72
|
+
const declarator = funcDef.declarator();
|
|
73
|
+
if (!declarator) return;
|
|
74
|
+
|
|
75
|
+
// Extract function name from declarator
|
|
76
|
+
const name = this.extractDeclaratorName(declarator);
|
|
77
|
+
if (!name) return;
|
|
78
|
+
|
|
79
|
+
const line = funcDef.start?.line ?? 0;
|
|
80
|
+
|
|
81
|
+
// Get return type from declaration specifiers
|
|
82
|
+
const declSpecs = funcDef.declarationSpecifiers();
|
|
83
|
+
const returnType = declSpecs
|
|
84
|
+
? this.extractTypeFromDeclSpecs(declSpecs)
|
|
85
|
+
: "int";
|
|
86
|
+
|
|
87
|
+
this.symbols.push({
|
|
88
|
+
name,
|
|
89
|
+
kind: ESymbolKind.Function,
|
|
90
|
+
type: returnType,
|
|
91
|
+
sourceFile: this.sourceFile,
|
|
92
|
+
sourceLine: line,
|
|
93
|
+
sourceLanguage: ESourceLanguage.C,
|
|
94
|
+
isExported: true,
|
|
95
|
+
isDeclaration: false,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private collectDeclaration(decl: DeclarationContext): void {
|
|
100
|
+
const declSpecs = decl.declarationSpecifiers();
|
|
101
|
+
if (!declSpecs) return;
|
|
102
|
+
|
|
103
|
+
const line = decl.start?.line ?? 0;
|
|
104
|
+
|
|
105
|
+
// Check for typedef
|
|
106
|
+
const isTypedef = this.hasStorageClass(declSpecs, "typedef");
|
|
107
|
+
const isExtern = this.hasStorageClass(declSpecs, "extern");
|
|
108
|
+
|
|
109
|
+
// Check for struct/union
|
|
110
|
+
const structSpec = this.findStructOrUnionSpecifier(declSpecs);
|
|
111
|
+
if (structSpec) {
|
|
112
|
+
// For typedef struct, extract the typedef name from declarationSpecifiers
|
|
113
|
+
// Example: typedef struct { ... } AppConfig;
|
|
114
|
+
// "AppConfig" appears as a typedefName in declarationSpecifiers
|
|
115
|
+
let typedefName: string | undefined;
|
|
116
|
+
if (isTypedef) {
|
|
117
|
+
for (const spec of declSpecs.declarationSpecifier()) {
|
|
118
|
+
const typeSpec = spec.typeSpecifier();
|
|
119
|
+
if (typeSpec) {
|
|
120
|
+
const typeName = typeSpec.typedefName?.();
|
|
121
|
+
if (typeName) {
|
|
122
|
+
typedefName = typeName.getText();
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.collectStructOrUnion(structSpec, line, typedefName);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Check for enum
|
|
133
|
+
const enumSpec = this.findEnumSpecifier(declSpecs);
|
|
134
|
+
if (enumSpec) {
|
|
135
|
+
this.collectEnum(enumSpec, line);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Collect declarators (variables, function prototypes, typedefs)
|
|
139
|
+
const initDeclList = decl.initDeclaratorList();
|
|
140
|
+
if (initDeclList) {
|
|
141
|
+
const baseType = this.extractTypeFromDeclSpecs(declSpecs);
|
|
142
|
+
this.collectInitDeclaratorList(
|
|
143
|
+
initDeclList,
|
|
144
|
+
baseType,
|
|
145
|
+
isTypedef,
|
|
146
|
+
isExtern,
|
|
147
|
+
line,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private collectInitDeclaratorList(
|
|
153
|
+
initDeclList: InitDeclaratorListContext,
|
|
154
|
+
baseType: string,
|
|
155
|
+
isTypedef: boolean,
|
|
156
|
+
isExtern: boolean,
|
|
157
|
+
line: number,
|
|
158
|
+
): void {
|
|
159
|
+
for (const initDecl of initDeclList.initDeclarator()) {
|
|
160
|
+
const declarator = initDecl.declarator();
|
|
161
|
+
if (!declarator) continue;
|
|
162
|
+
|
|
163
|
+
const name = this.extractDeclaratorName(declarator);
|
|
164
|
+
if (!name) continue;
|
|
165
|
+
|
|
166
|
+
// Check if this is a function declaration (has parameter list)
|
|
167
|
+
const isFunction = this.declaratorIsFunction(declarator);
|
|
168
|
+
|
|
169
|
+
if (isTypedef) {
|
|
170
|
+
this.symbols.push({
|
|
171
|
+
name,
|
|
172
|
+
kind: ESymbolKind.Type,
|
|
173
|
+
type: baseType,
|
|
174
|
+
sourceFile: this.sourceFile,
|
|
175
|
+
sourceLine: line,
|
|
176
|
+
sourceLanguage: ESourceLanguage.C,
|
|
177
|
+
isExported: true,
|
|
178
|
+
});
|
|
179
|
+
} else if (isFunction) {
|
|
180
|
+
this.symbols.push({
|
|
181
|
+
name,
|
|
182
|
+
kind: ESymbolKind.Function,
|
|
183
|
+
type: baseType,
|
|
184
|
+
sourceFile: this.sourceFile,
|
|
185
|
+
sourceLine: line,
|
|
186
|
+
sourceLanguage: ESourceLanguage.C,
|
|
187
|
+
isExported: !isExtern,
|
|
188
|
+
isDeclaration: true,
|
|
189
|
+
});
|
|
190
|
+
} else {
|
|
191
|
+
this.symbols.push({
|
|
192
|
+
name,
|
|
193
|
+
kind: ESymbolKind.Variable,
|
|
194
|
+
type: baseType,
|
|
195
|
+
sourceFile: this.sourceFile,
|
|
196
|
+
sourceLine: line,
|
|
197
|
+
sourceLanguage: ESourceLanguage.C,
|
|
198
|
+
isExported: !isExtern,
|
|
199
|
+
isDeclaration: isExtern,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private collectStructOrUnion(
|
|
206
|
+
structSpec: StructOrUnionSpecifierContext,
|
|
207
|
+
line: number,
|
|
208
|
+
typedefName?: string,
|
|
209
|
+
): void {
|
|
210
|
+
const identifier = structSpec.Identifier();
|
|
211
|
+
|
|
212
|
+
// Use typedef name for anonymous structs (e.g., typedef struct { ... } AppConfig;)
|
|
213
|
+
const name = identifier?.getText() || typedefName;
|
|
214
|
+
if (!name) return; // Skip if no name available
|
|
215
|
+
|
|
216
|
+
const isUnion = structSpec.structOrUnion()?.getText() === "union";
|
|
217
|
+
|
|
218
|
+
this.symbols.push({
|
|
219
|
+
name,
|
|
220
|
+
kind: ESymbolKind.Struct,
|
|
221
|
+
type: isUnion ? "union" : "struct",
|
|
222
|
+
sourceFile: this.sourceFile,
|
|
223
|
+
sourceLine: line,
|
|
224
|
+
sourceLanguage: ESourceLanguage.C,
|
|
225
|
+
isExported: true,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Extract struct field information if SymbolTable is available
|
|
229
|
+
if (this.symbolTable) {
|
|
230
|
+
const declList = structSpec.structDeclarationList();
|
|
231
|
+
if (declList) {
|
|
232
|
+
for (const structDecl of declList.structDeclaration()) {
|
|
233
|
+
this.collectStructFields(name, structDecl);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private collectEnum(enumSpec: EnumSpecifierContext, line: number): void {
|
|
240
|
+
const identifier = enumSpec.Identifier();
|
|
241
|
+
if (!identifier) return;
|
|
242
|
+
|
|
243
|
+
const name = identifier.getText();
|
|
244
|
+
|
|
245
|
+
this.symbols.push({
|
|
246
|
+
name,
|
|
247
|
+
kind: ESymbolKind.Enum,
|
|
248
|
+
sourceFile: this.sourceFile,
|
|
249
|
+
sourceLine: line,
|
|
250
|
+
sourceLanguage: ESourceLanguage.C,
|
|
251
|
+
isExported: true,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Collect enum members
|
|
255
|
+
const enumList = enumSpec.enumeratorList();
|
|
256
|
+
if (enumList) {
|
|
257
|
+
for (const enumeratorDef of enumList.enumerator()) {
|
|
258
|
+
const enumConst = enumeratorDef.enumerationConstant();
|
|
259
|
+
if (enumConst) {
|
|
260
|
+
const memberName = enumConst.Identifier()?.getText();
|
|
261
|
+
if (memberName) {
|
|
262
|
+
this.symbols.push({
|
|
263
|
+
name: memberName,
|
|
264
|
+
kind: ESymbolKind.EnumMember,
|
|
265
|
+
sourceFile: this.sourceFile,
|
|
266
|
+
sourceLine: enumeratorDef.start?.line ?? line,
|
|
267
|
+
sourceLanguage: ESourceLanguage.C,
|
|
268
|
+
isExported: true,
|
|
269
|
+
parent: name,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Collect struct field information
|
|
279
|
+
*/
|
|
280
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
281
|
+
private collectStructFields(structName: string, structDecl: any): void {
|
|
282
|
+
const specQualList = structDecl.specifierQualifierList?.();
|
|
283
|
+
if (!specQualList) return;
|
|
284
|
+
|
|
285
|
+
// Extract the field type from specifierQualifierList
|
|
286
|
+
const fieldType = this.extractTypeFromSpecQualList(specQualList);
|
|
287
|
+
|
|
288
|
+
// Extract field names from structDeclaratorList
|
|
289
|
+
const structDeclList = structDecl.structDeclaratorList?.();
|
|
290
|
+
if (!structDeclList) return;
|
|
291
|
+
|
|
292
|
+
for (const structDeclarator of structDeclList.structDeclarator()) {
|
|
293
|
+
const declarator = structDeclarator.declarator?.();
|
|
294
|
+
if (!declarator) continue;
|
|
295
|
+
|
|
296
|
+
const fieldName = this.extractDeclaratorName(declarator);
|
|
297
|
+
if (!fieldName) continue;
|
|
298
|
+
|
|
299
|
+
// Check if this field is an array and extract dimensions
|
|
300
|
+
const arrayDimensions = this.extractArrayDimensions(declarator);
|
|
301
|
+
|
|
302
|
+
// Add to SymbolTable
|
|
303
|
+
this.symbolTable!.addStructField(
|
|
304
|
+
structName,
|
|
305
|
+
fieldName,
|
|
306
|
+
fieldType,
|
|
307
|
+
arrayDimensions.length > 0 ? arrayDimensions : undefined,
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Extract type from specifierQualifierList (for struct fields)
|
|
314
|
+
*/
|
|
315
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
316
|
+
private extractTypeFromSpecQualList(specQualList: any): string {
|
|
317
|
+
const parts: string[] = [];
|
|
318
|
+
|
|
319
|
+
// Traverse the specifierQualifierList
|
|
320
|
+
let current = specQualList;
|
|
321
|
+
while (current) {
|
|
322
|
+
const typeSpec = current.typeSpecifier?.();
|
|
323
|
+
if (typeSpec) {
|
|
324
|
+
parts.push(typeSpec.getText());
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const typeQual = current.typeQualifier?.();
|
|
328
|
+
if (typeQual) {
|
|
329
|
+
parts.push(typeQual.getText());
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
current = current.specifierQualifierList?.();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return parts.join(" ") || "int";
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Extract array dimensions from a declarator
|
|
340
|
+
*/
|
|
341
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
342
|
+
private extractArrayDimensions(declarator: any): number[] {
|
|
343
|
+
const dimensions: number[] = [];
|
|
344
|
+
|
|
345
|
+
// Navigate to directDeclarator
|
|
346
|
+
const directDecl = declarator.directDeclarator?.();
|
|
347
|
+
if (!directDecl) return dimensions;
|
|
348
|
+
|
|
349
|
+
// Check for array syntax: directDeclarator '[' ... ']'
|
|
350
|
+
// This is a simplified extraction - may need enhancement for complex cases
|
|
351
|
+
const text = directDecl.getText();
|
|
352
|
+
const arrayMatches = text.match(/\[(\d+)\]/g);
|
|
353
|
+
|
|
354
|
+
if (arrayMatches) {
|
|
355
|
+
for (const match of arrayMatches) {
|
|
356
|
+
const size = parseInt(match.slice(1, -1), 10);
|
|
357
|
+
if (!isNaN(size)) {
|
|
358
|
+
dimensions.push(size);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return dimensions;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Helper methods
|
|
367
|
+
|
|
368
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
369
|
+
private extractDeclaratorName(declarator: any): string | null {
|
|
370
|
+
// Direct declarator contains the identifier
|
|
371
|
+
const directDecl = declarator.directDeclarator?.();
|
|
372
|
+
if (!directDecl) return null;
|
|
373
|
+
|
|
374
|
+
// Check for identifier
|
|
375
|
+
const identifier = directDecl.Identifier?.();
|
|
376
|
+
if (identifier) {
|
|
377
|
+
return identifier.getText();
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Nested declarator - recurse
|
|
381
|
+
const nestedDecl = directDecl.declarator?.();
|
|
382
|
+
if (nestedDecl) {
|
|
383
|
+
return this.extractDeclaratorName(nestedDecl);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
390
|
+
private declaratorIsFunction(declarator: any): boolean {
|
|
391
|
+
const directDecl = declarator.directDeclarator?.();
|
|
392
|
+
if (!directDecl) return false;
|
|
393
|
+
|
|
394
|
+
// Check for parameter type list (function)
|
|
395
|
+
return directDecl.parameterTypeList?.() !== null;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
private extractTypeFromDeclSpecs(
|
|
399
|
+
declSpecs: DeclarationSpecifiersContext,
|
|
400
|
+
): string {
|
|
401
|
+
const parts: string[] = [];
|
|
402
|
+
|
|
403
|
+
for (const spec of declSpecs.declarationSpecifier()) {
|
|
404
|
+
const typeSpec = spec.typeSpecifier();
|
|
405
|
+
if (typeSpec) {
|
|
406
|
+
parts.push(typeSpec.getText());
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return parts.join(" ") || "int";
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
private hasStorageClass(
|
|
414
|
+
declSpecs: DeclarationSpecifiersContext,
|
|
415
|
+
storage: string,
|
|
416
|
+
): boolean {
|
|
417
|
+
for (const spec of declSpecs.declarationSpecifier()) {
|
|
418
|
+
const storageSpec = spec.storageClassSpecifier();
|
|
419
|
+
if (storageSpec && storageSpec.getText() === storage) {
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private findStructOrUnionSpecifier(
|
|
427
|
+
declSpecs: DeclarationSpecifiersContext,
|
|
428
|
+
): StructOrUnionSpecifierContext | null {
|
|
429
|
+
for (const spec of declSpecs.declarationSpecifier()) {
|
|
430
|
+
const typeSpec = spec.typeSpecifier();
|
|
431
|
+
if (typeSpec) {
|
|
432
|
+
const structSpec = typeSpec.structOrUnionSpecifier?.();
|
|
433
|
+
if (structSpec) {
|
|
434
|
+
return structSpec;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
private findEnumSpecifier(
|
|
442
|
+
declSpecs: DeclarationSpecifiersContext,
|
|
443
|
+
): EnumSpecifierContext | null {
|
|
444
|
+
for (const spec of declSpecs.declarationSpecifier()) {
|
|
445
|
+
const typeSpec = spec.typeSpecifier();
|
|
446
|
+
if (typeSpec) {
|
|
447
|
+
const enumSpec = typeSpec.enumSpecifier?.();
|
|
448
|
+
if (enumSpec) {
|
|
449
|
+
return enumSpec;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export default CSymbolCollector;
|