qasm-ts 2.1.3 → 2.1.4

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.
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Error classes for QASM parsing and validation
3
+ *
4
+ * This module provides specific error types for different parsing failures,
5
+ * enabling precise error handling and debugging. Each error includes contextual
6
+ * information about where the error occurred in the source code.
7
+ *
8
+ * @module Error Handling
9
+ */
10
+ /** Class representing a bad argument exception. */
11
+ declare class BadArgumentError extends Error {
12
+ constructor(message?: string);
13
+ }
14
+ /** Class representing a bad include statement */
15
+ declare class BadIncludeError extends Error {
16
+ constructor(message?: string);
17
+ }
18
+ /** Class representing a bad quantum register exception. */
19
+ declare class BadQregError extends Error {
20
+ constructor(message?: string);
21
+ }
22
+ /** Class representing a bad equality exception. */
23
+ declare class BadEqualsError extends Error {
24
+ constructor(message?: string);
25
+ }
26
+ /** Class representing a bad classical register exception. */
27
+ declare class BadCregError extends Error {
28
+ constructor(message?: string);
29
+ }
30
+ /** Class representing a bad conditional exception. */
31
+ declare class BadConditionalError extends Error {
32
+ constructor(message?: string);
33
+ }
34
+ /** Class representing a bad barrier exception. */
35
+ declare class BadBarrierError extends Error {
36
+ constructor(message?: string);
37
+ }
38
+ /** Class representing a bad measurement exception. */
39
+ declare class BadMeasurementError extends Error {
40
+ constructor(message?: string);
41
+ }
42
+ /** Class representing a bad gate exception. */
43
+ declare class BadGateError extends Error {
44
+ constructor(message?: string);
45
+ }
46
+ /** Class representing a bad parameter exception. */
47
+ declare class BadParameterError extends Error {
48
+ constructor(message?: string);
49
+ }
50
+ /** Class representing a missing semicolon exception. */
51
+ declare class MissingSemicolonError extends Error {
52
+ constructor(message?: string);
53
+ }
54
+ /** Class representing a missing opening or closing parenthesis, bracket, or curly brakcet. */
55
+ declare class MissingBraceError extends Error {
56
+ constructor(message?: string);
57
+ }
58
+ /** Class representing an unsupported OpenQASM version exception. */
59
+ declare class UnsupportedOpenQASMVersionError extends Error {
60
+ constructor(message?: string);
61
+ }
62
+ /** Class representing an error parsing an expected string literal. */
63
+ declare class BadStringLiteralError extends Error {
64
+ constructor(message?: string);
65
+ }
66
+ /** Class representing an error parsing scalar types. */
67
+ declare class BadClassicalTypeError extends Error {
68
+ constructor(message?: string);
69
+ }
70
+ /** Class representing an error parsing an expression. */
71
+ declare class BadExpressionError extends Error {
72
+ constructor(message?: string);
73
+ }
74
+ /** Class representing an error in defining or calling a custom subroutine. */
75
+ declare class BadSubroutineError extends Error {
76
+ constructor(message?: string);
77
+ }
78
+ /** Class representing a bad loop statement declaration. */
79
+ declare class BadLoopError extends Error {
80
+ constructor(message?: string);
81
+ }
82
+ /** Class representing a bad quantum instruction. */
83
+ declare class BadQuantumInstructionError extends Error {
84
+ constructor(message?: string);
85
+ }
86
+ /** Type for returning an error constructor. */
87
+ type ReturnErrorConstructor = new (message?: string) => Error;
88
+ export { BadArgumentError, BadIncludeError, BadCregError, BadQregError, BadConditionalError, BadBarrierError, BadMeasurementError, BadGateError, BadEqualsError, BadParameterError, MissingSemicolonError, MissingBraceError, UnsupportedOpenQASMVersionError, BadStringLiteralError, BadClassicalTypeError, BadExpressionError, BadSubroutineError, BadLoopError, BadQuantumInstructionError, ReturnErrorConstructor, };
package/dist/errors.js ADDED
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Error classes for QASM parsing and validation
3
+ *
4
+ * This module provides specific error types for different parsing failures,
5
+ * enabling precise error handling and debugging. Each error includes contextual
6
+ * information about where the error occurred in the source code.
7
+ *
8
+ * @module Error Handling
9
+ */
10
+ /** Class representing a bad argument exception. */
11
+ class BadArgumentError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ Object.setPrototypeOf(this, new.target.prototype);
15
+ this.name = BadArgumentError.name;
16
+ }
17
+ }
18
+ /** Class representing a bad include statement */
19
+ class BadIncludeError extends Error {
20
+ constructor(message) {
21
+ super(message);
22
+ Object.setPrototypeOf(this, new.target.prototype);
23
+ this.name = BadIncludeError.name;
24
+ }
25
+ }
26
+ /** Class representing a bad quantum register exception. */
27
+ class BadQregError extends Error {
28
+ constructor(message) {
29
+ super(message);
30
+ Object.setPrototypeOf(this, new.target.prototype);
31
+ this.name = BadQregError.name;
32
+ }
33
+ }
34
+ /** Class representing a bad equality exception. */
35
+ class BadEqualsError extends Error {
36
+ constructor(message) {
37
+ super(message);
38
+ Object.setPrototypeOf(this, new.target.prototype);
39
+ this.name = BadEqualsError.name;
40
+ }
41
+ }
42
+ /** Class representing a bad classical register exception. */
43
+ class BadCregError extends Error {
44
+ constructor(message) {
45
+ super(message);
46
+ Object.setPrototypeOf(this, new.target.prototype);
47
+ this.name = BadCregError.name;
48
+ }
49
+ }
50
+ /** Class representing a bad conditional exception. */
51
+ class BadConditionalError extends Error {
52
+ constructor(message) {
53
+ super(message);
54
+ Object.setPrototypeOf(this, new.target.prototype);
55
+ this.name = BadConditionalError.name;
56
+ }
57
+ }
58
+ /** Class representing a bad barrier exception. */
59
+ class BadBarrierError extends Error {
60
+ constructor(message) {
61
+ super(message);
62
+ Object.setPrototypeOf(this, new.target.prototype);
63
+ this.name = BadBarrierError.name;
64
+ }
65
+ }
66
+ /** Class representing a bad measurement exception. */
67
+ class BadMeasurementError extends Error {
68
+ constructor(message) {
69
+ super(message);
70
+ Object.setPrototypeOf(this, new.target.prototype);
71
+ this.name = BadMeasurementError.name;
72
+ }
73
+ }
74
+ /** Class representing a bad gate exception. */
75
+ class BadGateError extends Error {
76
+ constructor(message) {
77
+ super(message);
78
+ Object.setPrototypeOf(this, new.target.prototype);
79
+ this.name = BadGateError.name;
80
+ }
81
+ }
82
+ /** Class representing a bad parameter exception. */
83
+ class BadParameterError extends Error {
84
+ constructor(message) {
85
+ super(message);
86
+ Object.setPrototypeOf(this, new.target.prototype);
87
+ this.name = BadParameterError.name;
88
+ }
89
+ }
90
+ /** Class representing a missing semicolon exception. */
91
+ class MissingSemicolonError extends Error {
92
+ constructor(message) {
93
+ super(message);
94
+ Object.setPrototypeOf(this, new.target.prototype);
95
+ this.name = MissingSemicolonError.name;
96
+ }
97
+ }
98
+ /** Class representing a missing opening or closing parenthesis, bracket, or curly brakcet. */
99
+ class MissingBraceError extends Error {
100
+ constructor(message) {
101
+ super(message);
102
+ Object.setPrototypeOf(this, new.target.prototype);
103
+ this.name = MissingSemicolonError.name;
104
+ }
105
+ }
106
+ /** Class representing an unsupported OpenQASM version exception. */
107
+ class UnsupportedOpenQASMVersionError extends Error {
108
+ constructor(message) {
109
+ super(message);
110
+ Object.setPrototypeOf(this, new.target.prototype);
111
+ this.name = UnsupportedOpenQASMVersionError.name;
112
+ }
113
+ }
114
+ /** Class representing an error parsing an expected string literal. */
115
+ class BadStringLiteralError extends Error {
116
+ constructor(message) {
117
+ super(message);
118
+ Object.setPrototypeOf(this, new.target.prototype);
119
+ this.name = BadStringLiteralError.name;
120
+ }
121
+ }
122
+ /** Class representing an error parsing scalar types. */
123
+ class BadClassicalTypeError extends Error {
124
+ constructor(message) {
125
+ super(message);
126
+ Object.setPrototypeOf(this, new.target.prototype);
127
+ this.name = BadClassicalTypeError.name;
128
+ }
129
+ }
130
+ /** Class representing an error parsing an expression. */
131
+ class BadExpressionError extends Error {
132
+ constructor(message) {
133
+ super(message);
134
+ Object.setPrototypeOf(this, new.target.prototype);
135
+ this.name = BadExpressionError.name;
136
+ }
137
+ }
138
+ /** Class representing an error in defining or calling a custom subroutine. */
139
+ class BadSubroutineError extends Error {
140
+ constructor(message) {
141
+ super(message);
142
+ Object.setPrototypeOf(this, new.target.prototype);
143
+ this.name = BadSubroutineError.name;
144
+ }
145
+ }
146
+ /** Class representing a bad loop statement declaration. */
147
+ class BadLoopError extends Error {
148
+ constructor(message) {
149
+ super(message);
150
+ Object.setPrototypeOf(this, new.target.prototype);
151
+ this.name = BadLoopError.name;
152
+ }
153
+ }
154
+ /** Class representing a bad quantum instruction. */
155
+ class BadQuantumInstructionError extends Error {
156
+ constructor(message) {
157
+ super(message);
158
+ Object.setPrototypeOf(this, new.target.prototype);
159
+ this.name = BadQuantumInstructionError.name;
160
+ }
161
+ }
162
+ export { BadArgumentError, BadIncludeError, BadCregError, BadQregError, BadConditionalError, BadBarrierError, BadMeasurementError, BadGateError, BadEqualsError, BadParameterError, MissingSemicolonError, MissingBraceError, UnsupportedOpenQASMVersionError, BadStringLiteralError, BadClassicalTypeError, BadExpressionError, BadSubroutineError, BadLoopError, BadQuantumInstructionError, };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Main lexer interface for tokenizing QASM code
3
+ *
4
+ * The lexer is responsible for breaking down QASM source code into tokens
5
+ * that can be consumed by the parser. It supports both OpenQASM 2.0 and 3.0
6
+ * syntax, with version-specific lexers handling the differences in token types
7
+ * and syntax rules.
8
+ *
9
+ * The specific Lexer implementations can be found at:
10
+ * - {@link Qasm3Lexer}
11
+ * - {@link Qasm2Lexer}
12
+ *
13
+ * @module Lexing
14
+ *
15
+ * @example Token Flow
16
+ * ```
17
+ * Source Code → Lexer → Tokens → Parser → AST
18
+ * "h q[0];" → [Id, Id, LSParen, NNInteger, RSParen, Semicolon]
19
+ * ```
20
+ *
21
+ * * @example Basic lexing workflow
22
+ * ```typescript
23
+ * import { lex } from './lexer';
24
+ *
25
+ * const qasmCode = 'OPENQASM 3.0; qubit q; h q;';
26
+ * const tokens = lex(qasmCode);
27
+ * console.log(tokens);
28
+ * // [
29
+ * // [Token.OpenQASM, undefined],
30
+ * // [Token.Id, 'qubit'],
31
+ * // [Token.Id, 'q'],
32
+ * // [Token.Semicolon, undefined],
33
+ * // [Token.Id, 'h'],
34
+ * // [Token.Id, 'q'],
35
+ * // [Token.Semicolon, undefined]
36
+ * // ]
37
+ * ```
38
+ */
39
+ import { Token as Qasm2Token } from "./qasm2/token";
40
+ import { Token as Qasm3Token } from "./qasm3/token";
41
+ import { OpenQASMVersion, OpenQASMMajorVersion } from "./version";
42
+ /**
43
+ * Tokenizes OpenQASM source code into an array of tokens.
44
+ *
45
+ * This is the main entry point for lexical analysis. It automatically selects
46
+ * the appropriate lexer implementation based on the OpenQASM version and returns
47
+ * an array of tokens that can be consumed by the parser.
48
+ *
49
+ * Each token is represented as a tuple containing:
50
+ * - **Token type**: An enum value indicating the kind of token
51
+ * - **Token value**: The associated value (for literals, identifiers, operators)
52
+ *
53
+ * @group Lexing
54
+ * @param qasm - The OpenQASM source code to tokenize
55
+ * @param cursor - Starting position in the input string (defaults to 0)
56
+ * @param version - OpenQASM version to use for lexing (defaults to 3.0)
57
+ * @returns Array of token tuples [TokenType, value?]
58
+ * @throws {UnsupportedOpenQASMVersionError} When an unsupported version is specified
59
+ *
60
+ * @example Tokenize OpenQASM 3.0 code
61
+ * ```typescript
62
+ * const tokens = lex('qubit[2] q; h q[0];', 0, 3);
63
+ * // Returns tokens using OpenQASM 3.0 syntax rules
64
+ * ```
65
+ *
66
+ * @example Tokenize OpenQASM 2.0 code
67
+ * ```typescript
68
+ * const tokens = lex('qreg q[2]; h q[0];', 0, 2);
69
+ * // Returns tokens using OpenQASM 2.0 syntax rules
70
+ * ```
71
+ *
72
+ * @example Resume lexing from specific position
73
+ * ```typescript
74
+ * const code = 'OPENQASM 3.0; qubit q;';
75
+ * const tokens = lex(code, 12); // Start after "OPENQASM 3.0"
76
+ * ```
77
+ */
78
+ export declare function lex(qasm: string, cursor?: number, version?: OpenQASMVersion | OpenQASMMajorVersion | number): Array<[Qasm2Token | Qasm3Token, (number | string)?]>;
package/dist/lexer.js ADDED
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Main lexer interface for tokenizing QASM code
3
+ *
4
+ * The lexer is responsible for breaking down QASM source code into tokens
5
+ * that can be consumed by the parser. It supports both OpenQASM 2.0 and 3.0
6
+ * syntax, with version-specific lexers handling the differences in token types
7
+ * and syntax rules.
8
+ *
9
+ * The specific Lexer implementations can be found at:
10
+ * - {@link Qasm3Lexer}
11
+ * - {@link Qasm2Lexer}
12
+ *
13
+ * @module Lexing
14
+ *
15
+ * @example Token Flow
16
+ * ```
17
+ * Source Code → Lexer → Tokens → Parser → AST
18
+ * "h q[0];" → [Id, Id, LSParen, NNInteger, RSParen, Semicolon]
19
+ * ```
20
+ *
21
+ * * @example Basic lexing workflow
22
+ * ```typescript
23
+ * import { lex } from './lexer';
24
+ *
25
+ * const qasmCode = 'OPENQASM 3.0; qubit q; h q;';
26
+ * const tokens = lex(qasmCode);
27
+ * console.log(tokens);
28
+ * // [
29
+ * // [Token.OpenQASM, undefined],
30
+ * // [Token.Id, 'qubit'],
31
+ * // [Token.Id, 'q'],
32
+ * // [Token.Semicolon, undefined],
33
+ * // [Token.Id, 'h'],
34
+ * // [Token.Id, 'q'],
35
+ * // [Token.Semicolon, undefined]
36
+ * // ]
37
+ * ```
38
+ */
39
+ import { default as Qasm2Lexer } from "./qasm2/lexer";
40
+ import { default as Qasm3Lexer } from "./qasm3/lexer";
41
+ import { OpenQASMVersion, OpenQASMMajorVersion } from "./version";
42
+ import { UnsupportedOpenQASMVersionError } from "./errors";
43
+ /**
44
+ * Tokenizes OpenQASM source code into an array of tokens.
45
+ *
46
+ * This is the main entry point for lexical analysis. It automatically selects
47
+ * the appropriate lexer implementation based on the OpenQASM version and returns
48
+ * an array of tokens that can be consumed by the parser.
49
+ *
50
+ * Each token is represented as a tuple containing:
51
+ * - **Token type**: An enum value indicating the kind of token
52
+ * - **Token value**: The associated value (for literals, identifiers, operators)
53
+ *
54
+ * @group Lexing
55
+ * @param qasm - The OpenQASM source code to tokenize
56
+ * @param cursor - Starting position in the input string (defaults to 0)
57
+ * @param version - OpenQASM version to use for lexing (defaults to 3.0)
58
+ * @returns Array of token tuples [TokenType, value?]
59
+ * @throws {UnsupportedOpenQASMVersionError} When an unsupported version is specified
60
+ *
61
+ * @example Tokenize OpenQASM 3.0 code
62
+ * ```typescript
63
+ * const tokens = lex('qubit[2] q; h q[0];', 0, 3);
64
+ * // Returns tokens using OpenQASM 3.0 syntax rules
65
+ * ```
66
+ *
67
+ * @example Tokenize OpenQASM 2.0 code
68
+ * ```typescript
69
+ * const tokens = lex('qreg q[2]; h q[0];', 0, 2);
70
+ * // Returns tokens using OpenQASM 2.0 syntax rules
71
+ * ```
72
+ *
73
+ * @example Resume lexing from specific position
74
+ * ```typescript
75
+ * const code = 'OPENQASM 3.0; qubit q;';
76
+ * const tokens = lex(code, 12); // Start after "OPENQASM 3.0"
77
+ * ```
78
+ */
79
+ export function lex(qasm, cursor, version) {
80
+ let lexer;
81
+ if (version instanceof OpenQASMVersion) {
82
+ switch (version.major) {
83
+ case OpenQASMMajorVersion.Version2:
84
+ lexer = new Qasm2Lexer(qasm, cursor);
85
+ break;
86
+ case OpenQASMMajorVersion.Version3:
87
+ lexer = new Qasm3Lexer(qasm, cursor);
88
+ break;
89
+ default:
90
+ throw new UnsupportedOpenQASMVersionError(`Unsupported OpenQASM version detected: ${version.major}`);
91
+ }
92
+ }
93
+ else if (typeof version === "number") {
94
+ switch (version) {
95
+ case 2:
96
+ lexer = new Qasm2Lexer(qasm, cursor);
97
+ break;
98
+ case 3:
99
+ lexer = new Qasm3Lexer(qasm, cursor);
100
+ break;
101
+ default:
102
+ throw new UnsupportedOpenQASMVersionError(`Unsupported OpenQASM version detected: ${version}`);
103
+ }
104
+ }
105
+ else if (version === OpenQASMMajorVersion.Version2) {
106
+ lexer = new Qasm2Lexer(qasm, cursor);
107
+ }
108
+ else if (version === OpenQASMMajorVersion.Version3) {
109
+ lexer = new Qasm3Lexer(qasm, cursor);
110
+ }
111
+ else {
112
+ lexer = new Qasm3Lexer(qasm, cursor);
113
+ }
114
+ const tokens = lexer.lex();
115
+ return tokens;
116
+ }
package/dist/main.d.ts ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Main parsing functions for qasm-ts - the primary entry points for parsing OpenQASM code
3
+ * @module Main Functions
4
+ */
5
+ import type * as qasm2 from "./qasm2/ast";
6
+ import type * as qasm3 from "./qasm3/ast";
7
+ import { OpenQASMVersion, OpenQASMMajorVersion } from "./version";
8
+ /**
9
+ * Parses OpenQASM code from a string and returns the abstract syntax tree.
10
+ *
11
+ * This is the primary entry point for parsing OpenQASM code. It handles both
12
+ * OpenQASM 2.0 and 3.0 syntax, automatically selecting the appropriate lexer
13
+ * and parser based on the version parameter.
14
+ *
15
+ * @group Main Functions
16
+ * @param qasm - The OpenQASM code string to parse
17
+ * @param version - The OpenQASM version to use (defaults to 3.0)
18
+ * @param verbose - Whether to include class names in the output (defaults to false)
19
+ * @param stringify - Whether to return stringified JSON (defaults to false)
20
+ * @returns The corresponding AST as an array of nodes, or stringified JSON if stringify is true
21
+ *
22
+ * @example Basic OpenQASM 3.0 parsing
23
+ * ```typescript
24
+ * import { parseString } from 'qasm-ts';
25
+ *
26
+ * const qasmCode = `
27
+ * OPENQASM 3.0;
28
+ * include "stdgates.inc";
29
+ * qubit[2] q;
30
+ * h q[0];
31
+ * cx q[0], q[1];
32
+ * `;
33
+ *
34
+ * const ast = parseString(qasmCode);
35
+ * console.log(ast);
36
+ * ```
37
+ *
38
+ * @example OpenQASM 2.0 parsing
39
+ * ```typescript
40
+ * const qasm2Code = `
41
+ * OPENQASM 2.0;
42
+ * include "qelib1.inc";
43
+ * qreg q[2];
44
+ * creg c[2];
45
+ * h q[0];
46
+ * cx q[0],q[1];
47
+ * measure q -> c;
48
+ * `;
49
+ *
50
+ * const ast = parseString(qasm2Code, 2);
51
+ * ```
52
+ *
53
+ * @example Verbose output with class names
54
+ * ```typescript
55
+ * const ast = parseString(qasmCode, 3, true);
56
+ * // Output will include __className__ properties for each node
57
+ * ```
58
+ */
59
+ export declare function parseString(qasm: string, version?: number | OpenQASMVersion | OpenQASMMajorVersion, verbose?: boolean, stringify?: boolean): string | qasm2.AstNode[] | qasm3.AstNode[];
60
+ /**
61
+ * Parses OpenQASM code from a file and returns the abstract syntax tree.
62
+ *
63
+ * @group Main Functions
64
+ * @param file - The path to the .qasm file to parse
65
+ * @param version - The OpenQASM version to use (defaults to 3.0)
66
+ * @param verbose - Whether to include class names in the output (defaults to false)
67
+ * @param stringify - Whether to return stringified JSON (defaults to false)
68
+ * @returns The corresponding AST as an array of nodes, or stringified JSON if stringify is true
69
+ *
70
+ * @example Parse a QASM file
71
+ * ```typescript
72
+ * import { parseFile } from 'qasm-ts';
73
+ *
74
+ * // Parse OpenQASM 3.0 file
75
+ * const ast = parseFile('./my-circuit.qasm');
76
+ *
77
+ * // Parse OpenQASM 2.0 file
78
+ * const ast2 = parseFile('./legacy-circuit.qasm', 2);
79
+ * ```
80
+ *
81
+ * @example Parse with verbose output
82
+ * ```typescript
83
+ * const ast = parseFile('./circuit.qasm', 3, true);
84
+ * // Includes detailed class information for each AST node
85
+ * ```
86
+ */
87
+ export declare function parseFile(file: string, version?: number | OpenQASMVersion | OpenQASMMajorVersion, verbose?: boolean, stringify?: boolean): string | qasm2.AstNode[] | qasm3.AstNode[];
package/dist/main.js ADDED
@@ -0,0 +1,122 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import * as fs from "fs";
3
+ import { lex } from "./lexer";
4
+ import { parse } from "./parser";
5
+ /**
6
+ * Parses OpenQASM code from a string and returns the abstract syntax tree.
7
+ *
8
+ * This is the primary entry point for parsing OpenQASM code. It handles both
9
+ * OpenQASM 2.0 and 3.0 syntax, automatically selecting the appropriate lexer
10
+ * and parser based on the version parameter.
11
+ *
12
+ * @group Main Functions
13
+ * @param qasm - The OpenQASM code string to parse
14
+ * @param version - The OpenQASM version to use (defaults to 3.0)
15
+ * @param verbose - Whether to include class names in the output (defaults to false)
16
+ * @param stringify - Whether to return stringified JSON (defaults to false)
17
+ * @returns The corresponding AST as an array of nodes, or stringified JSON if stringify is true
18
+ *
19
+ * @example Basic OpenQASM 3.0 parsing
20
+ * ```typescript
21
+ * import { parseString } from 'qasm-ts';
22
+ *
23
+ * const qasmCode = `
24
+ * OPENQASM 3.0;
25
+ * include "stdgates.inc";
26
+ * qubit[2] q;
27
+ * h q[0];
28
+ * cx q[0], q[1];
29
+ * `;
30
+ *
31
+ * const ast = parseString(qasmCode);
32
+ * console.log(ast);
33
+ * ```
34
+ *
35
+ * @example OpenQASM 2.0 parsing
36
+ * ```typescript
37
+ * const qasm2Code = `
38
+ * OPENQASM 2.0;
39
+ * include "qelib1.inc";
40
+ * qreg q[2];
41
+ * creg c[2];
42
+ * h q[0];
43
+ * cx q[0],q[1];
44
+ * measure q -> c;
45
+ * `;
46
+ *
47
+ * const ast = parseString(qasm2Code, 2);
48
+ * ```
49
+ *
50
+ * @example Verbose output with class names
51
+ * ```typescript
52
+ * const ast = parseString(qasmCode, 3, true);
53
+ * // Output will include __className__ properties for each node
54
+ * ```
55
+ */
56
+ export function parseString(qasm, version, verbose, stringify) {
57
+ let ast;
58
+ const tokens = lex(qasm, undefined, version);
59
+ ast = parse(tokens, version);
60
+ if (verbose === true) {
61
+ if (stringify === true) {
62
+ ast = JSON.stringify(getDetailedOutput(ast), null, 2);
63
+ }
64
+ ast = getDetailedOutput(ast);
65
+ }
66
+ else {
67
+ if (stringify === true) {
68
+ ast = JSON.stringify(ast, null, 2);
69
+ }
70
+ }
71
+ return ast;
72
+ }
73
+ /**
74
+ * Parses OpenQASM code from a file and returns the abstract syntax tree.
75
+ *
76
+ * @group Main Functions
77
+ * @param file - The path to the .qasm file to parse
78
+ * @param version - The OpenQASM version to use (defaults to 3.0)
79
+ * @param verbose - Whether to include class names in the output (defaults to false)
80
+ * @param stringify - Whether to return stringified JSON (defaults to false)
81
+ * @returns The corresponding AST as an array of nodes, or stringified JSON if stringify is true
82
+ *
83
+ * @example Parse a QASM file
84
+ * ```typescript
85
+ * import { parseFile } from 'qasm-ts';
86
+ *
87
+ * // Parse OpenQASM 3.0 file
88
+ * const ast = parseFile('./my-circuit.qasm');
89
+ *
90
+ * // Parse OpenQASM 2.0 file
91
+ * const ast2 = parseFile('./legacy-circuit.qasm', 2);
92
+ * ```
93
+ *
94
+ * @example Parse with verbose output
95
+ * ```typescript
96
+ * const ast = parseFile('./circuit.qasm', 3, true);
97
+ * // Includes detailed class information for each AST node
98
+ * ```
99
+ */
100
+ export function parseFile(file, version, verbose, stringify) {
101
+ return parseString(fs.readFileSync(file, "utf8"), version, verbose, stringify);
102
+ }
103
+ /**
104
+ * Adds class names to AST nodes for detailed inspection.
105
+ * @internal
106
+ */
107
+ function getDetailedOutput(object) {
108
+ if (Array.isArray(object)) {
109
+ return object.map(getDetailedOutput);
110
+ }
111
+ else if (object !== null && typeof object === "object") {
112
+ const result = {};
113
+ result["__className__"] = object.constructor.name;
114
+ for (const [key, value] of Object.entries(object)) {
115
+ result[key] = getDetailedOutput(value);
116
+ }
117
+ return result;
118
+ }
119
+ else {
120
+ return object;
121
+ }
122
+ }