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/parser.js
CHANGED
|
@@ -1,489 +1,124 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Main parser interface for generating AST from tokens
|
|
4
|
+
*
|
|
5
|
+
* The parser is responsible for transforming a stream of tokens into an Abstract
|
|
6
|
+
* Syntax Tree (AST) that represents the structure of the OpenQASM program. It acts
|
|
7
|
+
* as a dispatcher, selecting the appropriate version-specific parser based on the
|
|
8
|
+
* OpenQASM version being used.
|
|
9
|
+
*
|
|
10
|
+
* The parsing process follows these steps:
|
|
11
|
+
* 1. Receive tokenized input from the lexer
|
|
12
|
+
* 2. Determine OpenQASM version (2.0 or 3.0)
|
|
13
|
+
* 3. Select appropriate parser implementation
|
|
14
|
+
* 4. Generate version-specific AST nodes
|
|
15
|
+
*
|
|
16
|
+
* The specific Parser implementations can be found at:
|
|
17
|
+
* - {@link Qasm3Parser}
|
|
18
|
+
* - {@link Qasm2Parser}
|
|
19
|
+
*
|
|
20
|
+
* @module Parsing
|
|
21
|
+
*
|
|
22
|
+
* @example Basic parsing workflow
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { lex } from './lexer';
|
|
25
|
+
* import { parse } from './parser';
|
|
26
|
+
*
|
|
27
|
+
* const qasmCode = 'OPENQASM 3.0; h q[0];';
|
|
28
|
+
* const tokens = lex(qasmCode, undefined, 3);
|
|
29
|
+
* const ast = parse(tokens, 3);
|
|
30
|
+
* console.log(ast); // Array of AST nodes
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example Version-specific parsing
|
|
34
|
+
* ```typescript
|
|
35
|
+
* // Parse as OpenQASM 2.0
|
|
36
|
+
* const ast2 = parse(tokens, 2);
|
|
37
|
+
*
|
|
38
|
+
* // Parse as OpenQASM 3.0
|
|
39
|
+
* const ast3 = parse(tokens, 3);
|
|
40
|
+
*
|
|
41
|
+
* // Use OpenQASMVersion object
|
|
42
|
+
* const version = new OpenQASMVersion(3, 0);
|
|
43
|
+
* const ast = parse(tokens, version);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.parse = parse;
|
|
48
|
+
var parser_1 = require("./qasm2/parser");
|
|
49
|
+
var parser_2 = require("./qasm3/parser");
|
|
50
|
+
var version_1 = require("./version");
|
|
4
51
|
var errors_1 = require("./errors");
|
|
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
|
-
Parser.prototype.parse = function () {
|
|
41
|
-
var ast = [];
|
|
42
|
-
var i = 0;
|
|
43
|
-
while (i < (this.tokens.length - 1)) {
|
|
44
|
-
var nodes = this.parseNode(this.tokens.slice(i));
|
|
45
|
-
ast = ast.concat(nodes ? nodes : []);
|
|
46
|
-
while (!(this.matchNext(this.tokens.slice(i), [token_1.Token.Semicolon]))) {
|
|
47
|
-
if (this.matchNext(this.tokens.slice(i), [token_1.Token.LCParen])) {
|
|
48
|
-
while (!(this.matchNext(this.tokens.slice(i), [token_1.Token.RCParen]))) {
|
|
49
|
-
i++;
|
|
50
|
-
}
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
i++;
|
|
54
|
-
}
|
|
55
|
-
i++;
|
|
56
|
-
}
|
|
57
|
-
return ast;
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Delegates the parsing of the next set of tokens to the appropriate method.
|
|
61
|
-
* @param tokens - Remaining tokens to parse.
|
|
62
|
-
* @param allowVariables - Whether encountered identifiers should be consider
|
|
63
|
-
variable initializations or references.
|
|
64
|
-
* @return A set of AST nodes.
|
|
65
|
-
*/
|
|
66
|
-
Parser.prototype.parseNode = function (tokens, allowVariables) {
|
|
67
|
-
if (allowVariables === void 0) { allowVariables = false; }
|
|
68
|
-
var token = tokens[0];
|
|
69
|
-
switch (token[0]) {
|
|
70
|
-
case token_1.Token.QReg:
|
|
71
|
-
return [this.qreg(tokens.slice(1))];
|
|
72
|
-
case token_1.Token.CReg:
|
|
73
|
-
return [this.creg(tokens.slice(1))];
|
|
74
|
-
case token_1.Token.Barrier:
|
|
75
|
-
return [this.barrier(tokens.slice(1))];
|
|
76
|
-
case token_1.Token.Measure:
|
|
77
|
-
return [this.measure(tokens.slice(1))];
|
|
78
|
-
case token_1.Token.Id:
|
|
79
|
-
if (!(token[1].toString().indexOf('QASM') != -1) &&
|
|
80
|
-
!(token[1].toString().indexOf('include') != -1)) {
|
|
81
|
-
if (this.gates.includes(token[1].toString())) {
|
|
82
|
-
return [this.application(tokens, token[1].toString())];
|
|
83
|
-
}
|
|
84
|
-
else if (allowVariables) {
|
|
85
|
-
return [new ast_1.Variable(token[1].toString())];
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
throw errors_1.BadGateError;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
return [];
|
|
93
|
-
}
|
|
94
|
-
case token_1.Token.Gate:
|
|
95
|
-
return [this.gate(tokens.slice(1))];
|
|
96
|
-
case token_1.Token.If:
|
|
97
|
-
return [this.conditional(tokens.slice(1))];
|
|
98
|
-
case token_1.Token.Power:
|
|
99
|
-
return [new ast_1.Power()];
|
|
100
|
-
case token_1.Token.Divide:
|
|
101
|
-
return [new ast_1.Divide()];
|
|
102
|
-
case token_1.Token.Times:
|
|
103
|
-
return [new ast_1.Times()];
|
|
104
|
-
case token_1.Token.Plus:
|
|
105
|
-
return [new ast_1.Plus()];
|
|
106
|
-
case token_1.Token.Minus:
|
|
107
|
-
return [new ast_1.Minus()];
|
|
108
|
-
case token_1.Token.Pi:
|
|
109
|
-
return [new ast_1.Pi()];
|
|
110
|
-
case token_1.Token.Sin:
|
|
111
|
-
return [new ast_1.Sin()];
|
|
112
|
-
case token_1.Token.Cos:
|
|
113
|
-
return [new ast_1.Cos()];
|
|
114
|
-
case token_1.Token.Exp:
|
|
115
|
-
return [new ast_1.Exp()];
|
|
116
|
-
case token_1.Token.Ln:
|
|
117
|
-
return [new ast_1.Ln()];
|
|
118
|
-
case token_1.Token.Sqrt:
|
|
119
|
-
return [new ast_1.Sqrt()];
|
|
120
|
-
case token_1.Token.Tan:
|
|
121
|
-
return [new ast_1.Tan()];
|
|
122
|
-
case token_1.Token.NNInteger:
|
|
123
|
-
return [new ast_1.NNInteger(Number(token[1]))];
|
|
124
|
-
case token_1.Token.Real:
|
|
125
|
-
return [new ast_1.Real(Number(token[1]))];
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
/**
|
|
129
|
-
* Checks if the next tokens match those expected.
|
|
130
|
-
* @param tokens - Remaining tokens to parse.
|
|
131
|
-
* @param expectedTokens - Expected tokens.
|
|
132
|
-
* @return Whether these is a match.
|
|
133
|
-
*/
|
|
134
|
-
Parser.prototype.matchNext = function (tokens, expectedTokens) {
|
|
135
|
-
var matches = true;
|
|
136
|
-
var i = 0;
|
|
137
|
-
if (tokens.length == 0) {
|
|
138
|
-
return false;
|
|
139
|
-
}
|
|
140
|
-
while (i < expectedTokens.length) {
|
|
141
|
-
if (tokens[i][0] != expectedTokens[i]) {
|
|
142
|
-
matches = false;
|
|
52
|
+
/**
|
|
53
|
+
* Parses an array of tokens into an Abstract Syntax Tree (AST).
|
|
54
|
+
*
|
|
55
|
+
* This is the main entry point for parsing tokenized OpenQASM code. It automatically
|
|
56
|
+
* selects the appropriate parser implementation based on the specified version and
|
|
57
|
+
* returns an AST that can be used for further analysis, compilation, or execution.
|
|
58
|
+
*
|
|
59
|
+
* @group Parsing
|
|
60
|
+
* @param tokens - Array of tokens generated by the lexer
|
|
61
|
+
* @param version - OpenQASM version to use for parsing (defaults to 3.0)
|
|
62
|
+
* @returns Abstract Syntax Tree representing the parsed program
|
|
63
|
+
* @throws {UnsupportedOpenQASMVersionError} When an unsupported version is specified
|
|
64
|
+
*
|
|
65
|
+
* @example Parse OpenQASM 3.0 tokens
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const tokens = lex('OPENQASM 3.0; qubit q; h q;');
|
|
68
|
+
* const ast = parse(tokens, 3);
|
|
69
|
+
* // Returns array of OpenQASM 3.0 AST nodes
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @example Parse OpenQASM 2.0 tokens
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const tokens = lex('OPENQASM 2.0; qreg q[1]; h q[0];');
|
|
75
|
+
* const ast = parse(tokens, 2);
|
|
76
|
+
* // Returns array of OpenQASM 2.0 AST nodes
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
function parse(tokens, version) {
|
|
80
|
+
var parser;
|
|
81
|
+
var castTokens;
|
|
82
|
+
if (version instanceof version_1.OpenQASMVersion) {
|
|
83
|
+
switch (version.major) {
|
|
84
|
+
case version_1.OpenQASMMajorVersion.Version2:
|
|
85
|
+
castTokens = tokens;
|
|
86
|
+
parser = new parser_1.default(castTokens);
|
|
143
87
|
break;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return matches;
|
|
148
|
-
};
|
|
149
|
-
/**
|
|
150
|
-
* Parses a quantum register.
|
|
151
|
-
* @param tokens - Remaining tokens to parse.
|
|
152
|
-
* @return An AST node representing the quantum register.
|
|
153
|
-
*/
|
|
154
|
-
Parser.prototype.qreg = function (tokens) {
|
|
155
|
-
if (this.matchNext(tokens, [token_1.Token.Id, token_1.Token.LSParen, token_1.Token.NNInteger, token_1.Token.RSParen, token_1.Token.Semicolon])) {
|
|
156
|
-
var id = tokens[0][1];
|
|
157
|
-
var size = tokens[2][1];
|
|
158
|
-
return new ast_1.QReg(id.toString(), Number(size));
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
throw errors_1.BadQregError;
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
/**
|
|
165
|
-
* Parses a classical register.
|
|
166
|
-
* @param tokens - Remaining tokens to parse.
|
|
167
|
-
* @return An AST node representing the classical register.
|
|
168
|
-
*/
|
|
169
|
-
Parser.prototype.creg = function (tokens) {
|
|
170
|
-
if (this.matchNext(tokens, [token_1.Token.Id, token_1.Token.LSParen, token_1.Token.NNInteger,
|
|
171
|
-
token_1.Token.RSParen, token_1.Token.Semicolon])) {
|
|
172
|
-
var id = tokens[0][1];
|
|
173
|
-
var size = tokens[2][1];
|
|
174
|
-
return new ast_1.CReg(id.toString(), Number(size));
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
throw errors_1.BadCregError;
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
/**
|
|
181
|
-
* Parses a conditional.
|
|
182
|
-
* @param tokens - Remaining tokens to parse.
|
|
183
|
-
* @return An AST node representing the conditional.
|
|
184
|
-
*/
|
|
185
|
-
Parser.prototype.conditional = function (tokens) {
|
|
186
|
-
if (this.matchNext(tokens, [token_1.Token.LParen, token_1.Token.Id, token_1.Token.Equals, token_1.Token.NNInteger, token_1.Token.RParen])) {
|
|
187
|
-
var id = tokens[1][1];
|
|
188
|
-
var val = tokens[3][1];
|
|
189
|
-
var node = this.parseNode(tokens.slice(5));
|
|
190
|
-
return new ast_1.If(id.toString(), Number(val), node);
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
throw errors_1.BadConditionalError;
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
/**
|
|
197
|
-
* Parses a barrier.
|
|
198
|
-
* @param tokens - Remaining tokens to parse.
|
|
199
|
-
* @return An AST node representing the barrier.
|
|
200
|
-
*/
|
|
201
|
-
Parser.prototype.barrier = function (tokens) {
|
|
202
|
-
if (this.matchNext(tokens, [token_1.Token.Id, token_1.Token.Semicolon])) {
|
|
203
|
-
var id = tokens[0][1];
|
|
204
|
-
return new ast_1.Barrier(id.toString());
|
|
205
|
-
}
|
|
206
|
-
else if (this.matchNext(tokens, [token_1.Token.Id, token_1.Token.LParen,
|
|
207
|
-
token_1.Token.NNInteger, token_1.Token.RParen, token_1.Token.Semicolon])) {
|
|
208
|
-
var id = tokens[0][1];
|
|
209
|
-
var index = tokens[2][1];
|
|
210
|
-
return new ast_1.Barrier(id.toString(), Number(index));
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
throw errors_1.BadBarrierError;
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
/**
|
|
217
|
-
* Parses a measurement.
|
|
218
|
-
* @param tokens - Remaining tokens to parse.
|
|
219
|
-
* @return An AST node representing the measurement.
|
|
220
|
-
*/
|
|
221
|
-
Parser.prototype.measure = function (tokens) {
|
|
222
|
-
var first_id;
|
|
223
|
-
var second_id;
|
|
224
|
-
var first_index;
|
|
225
|
-
var second_index;
|
|
226
|
-
if (this.matchNext(tokens, [token_1.Token.Id, token_1.Token.Arrow])) {
|
|
227
|
-
first_id = tokens[0][1].toString();
|
|
228
|
-
tokens = tokens.slice(2);
|
|
229
|
-
}
|
|
230
|
-
else if (this.matchNext(tokens, [token_1.Token.Id, token_1.Token.LSParen, token_1.Token.NNInteger, token_1.Token.RSParen, token_1.Token.Arrow])) {
|
|
231
|
-
first_id = tokens[0][1].toString();
|
|
232
|
-
first_index = Number(tokens[2][1]);
|
|
233
|
-
tokens = tokens.slice(5);
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
throw errors_1.BadMeasurementError;
|
|
237
|
-
}
|
|
238
|
-
if (this.matchNext(tokens, [token_1.Token.Id, token_1.Token.Semicolon])) {
|
|
239
|
-
second_id = tokens[0][1].toString();
|
|
240
|
-
tokens = tokens.slice(2);
|
|
241
|
-
}
|
|
242
|
-
else if (this.matchNext(tokens, [token_1.Token.Id, token_1.Token.LSParen, token_1.Token.NNInteger, token_1.Token.RSParen, token_1.Token.Semicolon])) {
|
|
243
|
-
second_id = tokens[0][1].toString();
|
|
244
|
-
second_index = Number(tokens[2][1]);
|
|
245
|
-
tokens = tokens.slice(5);
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
throw errors_1.BadMeasurementError;
|
|
249
|
-
}
|
|
250
|
-
if (first_index != undefined && second_index != undefined) {
|
|
251
|
-
return new ast_1.Measure(first_id, second_id, first_index, second_index);
|
|
252
|
-
}
|
|
253
|
-
else if (first_index != undefined) {
|
|
254
|
-
return new ast_1.Measure(first_id, second_id, first_index = first_index);
|
|
255
|
-
}
|
|
256
|
-
else if (second_index != undefined) {
|
|
257
|
-
return new ast_1.Measure(first_id, second_id, second_index = second_index);
|
|
258
|
-
}
|
|
259
|
-
return new ast_1.Measure(first_id, second_id);
|
|
260
|
-
};
|
|
261
|
-
/**
|
|
262
|
-
* Parses an application of one of the allowed gates.
|
|
263
|
-
* @param tokens - Remaining tokens to parse.
|
|
264
|
-
* @return An AST node representing the gate application.
|
|
265
|
-
*/
|
|
266
|
-
Parser.prototype.application = function (tokens, op) {
|
|
267
|
-
var params = [];
|
|
268
|
-
var list = [];
|
|
269
|
-
var applications = [];
|
|
270
|
-
var id;
|
|
271
|
-
if (tokens[0][1] == op) {
|
|
272
|
-
tokens = tokens.slice(1);
|
|
273
|
-
}
|
|
274
|
-
if (this.matchNext(tokens, [token_1.Token.LParen])) {
|
|
275
|
-
if (this.matchNext(tokens.slice(1), [token_1.Token.RParen])) {
|
|
276
|
-
params = [];
|
|
277
|
-
tokens = tokens.slice(2);
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
params = this.matchParamList(tokens.slice(1));
|
|
281
|
-
var count = 0;
|
|
282
|
-
var commas = 0;
|
|
283
|
-
for (var i in params) {
|
|
284
|
-
commas += 1;
|
|
285
|
-
for (var j in params[i]) {
|
|
286
|
-
count++;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
tokens = tokens.slice(count + (commas - 1) + 2);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
var args = this.matchArgList(tokens);
|
|
293
|
-
for (var arg in args) {
|
|
294
|
-
id = args[arg][0];
|
|
295
|
-
list.push(args[arg]);
|
|
296
|
-
}
|
|
297
|
-
applications.push(new ast_1.ApplyGate(op, list, params));
|
|
298
|
-
return applications;
|
|
299
|
-
};
|
|
300
|
-
/**
|
|
301
|
-
* Parses a subroutine used in a custom gate definition.
|
|
302
|
-
* @param tokens - Expression tokens to parse.
|
|
303
|
-
* @return A parsed subroutine.
|
|
304
|
-
*/
|
|
305
|
-
Parser.prototype.sub = function (tokens) {
|
|
306
|
-
var ast = [];
|
|
307
|
-
var i = 0;
|
|
308
|
-
if (this.matchNext(tokens.slice(i), [token_1.Token.LCParen])) {
|
|
309
|
-
tokens = tokens.slice(1);
|
|
310
|
-
}
|
|
311
|
-
while ((i < (tokens.length - 1)) && (tokens[i][0] != token_1.Token.RCParen)) {
|
|
312
|
-
var nodes = this.parseNode(tokens.slice(i));
|
|
313
|
-
ast = ast.concat(nodes ? nodes : []);
|
|
314
|
-
while ((!this.matchNext(tokens.slice(i), [token_1.Token.Semicolon])) &&
|
|
315
|
-
(!this.matchNext(tokens.slice(i), [token_1.Token.RCParen]))) {
|
|
316
|
-
i++;
|
|
317
|
-
}
|
|
318
|
-
if (this.matchNext(tokens.slice(i), [token_1.Token.RCParen])) {
|
|
88
|
+
case version_1.OpenQASMMajorVersion.Version3:
|
|
89
|
+
castTokens = tokens;
|
|
90
|
+
parser = new parser_1.default(castTokens);
|
|
319
91
|
break;
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
return ast;
|
|
324
|
-
};
|
|
325
|
-
/**
|
|
326
|
-
* Parses a parameter value.
|
|
327
|
-
* @param tokens - Tokens to parse.
|
|
328
|
-
* @return An AST node representing the parameter value.
|
|
329
|
-
*/
|
|
330
|
-
Parser.prototype.matchParam = function (tokens) {
|
|
331
|
-
var param;
|
|
332
|
-
if (!(token_1.notParam(tokens[0][0]))) {
|
|
333
|
-
param = this.parseNode([tokens[0]], true);
|
|
92
|
+
default:
|
|
93
|
+
throw new errors_1.UnsupportedOpenQASMVersionError("Unsupported OpenQASM version detected: ".concat(version.major));
|
|
334
94
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
* Parses a list of parameter values.
|
|
342
|
-
* @param tokens - Tokens to parse.
|
|
343
|
-
* @return An array of AST nodes representing the parameter values.
|
|
344
|
-
*/
|
|
345
|
-
Parser.prototype.matchParamList = function (tokens) {
|
|
346
|
-
var args = [];
|
|
347
|
-
var i = 0;
|
|
348
|
-
var j = 0;
|
|
349
|
-
args[0] = [];
|
|
350
|
-
while (!this.matchNext(tokens.slice(j), [token_1.Token.RParen])) {
|
|
351
|
-
while (!this.matchNext(tokens.slice(j), [token_1.Token.Comma]) &&
|
|
352
|
-
!this.matchNext(tokens.slice(j), [token_1.Token.RParen])) {
|
|
353
|
-
if (token_1.notParam(tokens[j][0])) {
|
|
354
|
-
throw errors_1.BadParameterError;
|
|
355
|
-
}
|
|
356
|
-
var next = this.matchParam(tokens.slice(j));
|
|
357
|
-
args[i].push(next);
|
|
358
|
-
j++;
|
|
359
|
-
}
|
|
360
|
-
if (this.matchNext(tokens.slice(j), [token_1.Token.RParen])) {
|
|
95
|
+
}
|
|
96
|
+
else if (typeof version === "number") {
|
|
97
|
+
switch (version) {
|
|
98
|
+
case 2:
|
|
99
|
+
castTokens = tokens;
|
|
100
|
+
parser = new parser_1.default(castTokens);
|
|
361
101
|
break;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
};
|
|
369
|
-
/**
|
|
370
|
-
* Parses an argument value.
|
|
371
|
-
* @param tokens - Tokens to parse.
|
|
372
|
-
* @return An AST node representing the argument value.
|
|
373
|
-
*/
|
|
374
|
-
Parser.prototype.matchArg = function (tokens) {
|
|
375
|
-
var index;
|
|
376
|
-
if (this.matchNext(tokens, [token_1.Token.LSParen])) {
|
|
377
|
-
tokens = tokens.slice(1);
|
|
378
|
-
if (this.matchNext(tokens, [token_1.Token.NNInteger])) {
|
|
379
|
-
index = Number(tokens[0][1]);
|
|
380
|
-
tokens = tokens.slice(1);
|
|
381
|
-
}
|
|
382
|
-
else {
|
|
383
|
-
throw errors_1.BadArgumentError;
|
|
384
|
-
}
|
|
385
|
-
if (this.matchNext(tokens, [token_1.Token.RSParen])) {
|
|
386
|
-
return index;
|
|
387
|
-
}
|
|
388
|
-
else {
|
|
389
|
-
throw errors_1.BadArgumentError;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
/**
|
|
394
|
-
* Parses a list of argument values.
|
|
395
|
-
* @param tokens - Tokens to parse.
|
|
396
|
-
* @return An array of AST nodes representing the argument values.
|
|
397
|
-
*/
|
|
398
|
-
Parser.prototype.matchArgList = function (tokens) {
|
|
399
|
-
var args = [];
|
|
400
|
-
var next;
|
|
401
|
-
var id;
|
|
402
|
-
var j = 0;
|
|
403
|
-
while (j < tokens.length && !this.matchNext(tokens.slice(j), [token_1.Token.Semicolon])) {
|
|
404
|
-
if (this.matchNext(tokens.slice(j), [token_1.Token.Id])) {
|
|
405
|
-
id = tokens[j][1].toString();
|
|
406
|
-
var index = this.matchArg(tokens.slice(j + 1));
|
|
407
|
-
next = [id, index];
|
|
408
|
-
args.push(next);
|
|
409
|
-
if (index != undefined) {
|
|
410
|
-
j += 4;
|
|
411
|
-
}
|
|
412
|
-
else {
|
|
413
|
-
j++;
|
|
414
|
-
}
|
|
415
|
-
if (this.matchNext(tokens.slice(j), [token_1.Token.Comma])) {
|
|
416
|
-
j++;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
else {
|
|
420
|
-
throw errors_1.BadArgumentError;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
return args;
|
|
424
|
-
};
|
|
425
|
-
/**
|
|
426
|
-
* Parses a list of identifiers.
|
|
427
|
-
* @param tokens - Tokens to parse.
|
|
428
|
-
* @return An array of AST nodes representing the identifiers.
|
|
429
|
-
*/
|
|
430
|
-
Parser.prototype.matchIdList = function (tokens) {
|
|
431
|
-
var args = [];
|
|
432
|
-
var head;
|
|
433
|
-
if (this.matchNext(tokens, [token_1.Token.Id])) {
|
|
434
|
-
head = tokens[0][1].toString();
|
|
435
|
-
}
|
|
436
|
-
tokens = tokens.slice(1);
|
|
437
|
-
args.push(head);
|
|
438
|
-
if (this.matchNext(tokens, [token_1.Token.Comma])) {
|
|
439
|
-
tokens = tokens.slice(1);
|
|
440
|
-
var sub = this.matchIdList(tokens);
|
|
441
|
-
args = args.concat(sub);
|
|
442
|
-
}
|
|
443
|
-
return args;
|
|
444
|
-
};
|
|
445
|
-
/**
|
|
446
|
-
* Parses a gate.
|
|
447
|
-
* @param tokens - Remaining tokens to parse.
|
|
448
|
-
* @return An AST node representing the gate.
|
|
449
|
-
*/
|
|
450
|
-
Parser.prototype.gate = function (tokens) {
|
|
451
|
-
var name;
|
|
452
|
-
var params;
|
|
453
|
-
var registers;
|
|
454
|
-
var applications;
|
|
455
|
-
if (this.matchNext(tokens, [token_1.Token.Id])) {
|
|
456
|
-
name = tokens[0][1].toString();
|
|
457
|
-
}
|
|
458
|
-
else {
|
|
459
|
-
throw errors_1.BadGateError;
|
|
460
|
-
}
|
|
461
|
-
tokens = tokens.slice(1);
|
|
462
|
-
if (this.matchNext(tokens, [token_1.Token.LParen])) {
|
|
463
|
-
tokens = tokens.slice(1);
|
|
464
|
-
if (this.matchNext(tokens, [token_1.Token.RParen])) {
|
|
465
|
-
params = [];
|
|
466
|
-
tokens = tokens.slice(1);
|
|
467
|
-
}
|
|
468
|
-
else {
|
|
469
|
-
params = this.matchIdList(tokens);
|
|
470
|
-
var count_1 = 0;
|
|
471
|
-
for (var i in params) {
|
|
472
|
-
count_1++;
|
|
473
|
-
}
|
|
474
|
-
tokens = tokens.slice(count_1 + 1);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
registers = this.matchIdList(tokens);
|
|
478
|
-
var count = 0;
|
|
479
|
-
for (var i in registers) {
|
|
480
|
-
count++;
|
|
102
|
+
case 3:
|
|
103
|
+
castTokens = tokens;
|
|
104
|
+
parser = new parser_2.default(castTokens);
|
|
105
|
+
break;
|
|
106
|
+
default:
|
|
107
|
+
throw new errors_1.UnsupportedOpenQASMVersionError("Unsupported OpenQASM version detected: ".concat(version));
|
|
481
108
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
109
|
+
}
|
|
110
|
+
else if (version === version_1.OpenQASMMajorVersion.Version2) {
|
|
111
|
+
castTokens = tokens;
|
|
112
|
+
parser = new parser_1.default(castTokens);
|
|
113
|
+
}
|
|
114
|
+
else if (version === version_1.OpenQASMMajorVersion.Version3) {
|
|
115
|
+
castTokens = tokens;
|
|
116
|
+
parser = new parser_2.default(castTokens);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
castTokens = tokens;
|
|
120
|
+
parser = new parser_2.default(castTokens);
|
|
121
|
+
}
|
|
122
|
+
var ast = parser.parse();
|
|
123
|
+
return ast;
|
|
124
|
+
}
|