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.
Files changed (72) hide show
  1. package/README.md +726 -0
  2. package/bin/cnext.js +5 -0
  3. package/grammar/C.g4 +1112 -0
  4. package/grammar/CNext.g4 +817 -0
  5. package/grammar/CPP14Lexer.g4 +282 -0
  6. package/grammar/CPP14Parser.g4 +1072 -0
  7. package/package.json +85 -0
  8. package/src/analysis/DivisionByZeroAnalyzer.ts +378 -0
  9. package/src/analysis/FunctionCallAnalyzer.ts +526 -0
  10. package/src/analysis/InitializationAnalyzer.ts +725 -0
  11. package/src/analysis/NullCheckAnalyzer.ts +427 -0
  12. package/src/analysis/types/IDivisionByZeroError.ts +25 -0
  13. package/src/analysis/types/IFunctionCallError.ts +17 -0
  14. package/src/analysis/types/IInitializationError.ts +55 -0
  15. package/src/analysis/types/INullCheckError.ts +25 -0
  16. package/src/codegen/CodeGenerator.ts +7945 -0
  17. package/src/codegen/CommentExtractor.ts +240 -0
  18. package/src/codegen/CommentFormatter.ts +155 -0
  19. package/src/codegen/HeaderGenerator.ts +265 -0
  20. package/src/codegen/TypeResolver.ts +365 -0
  21. package/src/codegen/types/ECommentType.ts +10 -0
  22. package/src/codegen/types/IComment.ts +21 -0
  23. package/src/codegen/types/ICommentError.ts +15 -0
  24. package/src/codegen/types/TOverflowBehavior.ts +6 -0
  25. package/src/codegen/types/TParameterInfo.ts +13 -0
  26. package/src/codegen/types/TTypeConstants.ts +94 -0
  27. package/src/codegen/types/TTypeInfo.ts +22 -0
  28. package/src/index.ts +518 -0
  29. package/src/lib/IncludeDiscovery.ts +131 -0
  30. package/src/lib/InputExpansion.ts +121 -0
  31. package/src/lib/PlatformIODetector.ts +162 -0
  32. package/src/lib/transpiler.ts +439 -0
  33. package/src/lib/types/ITranspileResult.ts +80 -0
  34. package/src/parser/c/grammar/C.interp +338 -0
  35. package/src/parser/c/grammar/C.tokens +229 -0
  36. package/src/parser/c/grammar/CLexer.interp +415 -0
  37. package/src/parser/c/grammar/CLexer.tokens +229 -0
  38. package/src/parser/c/grammar/CLexer.ts +750 -0
  39. package/src/parser/c/grammar/CListener.ts +976 -0
  40. package/src/parser/c/grammar/CParser.ts +9663 -0
  41. package/src/parser/c/grammar/CVisitor.ts +626 -0
  42. package/src/parser/cpp/grammar/CPP14Lexer.interp +478 -0
  43. package/src/parser/cpp/grammar/CPP14Lexer.tokens +264 -0
  44. package/src/parser/cpp/grammar/CPP14Lexer.ts +848 -0
  45. package/src/parser/cpp/grammar/CPP14Parser.interp +492 -0
  46. package/src/parser/cpp/grammar/CPP14Parser.tokens +264 -0
  47. package/src/parser/cpp/grammar/CPP14Parser.ts +19961 -0
  48. package/src/parser/cpp/grammar/CPP14ParserListener.ts +2120 -0
  49. package/src/parser/cpp/grammar/CPP14ParserVisitor.ts +1354 -0
  50. package/src/parser/grammar/CNext.interp +340 -0
  51. package/src/parser/grammar/CNext.tokens +214 -0
  52. package/src/parser/grammar/CNextLexer.interp +374 -0
  53. package/src/parser/grammar/CNextLexer.tokens +214 -0
  54. package/src/parser/grammar/CNextLexer.ts +668 -0
  55. package/src/parser/grammar/CNextListener.ts +1020 -0
  56. package/src/parser/grammar/CNextParser.ts +9239 -0
  57. package/src/parser/grammar/CNextVisitor.ts +654 -0
  58. package/src/preprocessor/Preprocessor.ts +301 -0
  59. package/src/preprocessor/ToolchainDetector.ts +225 -0
  60. package/src/preprocessor/types/IPreprocessResult.ts +39 -0
  61. package/src/preprocessor/types/IToolchain.ts +27 -0
  62. package/src/project/FileDiscovery.ts +236 -0
  63. package/src/project/Project.ts +425 -0
  64. package/src/project/types/IProjectConfig.ts +64 -0
  65. package/src/symbols/CNextSymbolCollector.ts +326 -0
  66. package/src/symbols/CSymbolCollector.ts +457 -0
  67. package/src/symbols/CppSymbolCollector.ts +362 -0
  68. package/src/symbols/SymbolTable.ts +312 -0
  69. package/src/symbols/types/IConflict.ts +20 -0
  70. package/src/types/ESourceLanguage.ts +10 -0
  71. package/src/types/ESymbolKind.ts +20 -0
  72. 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;