qasm-ts 1.1.3 → 2.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/.eslintrc.json +13 -0
- package/.github/workflows/draft-pdf.yml +24 -0
- package/CONTRIBUTING.md +3 -0
- package/LICENSE +201 -0
- package/dist/errors.js +128 -2
- package/dist/lexer.js +110 -291
- package/dist/main.js +123 -18
- package/dist/parser.js +117 -482
- package/dist/{ast.js → qasm2/ast.js} +71 -2
- package/dist/qasm2/lexer.js +489 -0
- package/dist/qasm2/parser.js +659 -0
- package/dist/qasm2/token.js +160 -0
- package/dist/qasm3/ast.js +1081 -0
- package/dist/qasm3/lexer.js +673 -0
- package/dist/qasm3/parser.js +2083 -0
- package/dist/qasm3/token.js +425 -0
- package/dist/version.js +57 -0
- package/docs/assets/hierarchy.js +1 -0
- package/docs/custom.css +3 -0
- package/docs/docs-readme.md +208 -0
- package/docs/index.html +17 -0
- package/docs/typedoc/.nojekyll +1 -0
- package/docs/typedoc/assets/custom.css +3 -0
- package/docs/typedoc/assets/hierarchy.js +1 -0
- package/docs/typedoc/assets/highlight.css +99 -0
- package/docs/typedoc/assets/icons.js +18 -0
- package/docs/typedoc/assets/icons.svg +1 -0
- package/docs/typedoc/assets/main.js +60 -0
- package/docs/typedoc/assets/navigation.js +1 -0
- package/docs/typedoc/assets/search.js +1 -0
- package/docs/typedoc/assets/style.css +1633 -0
- package/docs/typedoc/classes/Error_Handling.BadArgumentError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadBarrierError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadClassicalTypeError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadConditionalError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadCregError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadEqualsError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadExpressionError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadGateError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadIncludeError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadLoopError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadMeasurementError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadParameterError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadQregError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadQuantumInstructionError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadStringLiteralError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadSubroutineError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.MissingBraceError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.MissingSemicolonError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.UnsupportedOpenQASMVersionError.html +12 -0
- package/docs/typedoc/classes/Version_Management.OpenQASMVersion.html +16 -0
- package/docs/typedoc/classes/qasm2_ast.ApplyGate.html +6 -0
- package/docs/typedoc/classes/qasm2_ast.AstNode.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Barrier.html +5 -0
- package/docs/typedoc/classes/qasm2_ast.CReg.html +5 -0
- package/docs/typedoc/classes/qasm2_ast.Cos.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Divide.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Exp.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Gate.html +7 -0
- package/docs/typedoc/classes/qasm2_ast.Id.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.If.html +6 -0
- package/docs/typedoc/classes/qasm2_ast.Include.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.Ln.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Measure.html +7 -0
- package/docs/typedoc/classes/qasm2_ast.Minus.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.NNInteger.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.Opaque.html +6 -0
- package/docs/typedoc/classes/qasm2_ast.Pi.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Plus.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Power.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.QReg.html +5 -0
- package/docs/typedoc/classes/qasm2_ast.Real.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.Sin.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Sqrt.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Tan.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Times.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Variable.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.Version.html +4 -0
- package/docs/typedoc/classes/qasm2_lexer.default.html +57 -0
- package/docs/typedoc/classes/qasm2_parser.default.html +93 -0
- package/docs/typedoc/classes/qasm3_ast.AliasStatement.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.AngleType.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Arithmetic.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.ArrayAccess.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.ArrayDeclaration.html +7 -0
- package/docs/typedoc/classes/qasm3_ast.ArrayInitializer.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.ArrayReference.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.AssignmentStatement.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.AstNode.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.Binary.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.BitType.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.BitstringLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.BoolType.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.BooleanLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.BoxDefinition.html +7 -0
- package/docs/typedoc/classes/qasm3_ast.BranchingStatement.html +8 -0
- package/docs/typedoc/classes/qasm3_ast.BreakStatement.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.CalibrationGrammarDeclaration.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.CaseStatement.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.Cast.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.ClassicalDeclaration.html +7 -0
- package/docs/typedoc/classes/qasm3_ast.ClassicalType.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.ComplexType.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.ContinueStatement.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.DefaultStatement.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.DurationLiteral.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.DurationOf.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.DurationType.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.Euler.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.Expression.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.ExternSignature.html +8 -0
- package/docs/typedoc/classes/qasm3_ast.FloatLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.FloatType.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.ForLoopStatement.html +12 -0
- package/docs/typedoc/classes/qasm3_ast.HardwareQubit.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.IODeclaration.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.Identifier.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.ImaginaryLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Include.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.IndexSet.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.IntType.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.IntegerLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.MathFunction.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.NumericLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Parameters.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Pi.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.ProgramBlock.html +7 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumBarrier.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumBlock.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumDeclaration.html +8 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumDelay.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumGateCall.html +9 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumGateDefinition.html +9 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumGateModifier.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumMeasurement.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumMeasurementAssignment.html +8 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumReset.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Range.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.ReturnStatement.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.SizeOf.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.Statement.html +12 -0
- package/docs/typedoc/classes/qasm3_ast.StretchType.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.SubroutineBlock.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.SubroutineCall.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.SubroutineDefinition.html +10 -0
- package/docs/typedoc/classes/qasm3_ast.SubscriptedIdentifier.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.SwitchStatement.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.Tau.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.TrigFunction.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.UIntType.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Unary.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.Version.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.WhileLoopStatement.html +6 -0
- package/docs/typedoc/classes/qasm3_lexer.default.html +71 -0
- package/docs/typedoc/classes/qasm3_parser.default.html +237 -0
- package/docs/typedoc/enums/Version_Management.OpenQASMMajorVersion.html +4 -0
- package/docs/typedoc/enums/qasm2_token.Token.html +42 -0
- package/docs/typedoc/enums/qasm3_ast.ArithmeticOp.html +9 -0
- package/docs/typedoc/enums/qasm3_ast.ArrayReferenceModifier.html +4 -0
- package/docs/typedoc/enums/qasm3_ast.BinaryOp.html +15 -0
- package/docs/typedoc/enums/qasm3_ast.DurationUnit.html +7 -0
- package/docs/typedoc/enums/qasm3_ast.IOModifier.html +4 -0
- package/docs/typedoc/enums/qasm3_ast.MathFunctionTypes.html +12 -0
- package/docs/typedoc/enums/qasm3_ast.QuantumGateModifierName.html +6 -0
- package/docs/typedoc/enums/qasm3_ast.TrigFunctionTypes.html +8 -0
- package/docs/typedoc/enums/qasm3_ast.UnaryOp.html +5 -0
- package/docs/typedoc/enums/qasm3_token.Token.html +113 -0
- package/docs/typedoc/functions/Lexing.lex.html +24 -0
- package/docs/typedoc/functions/Main_Functions.parseFile.html +13 -0
- package/docs/typedoc/functions/Main_Functions.parseString.html +19 -0
- package/docs/typedoc/functions/Parsing.parse.html +15 -0
- package/docs/typedoc/functions/qasm2_token.inverseLookup.html +3 -0
- package/docs/typedoc/functions/qasm2_token.lookup.html +4 -0
- package/docs/typedoc/functions/qasm2_token.notParam.html +3 -0
- package/docs/typedoc/functions/qasm3_token.inverseLookup.html +9 -0
- package/docs/typedoc/functions/qasm3_token.lookup.html +10 -0
- package/docs/typedoc/functions/qasm3_token.notParam.html +11 -0
- package/docs/typedoc/hierarchy.html +1 -0
- package/docs/typedoc/index.html +76 -0
- package/docs/typedoc/modules/Error_Handling.html +5 -0
- package/docs/typedoc/modules/Lexing.html +20 -0
- package/docs/typedoc/modules/Main_Functions.html +2 -0
- package/docs/typedoc/modules/Parsing.html +24 -0
- package/docs/typedoc/modules/Version_Management.html +8 -0
- package/docs/typedoc/modules/qasm2_ast.html +22 -0
- package/docs/typedoc/modules/qasm2_lexer.html +24 -0
- package/docs/typedoc/modules/qasm2_parser.html +21 -0
- package/docs/typedoc/modules/qasm2_token.html +15 -0
- package/docs/typedoc/modules/qasm3_ast.html +26 -0
- package/docs/typedoc/modules/qasm3_lexer.html +25 -0
- package/docs/typedoc/modules/qasm3_parser.html +25 -0
- package/docs/typedoc/modules/qasm3_token.html +15 -0
- package/docs/typedoc/modules.html +1 -0
- package/docs/typedoc/types/Error_Handling.ReturnErrorConstructor.html +2 -0
- package/docs/typedoc.json +47 -0
- package/package.json +10 -5
- package/paper/jats/paper.jats +464 -0
- package/paper/main.bib +191 -0
- package/paper/paper.md +166 -0
- package/paper/paper.pdf +0 -0
- package/readme.md +117 -47
- package/dist/example.js +0 -22
- package/dist/token.js +0 -89
package/dist/lexer.js
CHANGED
|
@@ -1,300 +1,119 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
exports.__esModule = true;
|
|
3
|
-
var token_1 = require("./token");
|
|
4
|
-
var errors_1 = require("./errors");
|
|
5
2
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
3
|
+
* Main lexer interface for tokenizing QASM code
|
|
4
|
+
*
|
|
5
|
+
* The lexer is responsible for breaking down QASM source code into tokens
|
|
6
|
+
* that can be consumed by the parser. It supports both OpenQASM 2.0 and 3.0
|
|
7
|
+
* syntax, with version-specific lexers handling the differences in token types
|
|
8
|
+
* and syntax rules.
|
|
9
|
+
*
|
|
10
|
+
* The specific Lexer implementations can be found at:
|
|
11
|
+
* - {@link Qasm3Lexer}
|
|
12
|
+
* - {@link Qasm2Lexer}
|
|
13
|
+
*
|
|
14
|
+
* @module Lexing
|
|
15
|
+
*
|
|
16
|
+
* @example Token Flow
|
|
17
|
+
* ```
|
|
18
|
+
* Source Code → Lexer → Tokens → Parser → AST
|
|
19
|
+
* "h q[0];" → [Id, Id, LSParen, NNInteger, RSParen, Semicolon]
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* * @example Basic lexing workflow
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { lex } from './lexer';
|
|
25
|
+
*
|
|
26
|
+
* const qasmCode = 'OPENQASM 3.0; qubit q; h q;';
|
|
27
|
+
* const tokens = lex(qasmCode);
|
|
28
|
+
* console.log(tokens);
|
|
29
|
+
* // [
|
|
30
|
+
* // [Token.OpenQASM, undefined],
|
|
31
|
+
* // [Token.Id, 'qubit'],
|
|
32
|
+
* // [Token.Id, 'q'],
|
|
33
|
+
* // [Token.Semicolon, undefined],
|
|
34
|
+
* // [Token.Id, 'h'],
|
|
35
|
+
* // [Token.Id, 'q'],
|
|
36
|
+
* // [Token.Semicolon, undefined]
|
|
37
|
+
* // ]
|
|
38
|
+
* ```
|
|
9
39
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.lex = lex;
|
|
42
|
+
var lexer_1 = require("./qasm2/lexer");
|
|
43
|
+
var lexer_2 = require("./qasm3/lexer");
|
|
44
|
+
var version_1 = require("./version");
|
|
45
|
+
var errors_1 = require("./errors");
|
|
13
46
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
47
|
+
* Tokenizes OpenQASM source code into an array of tokens.
|
|
48
|
+
*
|
|
49
|
+
* This is the main entry point for lexical analysis. It automatically selects
|
|
50
|
+
* the appropriate lexer implementation based on the OpenQASM version and returns
|
|
51
|
+
* an array of tokens that can be consumed by the parser.
|
|
52
|
+
*
|
|
53
|
+
* Each token is represented as a tuple containing:
|
|
54
|
+
* - **Token type**: An enum value indicating the kind of token
|
|
55
|
+
* - **Token value**: The associated value (for literals, identifiers, operators)
|
|
56
|
+
*
|
|
57
|
+
* @group Lexing
|
|
58
|
+
* @param qasm - The OpenQASM source code to tokenize
|
|
59
|
+
* @param cursor - Starting position in the input string (defaults to 0)
|
|
60
|
+
* @param version - OpenQASM version to use for lexing (defaults to 3.0)
|
|
61
|
+
* @returns Array of token tuples [TokenType, value?]
|
|
62
|
+
* @throws {UnsupportedOpenQASMVersionError} When an unsupported version is specified
|
|
63
|
+
*
|
|
64
|
+
* @example Tokenize OpenQASM 3.0 code
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const tokens = lex('qubit[2] q; h q[0];', 0, 3);
|
|
67
|
+
* // Returns tokens using OpenQASM 3.0 syntax rules
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @example Tokenize OpenQASM 2.0 code
|
|
71
|
+
* ```typescript
|
|
72
|
+
* const tokens = lex('qreg q[2]; h q[0];', 0, 2);
|
|
73
|
+
* // Returns tokens using OpenQASM 2.0 syntax rules
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example Resume lexing from specific position
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const code = 'OPENQASM 3.0; qubit q;';
|
|
79
|
+
* const tokens = lex(code, 12); // Start after "OPENQASM 3.0"
|
|
80
|
+
* ```
|
|
17
81
|
*/
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
82
|
+
function lex(qasm, cursor, version) {
|
|
83
|
+
var lexer;
|
|
84
|
+
if (version instanceof version_1.OpenQASMVersion) {
|
|
85
|
+
switch (version.major) {
|
|
86
|
+
case version_1.OpenQASMMajorVersion.Version2:
|
|
87
|
+
lexer = new lexer_1.default(qasm, cursor);
|
|
88
|
+
break;
|
|
89
|
+
case version_1.OpenQASMMajorVersion.Version3:
|
|
90
|
+
lexer = new lexer_2.default(qasm, cursor);
|
|
91
|
+
break;
|
|
92
|
+
default:
|
|
93
|
+
throw new errors_1.UnsupportedOpenQASMVersionError("Unsupported OpenQASM version detected: ".concat(version.major));
|
|
94
|
+
}
|
|
21
95
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
96
|
+
else if (typeof version === "number") {
|
|
97
|
+
switch (version) {
|
|
98
|
+
case 2:
|
|
99
|
+
lexer = new lexer_1.default(qasm, cursor);
|
|
100
|
+
break;
|
|
101
|
+
case 3:
|
|
102
|
+
lexer = new lexer_2.default(qasm, cursor);
|
|
103
|
+
break;
|
|
104
|
+
default:
|
|
105
|
+
throw new errors_1.UnsupportedOpenQASMVersionError("Unsupported OpenQASM version detected: ".concat(version));
|
|
106
|
+
}
|
|
32
107
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Returns whether a given character is a newline character.
|
|
37
|
-
* @param c - The character.
|
|
38
|
-
* @return Whether the character is a newline.
|
|
39
|
-
*/
|
|
40
|
-
function isNewline(c) {
|
|
41
|
-
if (c.match(/\n|\r(?!\n)|\u2028|\u2029|\r\n/g)) {
|
|
42
|
-
return true;
|
|
108
|
+
else if (version === version_1.OpenQASMMajorVersion.Version2) {
|
|
109
|
+
lexer = new lexer_1.default(qasm, cursor);
|
|
43
110
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* Creates a lexer.
|
|
50
|
-
* @param input - The string to lex.
|
|
51
|
-
* @param cursor - The starting cursor position.
|
|
52
|
-
*/
|
|
53
|
-
function Lexer(input, cursor) {
|
|
54
|
-
var _this = this;
|
|
55
|
-
if (cursor === void 0) { cursor = 0; }
|
|
56
|
-
this.verifyInput = function () {
|
|
57
|
-
var lines = _this.input.split(/\n|\r(?!\n)|\u2028|\u2029|\r\n/g);
|
|
58
|
-
for (var i = 0; i < lines.length; i++) {
|
|
59
|
-
if (!lines[i].startsWith('//')
|
|
60
|
-
&& !(lines[i].length == 0)
|
|
61
|
-
&& !(lines[i].includes('gate'))
|
|
62
|
-
&& !(lines[i].trim() == '{' || lines[i].trim() == '}')
|
|
63
|
-
&& !lines[i].includes(';')) {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return true;
|
|
68
|
-
};
|
|
69
|
-
/**
|
|
70
|
-
* Calling this method lexes the code represented by the provided string.
|
|
71
|
-
* @return An array of tokens and their corresponding values.
|
|
72
|
-
*/
|
|
73
|
-
this.lex = function () {
|
|
74
|
-
var tokens = [];
|
|
75
|
-
var token;
|
|
76
|
-
if (!_this.verifyInput()) {
|
|
77
|
-
throw errors_1.MissingSemicolonError;
|
|
78
|
-
}
|
|
79
|
-
while (_this.cursor < _this.input.length) {
|
|
80
|
-
token = _this.nextToken();
|
|
81
|
-
if (token) {
|
|
82
|
-
tokens.push(token);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return tokens;
|
|
86
|
-
};
|
|
87
|
-
/**
|
|
88
|
-
* Reads a character and advances the cursor.
|
|
89
|
-
* @param num - Optional cursor position modifier.
|
|
90
|
-
*/
|
|
91
|
-
this.readChar = function (num) {
|
|
92
|
-
if (num === void 0) { num = 1; }
|
|
93
|
-
_this.cursor += num;
|
|
94
|
-
return _this.input[_this.cursor - num];
|
|
95
|
-
};
|
|
96
|
-
/**
|
|
97
|
-
* Advances the cusor past the next comment.
|
|
98
|
-
*/
|
|
99
|
-
this.skipComment = function () {
|
|
100
|
-
var char = '';
|
|
101
|
-
while (!isNewline(char)) {
|
|
102
|
-
char = _this.readChar();
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
|
-
* Determines whether the next character to process equals a given character.
|
|
107
|
-
* @param c - The given character.
|
|
108
|
-
* @return Whether the next character equals the given character.
|
|
109
|
-
*/
|
|
110
|
-
this.peekEq = function (c) { return (_this.peek() == c); };
|
|
111
|
-
/**
|
|
112
|
-
* Reads a character without advancing the cursor.
|
|
113
|
-
* @param index - Optional peek position offset.
|
|
114
|
-
*/
|
|
115
|
-
this.peek = function () { return _this.input[_this.cursor]; };
|
|
116
|
-
/**
|
|
117
|
-
* Reads a numeric value.
|
|
118
|
-
* @return The numeric value as a string.
|
|
119
|
-
*/
|
|
120
|
-
this.readNumeric = function () {
|
|
121
|
-
var num = '';
|
|
122
|
-
while (isNumeric(_this.peek())) {
|
|
123
|
-
num += _this.readChar();
|
|
124
|
-
}
|
|
125
|
-
return num;
|
|
126
|
-
};
|
|
127
|
-
/**
|
|
128
|
-
* Reads an identifier.
|
|
129
|
-
* @return The identifier as a string.
|
|
130
|
-
*/
|
|
131
|
-
this.readIdentifier = function () {
|
|
132
|
-
var id = '';
|
|
133
|
-
while (isAlpha(_this.peek())) {
|
|
134
|
-
id += _this.readChar();
|
|
135
|
-
}
|
|
136
|
-
return id;
|
|
137
|
-
};
|
|
138
|
-
/**
|
|
139
|
-
* Reads a string literal.
|
|
140
|
-
* @param terminator - The literal's termination character.
|
|
141
|
-
* @return The literal as a string.
|
|
142
|
-
*/
|
|
143
|
-
this.readStringLiteral = function (terminator) {
|
|
144
|
-
var lit = '';
|
|
145
|
-
var char = '';
|
|
146
|
-
while (!(terminator == char)) {
|
|
147
|
-
char = _this.readChar();
|
|
148
|
-
lit += char;
|
|
149
|
-
}
|
|
150
|
-
return lit;
|
|
151
|
-
};
|
|
152
|
-
/**
|
|
153
|
-
* Advances the cusor past the next block of whitespace.
|
|
154
|
-
*/
|
|
155
|
-
this.skipWhitespace = function () {
|
|
156
|
-
while (' \t\n\r\v'.indexOf(_this.peek()) > -1) {
|
|
157
|
-
_this.cursor += 1;
|
|
158
|
-
}
|
|
159
|
-
return null;
|
|
160
|
-
};
|
|
161
|
-
/**
|
|
162
|
-
* Lexes the next token.
|
|
163
|
-
* @return The next token and its corresponding value.
|
|
164
|
-
*/
|
|
165
|
-
this.nextToken = function () {
|
|
166
|
-
_this.skipWhitespace();
|
|
167
|
-
if (_this.cursor == _this.input.length) {
|
|
168
|
-
return [token_1.Token.EndOfFile];
|
|
169
|
-
}
|
|
170
|
-
var char = _this.peek();
|
|
171
|
-
_this.readChar();
|
|
172
|
-
switch (char) {
|
|
173
|
-
case '=':
|
|
174
|
-
if (_this.peekEq('=')) {
|
|
175
|
-
_this.readChar();
|
|
176
|
-
return [token_1.Token.Equals];
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
throw errors_1.BadEqualsError;
|
|
180
|
-
}
|
|
181
|
-
case '-':
|
|
182
|
-
if (_this.peekEq('>')) {
|
|
183
|
-
_this.readChar();
|
|
184
|
-
return [token_1.Token.Arrow];
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
return [token_1.Token.Minus];
|
|
188
|
-
}
|
|
189
|
-
case '+':
|
|
190
|
-
return [token_1.Token.Plus];
|
|
191
|
-
case '*':
|
|
192
|
-
return [token_1.Token.Times];
|
|
193
|
-
case '^':
|
|
194
|
-
return [token_1.Token.Power];
|
|
195
|
-
case ';':
|
|
196
|
-
return [token_1.Token.Semicolon];
|
|
197
|
-
case ',':
|
|
198
|
-
return [token_1.Token.Comma];
|
|
199
|
-
case '(':
|
|
200
|
-
return [token_1.Token.LParen];
|
|
201
|
-
case '[':
|
|
202
|
-
return [token_1.Token.LSParen];
|
|
203
|
-
case '{':
|
|
204
|
-
return [token_1.Token.LCParen];
|
|
205
|
-
case ')':
|
|
206
|
-
return [token_1.Token.RParen];
|
|
207
|
-
case ']':
|
|
208
|
-
return [token_1.Token.RSParen];
|
|
209
|
-
case '}':
|
|
210
|
-
return [token_1.Token.RCParen];
|
|
211
|
-
case '/':
|
|
212
|
-
if (_this.peekEq('/')) {
|
|
213
|
-
_this.skipComment();
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
return [token_1.Token.Divide];
|
|
218
|
-
}
|
|
219
|
-
case 'g':
|
|
220
|
-
if ((_this.input[_this.cursor] == 'a')
|
|
221
|
-
&& (_this.input[_this.cursor + 1] == 't')
|
|
222
|
-
&& (_this.input[_this.cursor + 2] == 'e')) {
|
|
223
|
-
_this.readChar(3);
|
|
224
|
-
return [token_1.Token.Gate];
|
|
225
|
-
}
|
|
226
|
-
var literal = char + _this.readIdentifier();
|
|
227
|
-
return [token_1.lookup(literal), new String(literal)];
|
|
228
|
-
case 'q':
|
|
229
|
-
if ((_this.input[_this.cursor] == 'r')
|
|
230
|
-
&& (_this.input[_this.cursor + 1] == 'e')
|
|
231
|
-
&& (_this.input[_this.cursor + 2] == 'g')) {
|
|
232
|
-
_this.readChar(3);
|
|
233
|
-
return [token_1.Token.QReg];
|
|
234
|
-
}
|
|
235
|
-
var qregLit = char + _this.readIdentifier();
|
|
236
|
-
return [token_1.lookup(qregLit), new String(qregLit)];
|
|
237
|
-
case 'c':
|
|
238
|
-
if ((_this.input[_this.cursor] == 'r')
|
|
239
|
-
&& (_this.input[_this.cursor + 1] == 'e')
|
|
240
|
-
&& (_this.input[_this.cursor + 2] == 'g')) {
|
|
241
|
-
_this.readChar(3);
|
|
242
|
-
return [token_1.Token.QReg];
|
|
243
|
-
}
|
|
244
|
-
var cregLit = char + _this.readIdentifier();
|
|
245
|
-
return [token_1.lookup(cregLit), new String(cregLit)];
|
|
246
|
-
case 'b':
|
|
247
|
-
if ((_this.input[_this.cursor] == 'a')
|
|
248
|
-
&& (_this.input[_this.cursor + 1] == 'r')
|
|
249
|
-
&& (_this.input[_this.cursor + 2] == 'r')
|
|
250
|
-
&& (_this.input[_this.cursor + 3] == 'i')
|
|
251
|
-
&& (_this.input[_this.cursor + 4] == 'e')
|
|
252
|
-
&& (_this.input[_this.cursor + 5] == 'r')) {
|
|
253
|
-
_this.readChar(6);
|
|
254
|
-
return [token_1.Token.Barrier];
|
|
255
|
-
}
|
|
256
|
-
var barLit = char + _this.readIdentifier();
|
|
257
|
-
return [token_1.lookup(barLit), new String(barLit)];
|
|
258
|
-
case 'm':
|
|
259
|
-
if ((_this.input[_this.cursor] == 'e')
|
|
260
|
-
&& (_this.input[_this.cursor + 1] == 'a')
|
|
261
|
-
&& (_this.input[_this.cursor + 2] == 's')
|
|
262
|
-
&& (_this.input[_this.cursor + 3] == 'u')
|
|
263
|
-
&& (_this.input[_this.cursor + 4] == 'r')
|
|
264
|
-
&& (_this.input[_this.cursor + 5] == 'e')) {
|
|
265
|
-
_this.readChar(6);
|
|
266
|
-
return [token_1.Token.Measure];
|
|
267
|
-
}
|
|
268
|
-
var measureLit = char + _this.readIdentifier();
|
|
269
|
-
return [token_1.lookup(measureLit), new String(measureLit)];
|
|
270
|
-
case '\"':
|
|
271
|
-
var stringLiteral = char + _this.readStringLiteral('\"');
|
|
272
|
-
return [token_1.Token.String, new String(stringLiteral)];
|
|
273
|
-
case '\’':
|
|
274
|
-
var singleStringLiteral = char + _this.readStringLiteral('\’');
|
|
275
|
-
return [token_1.Token.String, new String(singleStringLiteral)];
|
|
276
|
-
default:
|
|
277
|
-
if (isLetter(char)) {
|
|
278
|
-
var literal_1 = char + _this.readIdentifier();
|
|
279
|
-
return [token_1.lookup(literal_1), new String(literal_1)];
|
|
280
|
-
}
|
|
281
|
-
else if (isNumeric(char)) {
|
|
282
|
-
var num = char + _this.readNumeric();
|
|
283
|
-
if (num.indexOf('.') != -1) {
|
|
284
|
-
return [token_1.Token.Real, parseFloat(num)];
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
return [token_1.Token.NNInteger, parseFloat(num)];
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
return [token_1.Token.Illegal];
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
this.input = input;
|
|
296
|
-
this.cursor = cursor;
|
|
111
|
+
else if (version === version_1.OpenQASMMajorVersion.Version3) {
|
|
112
|
+
lexer = new lexer_2.default(qasm, cursor);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
lexer = new lexer_2.default(qasm, cursor);
|
|
297
116
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
117
|
+
var tokens = lexer.lex();
|
|
118
|
+
return tokens;
|
|
119
|
+
}
|
package/dist/main.js
CHANGED
|
@@ -1,26 +1,131 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.parseString = parseString;
|
|
5
|
+
exports.parseFile = parseFile;
|
|
6
|
+
/**
|
|
7
|
+
* Main parsing functions for qasm-ts - the primary entry points for parsing OpenQASM code
|
|
8
|
+
* @module Main Functions
|
|
9
|
+
*/
|
|
5
10
|
var fs = require("fs");
|
|
11
|
+
var lexer_1 = require("./lexer");
|
|
12
|
+
var parser_1 = require("./parser");
|
|
6
13
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
14
|
+
* Parses OpenQASM code from a string and returns the abstract syntax tree.
|
|
15
|
+
*
|
|
16
|
+
* This is the primary entry point for parsing OpenQASM code. It handles both
|
|
17
|
+
* OpenQASM 2.0 and 3.0 syntax, automatically selecting the appropriate lexer
|
|
18
|
+
* and parser based on the version parameter.
|
|
19
|
+
*
|
|
20
|
+
* @group Main Functions
|
|
21
|
+
* @param qasm - The OpenQASM code string to parse
|
|
22
|
+
* @param version - The OpenQASM version to use (defaults to 3.0)
|
|
23
|
+
* @param verbose - Whether to include class names in the output (defaults to false)
|
|
24
|
+
* @param stringify - Whether to return stringified JSON (defaults to false)
|
|
25
|
+
* @returns The corresponding AST as an array of nodes, or stringified JSON if stringify is true
|
|
26
|
+
*
|
|
27
|
+
* @example Basic OpenQASM 3.0 parsing
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { parseString } from 'qasm-ts';
|
|
30
|
+
*
|
|
31
|
+
* const qasmCode = `
|
|
32
|
+
* OPENQASM 3.0;
|
|
33
|
+
* include "stdgates.inc";
|
|
34
|
+
* qubit[2] q;
|
|
35
|
+
* h q[0];
|
|
36
|
+
* cx q[0], q[1];
|
|
37
|
+
* `;
|
|
38
|
+
*
|
|
39
|
+
* const ast = parseString(qasmCode);
|
|
40
|
+
* console.log(ast);
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example OpenQASM 2.0 parsing
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const qasm2Code = `
|
|
46
|
+
* OPENQASM 2.0;
|
|
47
|
+
* include "qelib1.inc";
|
|
48
|
+
* qreg q[2];
|
|
49
|
+
* creg c[2];
|
|
50
|
+
* h q[0];
|
|
51
|
+
* cx q[0],q[1];
|
|
52
|
+
* measure q -> c;
|
|
53
|
+
* `;
|
|
54
|
+
*
|
|
55
|
+
* const ast = parseString(qasm2Code, 2);
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @example Verbose output with class names
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const ast = parseString(qasmCode, 3, true);
|
|
61
|
+
* // Output will include __className__ properties for each node
|
|
62
|
+
* ```
|
|
10
63
|
*/
|
|
11
|
-
function parseString(qasm) {
|
|
12
|
-
var
|
|
13
|
-
var tokens =
|
|
14
|
-
|
|
15
|
-
|
|
64
|
+
function parseString(qasm, version, verbose, stringify) {
|
|
65
|
+
var ast;
|
|
66
|
+
var tokens = (0, lexer_1.lex)(qasm, undefined, version);
|
|
67
|
+
ast = (0, parser_1.parse)(tokens, version);
|
|
68
|
+
if (verbose === true) {
|
|
69
|
+
if (stringify === true) {
|
|
70
|
+
ast = JSON.stringify(getDetailedOutput(ast), null, 2);
|
|
71
|
+
}
|
|
72
|
+
ast = getDetailedOutput(ast);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
if (stringify === true) {
|
|
76
|
+
ast = JSON.stringify(ast, null, 2);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
16
79
|
return ast;
|
|
17
80
|
}
|
|
18
81
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* @
|
|
82
|
+
* Parses OpenQASM code from a file and returns the abstract syntax tree.
|
|
83
|
+
*
|
|
84
|
+
* @group Main Functions
|
|
85
|
+
* @param file - The path to the .qasm file to parse
|
|
86
|
+
* @param version - The OpenQASM version to use (defaults to 3.0)
|
|
87
|
+
* @param verbose - Whether to include class names in the output (defaults to false)
|
|
88
|
+
* @param stringify - Whether to return stringified JSON (defaults to false)
|
|
89
|
+
* @returns The corresponding AST as an array of nodes, or stringified JSON if stringify is true
|
|
90
|
+
*
|
|
91
|
+
* @example Parse a QASM file
|
|
92
|
+
* ```typescript
|
|
93
|
+
* import { parseFile } from 'qasm-ts';
|
|
94
|
+
*
|
|
95
|
+
* // Parse OpenQASM 3.0 file
|
|
96
|
+
* const ast = parseFile('./my-circuit.qasm');
|
|
97
|
+
*
|
|
98
|
+
* // Parse OpenQASM 2.0 file
|
|
99
|
+
* const ast2 = parseFile('./legacy-circuit.qasm', 2);
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @example Parse with verbose output
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const ast = parseFile('./circuit.qasm', 3, true);
|
|
105
|
+
* // Includes detailed class information for each AST node
|
|
106
|
+
* ```
|
|
22
107
|
*/
|
|
23
|
-
|
|
24
|
-
return parseString(fs.readFileSync(file,
|
|
25
|
-
}
|
|
26
|
-
|
|
108
|
+
function parseFile(file, version, verbose, stringify) {
|
|
109
|
+
return parseString(fs.readFileSync(file, "utf8"), version, verbose, stringify);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Adds class names to AST nodes for detailed inspection.
|
|
113
|
+
* @internal
|
|
114
|
+
*/
|
|
115
|
+
function getDetailedOutput(object) {
|
|
116
|
+
if (Array.isArray(object)) {
|
|
117
|
+
return object.map(getDetailedOutput);
|
|
118
|
+
}
|
|
119
|
+
else if (object !== null && typeof object === "object") {
|
|
120
|
+
var result = {};
|
|
121
|
+
result["__className__"] = object.constructor.name;
|
|
122
|
+
for (var _i = 0, _a = Object.entries(object); _i < _a.length; _i++) {
|
|
123
|
+
var _b = _a[_i], key = _b[0], value = _b[1];
|
|
124
|
+
result[key] = getDetailedOutput(value);
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
return object;
|
|
130
|
+
}
|
|
131
|
+
}
|