Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 32x 4x 8x 2x 3x 8x 4x 3x 24x 24x 24x 24x 24x 24x 24x 24x 24x 24x 24x 32x 24x 3x 3x | /**
* Parse C/C++ header source and extract symbols for IDE features
*/
import { CharStream, CommonTokenStream } from "antlr4ng";
import { CLexer } from "../transpiler/logic/parser/c/grammar/CLexer";
import { CParser } from "../transpiler/logic/parser/c/grammar/CParser";
import CSymbolCollector from "../transpiler/logic/symbols/CSymbolCollector";
import ESymbolKind from "../utils/types/ESymbolKind";
import ISymbolInfo from "./types/ISymbolInfo";
import IParseWithSymbolsResult from "./types/IParseWithSymbolsResult";
import TSymbolKind from "./types/TSymbolKind";
/**
* Map ESymbolKind to TSymbolKind for extension use
*/
function mapSymbolKind(kind: ESymbolKind): TSymbolKind {
switch (kind) {
case ESymbolKind.Struct:
return "struct";
case ESymbolKind.Function:
return "function";
case ESymbolKind.Variable:
return "variable";
case ESymbolKind.Enum:
return "enum";
case ESymbolKind.EnumMember:
return "enumMember";
case ESymbolKind.Type:
return "type";
default:
return "variable";
}
}
/**
* Parse C/C++ header source and extract symbols for IDE features
*
* Unlike transpilation, this function attempts to extract symbols even when
* there are parse errors, making it suitable for autocomplete during typing.
*
* @param source - C/C++ header source code string
* @param filePath - Optional file path for symbol source tracking
* @returns Parse result with symbols
*
* @example
* ```typescript
* import parseCHeader from './lib/parseCHeader';
*
* const result = parseCHeader(headerSource, 'config.h');
* // Find all functions defined in the header
* const functions = result.symbols.filter(s => s.kind === 'function');
* ```
*/
function parseCHeader(
source: string,
filePath?: string,
): IParseWithSymbolsResult {
const errors: Array<{
line: number;
column: number;
message: string;
severity: "error" | "warning";
}> = [];
try {
// Parse C source
const charStream = CharStream.fromString(source);
const lexer = new CLexer(charStream);
const tokenStream = new CommonTokenStream(lexer);
const parser = new CParser(tokenStream);
// Suppress error output for headers (they often have incomplete code)
lexer.removeErrorListeners();
parser.removeErrorListeners();
const tree = parser.compilationUnit();
const collector = new CSymbolCollector(filePath ?? "<header>");
const rawSymbols = collector.collect(tree);
// Transform ISymbol[] to ISymbolInfo[]
const symbols: ISymbolInfo[] = rawSymbols.map((sym) => ({
name: sym.name,
fullName: sym.parent ? `${sym.parent}.${sym.name}` : sym.name,
kind: mapSymbolKind(sym.kind),
type: sym.type,
parent: sym.parent,
line: sym.sourceLine ?? 0,
sourceFile: filePath,
language: "c",
}));
return {
success: true,
errors,
symbols,
};
} catch (err) {
errors.push({
line: 1,
column: 0,
message: err instanceof Error ? err.message : String(err),
severity: "error",
});
return {
success: false,
errors,
symbols: [],
};
}
}
export default parseCHeader;
|