First code commit
This commit is contained in:
43
src/elements/Common.ts
Normal file
43
src/elements/Common.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import Parser from 'web-tree-sitter';
|
||||
import { IPosition } from './interfaces/Common';
|
||||
|
||||
/**
|
||||
* Position of a node in the source code.
|
||||
*/
|
||||
export class Position implements IPosition {
|
||||
/**
|
||||
* Convert a tree-sitter node to a position object.
|
||||
* @param node The tree-sitter node to convert.
|
||||
* @returns A position object representing the node.
|
||||
*/
|
||||
static fromNode(node: Parser.SyntaxNode): Position {
|
||||
return new Position(
|
||||
node.startPosition.row,
|
||||
node.endPosition.row,
|
||||
node.startPosition.column,
|
||||
node.endPosition.column,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Position of a node in the source code.
|
||||
* @param startLine Start line number
|
||||
* @param endLine End line number
|
||||
* @param startColumn Start column number
|
||||
* @param endColumn End column number
|
||||
*/
|
||||
constructor(
|
||||
public startLine: number,
|
||||
public endLine: number,
|
||||
public startColumn: number,
|
||||
public endColumn: number,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Convert the position to a string representation.
|
||||
* @returns String representation of the position
|
||||
*/
|
||||
toString(): string {
|
||||
return `(${this.startLine}:${this.startColumn}-${this.endLine}:${this.endColumn})`;
|
||||
}
|
||||
}
|
||||
53
src/elements/HDLElement.ts
Normal file
53
src/elements/HDLElement.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { IPosition } from './interfaces/Common';
|
||||
import { IHDLElement, IHDLElementInfo } from './interfaces/IHDLElement';
|
||||
|
||||
/**
|
||||
* Base implementation for all HDL elements.
|
||||
* @template T - Type of the HDL element info.
|
||||
*/
|
||||
export class HDLElement<T extends IHDLElementInfo> implements IHDLElement<T> {
|
||||
protected _info: T;
|
||||
|
||||
/**
|
||||
* Create a new HDL element.
|
||||
* @param info Metadata about the HDL element
|
||||
*/
|
||||
constructor(info: T) {
|
||||
this._info = info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the HDL element.
|
||||
*/
|
||||
get name(): string {
|
||||
return this._info.name ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the machine-generated description of the HDL element.
|
||||
*/
|
||||
get description(): string | undefined {
|
||||
return this._info.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the code comment associated with the HDL element.
|
||||
*/
|
||||
get comment(): string | undefined {
|
||||
return this._info.comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of the HDL element in the source code.
|
||||
*/
|
||||
get position(): IPosition {
|
||||
return this._info.position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full metadata object.
|
||||
*/
|
||||
get info(): T {
|
||||
return this._info;
|
||||
}
|
||||
}
|
||||
24
src/elements/HDLFunction.ts
Normal file
24
src/elements/HDLFunction.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { HDLElement } from './HDLElement';
|
||||
import { IHDLFunctionInfo, IHDLFunction } from './interfaces/IHDLFunction';
|
||||
|
||||
/**
|
||||
* Function element in VHDL.
|
||||
*/
|
||||
export class HDLFunction
|
||||
extends HDLElement<IHDLFunctionInfo>
|
||||
implements IHDLFunction
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get parameters(): string {
|
||||
return this._info.parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get returnType(): string {
|
||||
return this._info.returnType;
|
||||
}
|
||||
}
|
||||
20
src/elements/HDLInstantiation.ts
Normal file
20
src/elements/HDLInstantiation.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { HDLElement } from './HDLElement';
|
||||
import {
|
||||
IHDLInstantiationInfo,
|
||||
IHDLInstantiation,
|
||||
} from './interfaces/IHDLInstantiation';
|
||||
|
||||
/**
|
||||
* Instantiation element in VHDL.
|
||||
*/
|
||||
export class Instantiation
|
||||
extends HDLElement<IHDLInstantiationInfo>
|
||||
implements IHDLInstantiation
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get instanceType(): string {
|
||||
return this._info.instanceType;
|
||||
}
|
||||
}
|
||||
17
src/elements/HDLProcedure.ts
Normal file
17
src/elements/HDLProcedure.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { HDLElement } from './HDLElement';
|
||||
import { IHDLProcedureInfo, IHDLProcedure } from './interfaces/IHDLProcedure';
|
||||
|
||||
/**
|
||||
* Procedure element in VHDL.
|
||||
*/
|
||||
export class HDLProcedure
|
||||
extends HDLElement<IHDLProcedureInfo>
|
||||
implements IHDLProcedure
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get parameters(): string {
|
||||
return this._info.parameters;
|
||||
}
|
||||
}
|
||||
24
src/elements/HDLProcess.ts
Normal file
24
src/elements/HDLProcess.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { HDLElement } from './HDLElement';
|
||||
import { IHDLProcessInfo, IHDLProcess } from './interfaces/IHDLProcess';
|
||||
|
||||
/**
|
||||
* Process element in VHDL.
|
||||
*/
|
||||
export class HDLProcess
|
||||
extends HDLElement<IHDLProcessInfo>
|
||||
implements IHDLProcess
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get sensitivityList(): string[] | undefined {
|
||||
return this._info.sensitivityList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get processType(): string | undefined {
|
||||
return this._info.processType;
|
||||
}
|
||||
}
|
||||
24
src/elements/HDLSignal.ts
Normal file
24
src/elements/HDLSignal.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { HDLElement } from './HDLElement';
|
||||
import { IHDLSignalInfo, IHDLSignal } from './interfaces/IHDLSignal';
|
||||
|
||||
/**
|
||||
* Signal element in VHDL.
|
||||
*/
|
||||
export class HDLSignal
|
||||
extends HDLElement<IHDLSignalInfo>
|
||||
implements IHDLSignal
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get type(): string {
|
||||
return this._info.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get defaultValue(): string | undefined {
|
||||
return this._info.defaultValue;
|
||||
}
|
||||
}
|
||||
52
src/elements/interfaces/Common.ts
Normal file
52
src/elements/interfaces/Common.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import Parser from 'web-tree-sitter';
|
||||
|
||||
/**
|
||||
* Static interface for position objects.
|
||||
*/
|
||||
export interface IPosition_ {
|
||||
/**
|
||||
* Convert a tree-sitter node to a position object.
|
||||
* @param node The tree-sitter node to convert.
|
||||
* @returns A position object representing the node.
|
||||
*/
|
||||
fromNode(node: Parser.SyntaxNode): IPosition;
|
||||
|
||||
/**
|
||||
* Create a new position object.
|
||||
* @param startLine Start line number
|
||||
* @param endLine End line number
|
||||
* @param startColumn Start column number
|
||||
* @param endColumn End column number
|
||||
*/
|
||||
new (
|
||||
startLine: number,
|
||||
endLine: number,
|
||||
startColumn: number,
|
||||
endColumn: number,
|
||||
): IPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Position of a node in the source code.
|
||||
*/
|
||||
export interface IPosition {
|
||||
/**
|
||||
* The line number of the start of the node.
|
||||
*/
|
||||
startLine: number;
|
||||
|
||||
/**
|
||||
* The line number of the end of the node.
|
||||
*/
|
||||
endLine: number;
|
||||
|
||||
/**
|
||||
* The column number of the start of the node.
|
||||
*/
|
||||
startColumn: number;
|
||||
|
||||
/**
|
||||
* The column number of the end of the node.
|
||||
*/
|
||||
endColumn: number;
|
||||
}
|
||||
14
src/elements/interfaces/HDLElementTagNameMap.ts
Normal file
14
src/elements/interfaces/HDLElementTagNameMap.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface HDLElementTagNameMap {
|
||||
process: 'HDLProcess';
|
||||
type: 'HDLType';
|
||||
signal: 'HDLSignal';
|
||||
variable: 'HDLVariable';
|
||||
constant: 'HDLConstant';
|
||||
attribute: 'HDLAttribute';
|
||||
function: 'HDLFunction';
|
||||
procedure: 'HDLProcedure';
|
||||
instance: 'HDLInstance';
|
||||
generic: 'HDLGeneric';
|
||||
port: 'HDLPort';
|
||||
concurrent: 'HDLConcurrent';
|
||||
}
|
||||
66
src/elements/interfaces/IHDLElement.ts
Normal file
66
src/elements/interfaces/IHDLElement.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { IPosition } from './Common';
|
||||
|
||||
/**
|
||||
* Shared metadata for any HDL element.
|
||||
*/
|
||||
export interface IHDLElementInfo {
|
||||
/**
|
||||
* Name of the HDL element.
|
||||
* e.g. "my_signal", "my_function", "my_process".
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* Machine generated description of the element.
|
||||
*/
|
||||
description?: string;
|
||||
|
||||
/**
|
||||
* Code comment associated with the HDL element.
|
||||
*/
|
||||
comment?: string;
|
||||
|
||||
/**
|
||||
* Position of the HDL element in the source code.
|
||||
*/
|
||||
position: IPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static interface for all HDL elements.
|
||||
* @template T - Type of the HDL element info.
|
||||
*/
|
||||
export interface IHDLElement_<T extends IHDLElementInfo> {
|
||||
new (info: T): IHDLElement<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for all HDL elements.
|
||||
* @template T - Type of the HDL element info.
|
||||
*/
|
||||
export interface IHDLElement<T extends IHDLElementInfo> {
|
||||
/**
|
||||
* Get the name of the HDL element.
|
||||
*/
|
||||
get name(): string;
|
||||
|
||||
/**
|
||||
* Get the machine generated description of the HDL element.
|
||||
*/
|
||||
get description(): string | undefined;
|
||||
|
||||
/**
|
||||
* Get the code comment associated with the HDL element.
|
||||
*/
|
||||
get comment(): string | undefined;
|
||||
|
||||
/**
|
||||
* Get the position of the HDL element in the source code.
|
||||
*/
|
||||
get position(): IPosition;
|
||||
|
||||
/**
|
||||
* Get the full metadata object.
|
||||
*/
|
||||
get info(): T;
|
||||
}
|
||||
31
src/elements/interfaces/IHDLFunction.ts
Normal file
31
src/elements/interfaces/IHDLFunction.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { IHDLElement, IHDLElementInfo } from './IHDLElement';
|
||||
|
||||
/**
|
||||
* Interface for function metadata.
|
||||
*/
|
||||
export interface IHDLFunctionInfo extends IHDLElementInfo {
|
||||
/**
|
||||
* Parameter list as string.
|
||||
*/
|
||||
parameters: string;
|
||||
|
||||
/**
|
||||
* Return type.
|
||||
*/
|
||||
returnType: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for function elements.
|
||||
*/
|
||||
export interface IHDLFunction extends IHDLElement<IHDLFunctionInfo> {
|
||||
/**
|
||||
* Get the parameter list of the function.
|
||||
*/
|
||||
get parameters(): string;
|
||||
|
||||
/**
|
||||
* Get the return type of the function.
|
||||
*/
|
||||
get returnType(): string;
|
||||
}
|
||||
22
src/elements/interfaces/IHDLInstantiation.ts
Normal file
22
src/elements/interfaces/IHDLInstantiation.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { IHDLElement, IHDLElementInfo } from './IHDLElement';
|
||||
|
||||
/**
|
||||
* Interface for component instantiation metadata.
|
||||
*/
|
||||
export interface IHDLInstantiationInfo extends IHDLElementInfo {
|
||||
/**
|
||||
* Type of the instantiated.
|
||||
* e.g. "my_component", "my_package.my_component".
|
||||
*/
|
||||
instanceType: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for instantiation elements.
|
||||
*/
|
||||
export interface IHDLInstantiation extends IHDLElement<IHDLInstantiationInfo> {
|
||||
/**
|
||||
* Get the type of the instantiated element.
|
||||
*/
|
||||
get instanceType(): string;
|
||||
}
|
||||
21
src/elements/interfaces/IHDLProcedure.ts
Normal file
21
src/elements/interfaces/IHDLProcedure.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { IHDLElement, IHDLElementInfo } from './IHDLElement';
|
||||
|
||||
/**
|
||||
* Interface for procedure metadata.
|
||||
*/
|
||||
export interface IHDLProcedureInfo extends IHDLElementInfo {
|
||||
/**
|
||||
* Parameter list as string.
|
||||
*/
|
||||
parameters: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for procedure elements.
|
||||
*/
|
||||
export interface IHDLProcedure extends IHDLElement<IHDLProcedureInfo> {
|
||||
/**
|
||||
* Get the parameter list of the procedure.
|
||||
*/
|
||||
get parameters(): string;
|
||||
}
|
||||
33
src/elements/interfaces/IHDLProcess.ts
Normal file
33
src/elements/interfaces/IHDLProcess.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { IHDLElement, IHDLElementInfo } from './IHDLElement';
|
||||
|
||||
/**
|
||||
* Interface for process metadata.
|
||||
*/
|
||||
export interface IHDLProcessInfo extends IHDLElementInfo {
|
||||
/**
|
||||
* Sensitivity list of the process.
|
||||
*/
|
||||
sensitivityList?: string[];
|
||||
|
||||
/**
|
||||
* Type of process (optional: FSM, combinatorial, etc.).
|
||||
*/
|
||||
processType?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for process elements.
|
||||
*/
|
||||
export interface IHDLProcess extends IHDLElement<IHDLProcessInfo> {
|
||||
/**
|
||||
* Get the sensitivity list of the process.
|
||||
* e.g. "clk", "reset".
|
||||
*/
|
||||
get sensitivityList(): string[] | undefined;
|
||||
|
||||
/**
|
||||
* Get the type of the process.
|
||||
* e.g. "FSM", "combinatorial", etc.
|
||||
*/
|
||||
get processType(): string | undefined;
|
||||
}
|
||||
33
src/elements/interfaces/IHDLSignal.ts
Normal file
33
src/elements/interfaces/IHDLSignal.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { IHDLElement, IHDLElementInfo } from './IHDLElement';
|
||||
|
||||
/**
|
||||
* Interface for signal metadata.
|
||||
*/
|
||||
export interface IHDLSignalInfo extends IHDLElementInfo {
|
||||
/**
|
||||
* Type of the signal.
|
||||
* e.g. "std_logic", "std_logic_vector(7 downto 0)".
|
||||
*/
|
||||
type: string;
|
||||
|
||||
/**
|
||||
* Default value of the signal.
|
||||
*/
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for signal elements.
|
||||
*/
|
||||
export interface IHDLSignal extends IHDLElement<IHDLSignalInfo> {
|
||||
/**
|
||||
* Get the type of the signal.
|
||||
* e.g. "std_logic", "std_logic_vector(7 downto 0)".
|
||||
*/
|
||||
get type(): string;
|
||||
|
||||
/**
|
||||
* Get the default value of the signal.
|
||||
*/
|
||||
get defaultValue(): string | undefined;
|
||||
}
|
||||
102
src/extractors/HDLElementExtractor.ts
Normal file
102
src/extractors/HDLElementExtractor.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import Parser from 'web-tree-sitter';
|
||||
import { ICommentOptions } from './interfaces/ICommentOptions';
|
||||
import {
|
||||
IHDLElement,
|
||||
IHDLElementInfo,
|
||||
} from '../elements/interfaces/IHDLElement';
|
||||
|
||||
/**
|
||||
* Abstract base class for all HDL element extractors.
|
||||
* Collects and provides access to leading comments and implements recursive AST traversal.
|
||||
*/
|
||||
export abstract class HDLElementExtractor<
|
||||
T extends IHDLElement<IHDLElementInfo>,
|
||||
> {
|
||||
protected readonly _comments: Map<number, string> = new Map();
|
||||
|
||||
constructor(
|
||||
protected readonly root: Parser.SyntaxNode,
|
||||
protected readonly commentOptions: ICommentOptions = {
|
||||
markerPrefix: '@',
|
||||
stripPrefix: true,
|
||||
},
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Collect all comments in the file and map them by line number.
|
||||
*/
|
||||
protected extractComments(): void {
|
||||
const stack: Parser.SyntaxNode[] = [this.root];
|
||||
|
||||
while (stack.length > 0) {
|
||||
const node = stack.pop();
|
||||
|
||||
if (!node) continue;
|
||||
|
||||
if (node.type === 'comment') {
|
||||
let comment = node.text.trim().replace(/^--\s*/, '');
|
||||
const prefix = this.commentOptions.markerPrefix;
|
||||
|
||||
if (prefix && !comment.startsWith(prefix)) return;
|
||||
|
||||
if (prefix && this.commentOptions.stripPrefix) {
|
||||
comment = comment.substring(prefix.length);
|
||||
|
||||
if (comment.startsWith(' ')) comment = comment.substring(1);
|
||||
}
|
||||
|
||||
this._comments.set(node.startPosition.row, comment);
|
||||
}
|
||||
|
||||
for (const child of node.namedChildren) {
|
||||
stack.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a contiguous block of comment lines directly above the given line.
|
||||
* Stops at the first non-comment or skipped line.
|
||||
* @param line The line number to check for comments.
|
||||
* @returns The comment block as a string, or undefined if no comments are found.
|
||||
*/
|
||||
protected getLeadingComment(line: number): string | undefined {
|
||||
const lines: string[] = [];
|
||||
let currentLine = line - 1;
|
||||
|
||||
while (this._comments.has(currentLine)) {
|
||||
lines.unshift(this._comments.get(currentLine)!);
|
||||
currentLine--;
|
||||
}
|
||||
|
||||
return lines.length > 0 ? lines.join('\n') : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively find all nodes of a given type in the syntax tree.
|
||||
* @param node The starting node.
|
||||
* @param type The node type to search for.
|
||||
* @returns A flat array of matching nodes.
|
||||
*/
|
||||
protected findNodesByType(
|
||||
node: Parser.SyntaxNode,
|
||||
type: string,
|
||||
): Parser.SyntaxNode[] {
|
||||
const result: Parser.SyntaxNode[] = [];
|
||||
|
||||
if (node.type === type) {
|
||||
result.push(node);
|
||||
}
|
||||
|
||||
for (const child of node.namedChildren) {
|
||||
result.push(...this.findNodesByType(child, type));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main extraction method to be implemented by subclasses.
|
||||
*/
|
||||
abstract extract(): T[];
|
||||
}
|
||||
51
src/extractors/SignalExtractor.ts
Normal file
51
src/extractors/SignalExtractor.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { HDLElementExtractor } from './HDLElementExtractor';
|
||||
import { Position } from '../elements/Common';
|
||||
import { HDLSignal } from '../elements/HDLSignal';
|
||||
import { IHDLSignalInfo } from '../elements/interfaces/IHDLSignal';
|
||||
|
||||
/**
|
||||
* Extractor for VHDL signal declarations.
|
||||
*/
|
||||
export class SignalExtractor extends HDLElementExtractor<HDLSignal> {
|
||||
/**
|
||||
* Extract all signal declarations from the syntax tree.
|
||||
*/
|
||||
extract(): HDLSignal[] {
|
||||
this.extractComments();
|
||||
|
||||
const result: HDLSignal[] = [];
|
||||
|
||||
const signalNodes = this.findNodesByType(
|
||||
this.root,
|
||||
'signal_declaration',
|
||||
);
|
||||
|
||||
for (const node of signalNodes) {
|
||||
const nameNode = node.descendantsOfType('identifier_list')[0];
|
||||
const typeNode = node.descendantsOfType('subtype_indication')[0];
|
||||
const defaultNode = node.descendantsOfType('default_expression')[0];
|
||||
|
||||
const names = nameNode.text.split(',').map((s) => s.trim());
|
||||
const type = typeNode?.text ?? '';
|
||||
const defaultValue = defaultNode?.text ?? undefined;
|
||||
const pos = Position.fromNode(nameNode);
|
||||
|
||||
for (const name of names) {
|
||||
const comment = this.getLeadingComment(pos.startLine);
|
||||
|
||||
const info: IHDLSignalInfo = {
|
||||
name,
|
||||
type,
|
||||
defaultValue,
|
||||
comment,
|
||||
description: undefined,
|
||||
position: pos,
|
||||
};
|
||||
|
||||
result.push(new HDLSignal(info));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
16
src/extractors/interfaces/ICommentOptions.ts
Normal file
16
src/extractors/interfaces/ICommentOptions.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Options for how to treat HDL comments.
|
||||
*/
|
||||
export interface ICommentOptions {
|
||||
/**
|
||||
* Line must start with this prefix (after '--').
|
||||
* Example: '@' to accept '--@ comment'.
|
||||
*/
|
||||
markerPrefix?: string;
|
||||
|
||||
/**
|
||||
* If true, strip the marker prefix and one space (if present).
|
||||
* Example: '--@ Hello' becomes 'Hello'
|
||||
*/
|
||||
stripPrefix?: boolean;
|
||||
}
|
||||
56
src/parser/VHDLParser.ts
Normal file
56
src/parser/VHDLParser.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import Parser from 'web-tree-sitter';
|
||||
import { IParser } from './interfaces/IParser';
|
||||
|
||||
/**
|
||||
* VHDLParser is a class that provides methods to parse VHDL code
|
||||
* using the tree-sitter library.
|
||||
*/
|
||||
export class VHDLParser implements IParser {
|
||||
private _parser!: Parser;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async init(): Promise<void> {
|
||||
await Parser.init();
|
||||
this._parser = new Parser();
|
||||
|
||||
const lang = await Parser.Language.load(
|
||||
join(__dirname, '../vendor/tree-sitter-vhdl.wasm'),
|
||||
);
|
||||
this._parser.setLanguage(lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
parse(code: string): Parser.Tree {
|
||||
return this._parser.parse(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async parseFile(path: string): Promise<Parser.Tree> {
|
||||
const code = readFileSync(path, 'utf-8');
|
||||
|
||||
return this.parse(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async toJson(node: Parser.SyntaxNode): Promise<unknown> {
|
||||
return {
|
||||
type: node.type,
|
||||
text: node.text,
|
||||
startPosition: node.startPosition,
|
||||
endPosition: node.endPosition,
|
||||
children: await Promise.all(
|
||||
node.namedChildren.map((child) => this.toJson(child)),
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
41
src/parser/interfaces/IParser.ts
Normal file
41
src/parser/interfaces/IParser.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import Parser from 'web-tree-sitter';
|
||||
|
||||
/**
|
||||
* Static parser interface
|
||||
*/
|
||||
export interface IParser_ {
|
||||
new (): IParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser interface
|
||||
*/
|
||||
export interface IParser {
|
||||
/**
|
||||
* Initialize the parser and load the language.
|
||||
* @returns A promise that resolves when the parser is initialized.
|
||||
*/
|
||||
init(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Parse a string of code and return the parse tree.
|
||||
* @param code The code to parse
|
||||
* @returns The parsed tree.
|
||||
*/
|
||||
parse(code: string): Parser.Tree;
|
||||
|
||||
/**
|
||||
* Parse a file and return the parse tree.
|
||||
* @param path The path to the file to parse
|
||||
* @returns The parsed tree.
|
||||
*/
|
||||
parseFile(path: string): Promise<Parser.Tree>;
|
||||
|
||||
/**
|
||||
* Convert a tree-sitter node to a JSON object.
|
||||
* This is useful for debugging and visualization purposes.
|
||||
* @param node The tree-sitter node to convert.
|
||||
* @returns A JSON object representing the node.
|
||||
*/
|
||||
toJson(node: Parser.SyntaxNode): Promise<unknown>;
|
||||
}
|
||||
Reference in New Issue
Block a user