qasm-ts 1.1.2 → 2.0.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/dist/errors.js +119 -2
- package/dist/lexer.js +39 -294
- package/dist/main.js +42 -12
- package/dist/parser.js +46 -482
- package/dist/{ast.js → qasm2/ast.js} +38 -2
- package/dist/qasm2/lexer.js +436 -0
- package/dist/qasm2/parser.js +609 -0
- package/dist/{token.js → qasm2/token.js} +62 -21
- package/dist/qasm3/ast.js +1081 -0
- package/dist/qasm3/lexer.js +615 -0
- package/dist/qasm3/parser.js +2030 -0
- package/dist/qasm3/token.js +342 -0
- package/dist/version.js +41 -0
- package/docs/.nojekyll +1 -0
- package/docs/assets/highlight.css +99 -0
- package/docs/assets/icons.js +18 -0
- package/docs/assets/icons.svg +1 -0
- package/docs/assets/main.js +60 -0
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1493 -0
- package/docs/classes/errors.BadArgumentError.html +12 -0
- package/docs/classes/errors.BadBarrierError.html +12 -0
- package/docs/classes/errors.BadClassicalTypeError.html +12 -0
- package/docs/classes/errors.BadConditionalError.html +12 -0
- package/docs/classes/errors.BadCregError.html +12 -0
- package/docs/classes/errors.BadEqualsError.html +12 -0
- package/docs/classes/errors.BadExpressionError.html +12 -0
- package/docs/classes/errors.BadGateError.html +12 -0
- package/docs/classes/errors.BadIncludeError.html +12 -0
- package/docs/classes/errors.BadLoopError.html +12 -0
- package/docs/classes/errors.BadMeasurementError.html +12 -0
- package/docs/classes/errors.BadParameterError.html +12 -0
- package/docs/classes/errors.BadQregError.html +12 -0
- package/docs/classes/errors.BadQuantumInstructionError.html +12 -0
- package/docs/classes/errors.BadStringLiteralError.html +12 -0
- package/docs/classes/errors.BadSubroutineError.html +12 -0
- package/docs/classes/errors.MissingBraceError.html +12 -0
- package/docs/classes/errors.MissingSemicolonError.html +12 -0
- package/docs/classes/errors.UnsupportedOpenQASMVersionError.html +12 -0
- package/docs/classes/qasm2_ast.ApplyGate.html +6 -0
- package/docs/classes/qasm2_ast.AstNode.html +3 -0
- package/docs/classes/qasm2_ast.Barrier.html +5 -0
- package/docs/classes/qasm2_ast.CReg.html +5 -0
- package/docs/classes/qasm2_ast.Cos.html +3 -0
- package/docs/classes/qasm2_ast.Divide.html +3 -0
- package/docs/classes/qasm2_ast.Exp.html +3 -0
- package/docs/classes/qasm2_ast.Gate.html +7 -0
- package/docs/classes/qasm2_ast.Id.html +4 -0
- package/docs/classes/qasm2_ast.If.html +6 -0
- package/docs/classes/qasm2_ast.Include.html +4 -0
- package/docs/classes/qasm2_ast.Ln.html +3 -0
- package/docs/classes/qasm2_ast.Measure.html +7 -0
- package/docs/classes/qasm2_ast.Minus.html +3 -0
- package/docs/classes/qasm2_ast.NNInteger.html +4 -0
- package/docs/classes/qasm2_ast.Opaque.html +6 -0
- package/docs/classes/qasm2_ast.Pi.html +3 -0
- package/docs/classes/qasm2_ast.Plus.html +3 -0
- package/docs/classes/qasm2_ast.Power.html +3 -0
- package/docs/classes/qasm2_ast.QReg.html +5 -0
- package/docs/classes/qasm2_ast.Real.html +4 -0
- package/docs/classes/qasm2_ast.Sin.html +3 -0
- package/docs/classes/qasm2_ast.Sqrt.html +3 -0
- package/docs/classes/qasm2_ast.Tan.html +3 -0
- package/docs/classes/qasm2_ast.Times.html +3 -0
- package/docs/classes/qasm2_ast.Variable.html +4 -0
- package/docs/classes/qasm2_ast.Version.html +4 -0
- package/docs/classes/qasm2_lexer.default.html +50 -0
- package/docs/classes/qasm2_parser.default.html +87 -0
- package/docs/classes/qasm3_ast.AliasStatement.html +5 -0
- package/docs/classes/qasm3_ast.AngleType.html +4 -0
- package/docs/classes/qasm3_ast.Arithmetic.html +6 -0
- package/docs/classes/qasm3_ast.ArrayAccess.html +5 -0
- package/docs/classes/qasm3_ast.ArrayDeclaration.html +7 -0
- package/docs/classes/qasm3_ast.ArrayInitializer.html +4 -0
- package/docs/classes/qasm3_ast.ArrayReference.html +5 -0
- package/docs/classes/qasm3_ast.AssignmentStatement.html +5 -0
- package/docs/classes/qasm3_ast.AstNode.html +3 -0
- package/docs/classes/qasm3_ast.Binary.html +6 -0
- package/docs/classes/qasm3_ast.BitType.html +4 -0
- package/docs/classes/qasm3_ast.BitstringLiteral.html +4 -0
- package/docs/classes/qasm3_ast.BoolType.html +3 -0
- package/docs/classes/qasm3_ast.BooleanLiteral.html +4 -0
- package/docs/classes/qasm3_ast.BoxDefinition.html +7 -0
- package/docs/classes/qasm3_ast.BranchingStatement.html +8 -0
- package/docs/classes/qasm3_ast.BreakStatement.html +3 -0
- package/docs/classes/qasm3_ast.CalibrationGrammarDeclaration.html +6 -0
- package/docs/classes/qasm3_ast.CaseStatement.html +5 -0
- package/docs/classes/qasm3_ast.Cast.html +5 -0
- package/docs/classes/qasm3_ast.ClassicalDeclaration.html +7 -0
- package/docs/classes/qasm3_ast.ClassicalType.html +3 -0
- package/docs/classes/qasm3_ast.ComplexType.html +6 -0
- package/docs/classes/qasm3_ast.ContinueStatement.html +3 -0
- package/docs/classes/qasm3_ast.DefaultStatement.html +4 -0
- package/docs/classes/qasm3_ast.DurationLiteral.html +5 -0
- package/docs/classes/qasm3_ast.DurationOf.html +4 -0
- package/docs/classes/qasm3_ast.DurationType.html +3 -0
- package/docs/classes/qasm3_ast.Euler.html +3 -0
- package/docs/classes/qasm3_ast.Expression.html +3 -0
- package/docs/classes/qasm3_ast.ExternSignature.html +8 -0
- package/docs/classes/qasm3_ast.FloatLiteral.html +4 -0
- package/docs/classes/qasm3_ast.FloatType.html +6 -0
- package/docs/classes/qasm3_ast.ForLoopStatement.html +12 -0
- package/docs/classes/qasm3_ast.HardwareQubit.html +5 -0
- package/docs/classes/qasm3_ast.IODeclaration.html +5 -0
- package/docs/classes/qasm3_ast.Identifier.html +4 -0
- package/docs/classes/qasm3_ast.ImaginaryLiteral.html +4 -0
- package/docs/classes/qasm3_ast.Include.html +6 -0
- package/docs/classes/qasm3_ast.IndexSet.html +5 -0
- package/docs/classes/qasm3_ast.IntType.html +4 -0
- package/docs/classes/qasm3_ast.IntegerLiteral.html +4 -0
- package/docs/classes/qasm3_ast.MathFunction.html +5 -0
- package/docs/classes/qasm3_ast.NumericLiteral.html +4 -0
- package/docs/classes/qasm3_ast.Parameters.html +4 -0
- package/docs/classes/qasm3_ast.Pi.html +3 -0
- package/docs/classes/qasm3_ast.ProgramBlock.html +7 -0
- package/docs/classes/qasm3_ast.QuantumBarrier.html +6 -0
- package/docs/classes/qasm3_ast.QuantumBlock.html +6 -0
- package/docs/classes/qasm3_ast.QuantumDeclaration.html +8 -0
- package/docs/classes/qasm3_ast.QuantumDelay.html +5 -0
- package/docs/classes/qasm3_ast.QuantumGateCall.html +9 -0
- package/docs/classes/qasm3_ast.QuantumGateDefinition.html +9 -0
- package/docs/classes/qasm3_ast.QuantumGateModifier.html +5 -0
- package/docs/classes/qasm3_ast.QuantumMeasurement.html +6 -0
- package/docs/classes/qasm3_ast.QuantumMeasurementAssignment.html +8 -0
- package/docs/classes/qasm3_ast.QuantumReset.html +4 -0
- package/docs/classes/qasm3_ast.Range.html +6 -0
- package/docs/classes/qasm3_ast.ReturnStatement.html +4 -0
- package/docs/classes/qasm3_ast.SizeOf.html +5 -0
- package/docs/classes/qasm3_ast.Statement.html +12 -0
- package/docs/classes/qasm3_ast.StretchType.html +3 -0
- package/docs/classes/qasm3_ast.SubroutineBlock.html +6 -0
- package/docs/classes/qasm3_ast.SubroutineCall.html +5 -0
- package/docs/classes/qasm3_ast.SubroutineDefinition.html +10 -0
- package/docs/classes/qasm3_ast.SubscriptedIdentifier.html +5 -0
- package/docs/classes/qasm3_ast.SwitchStatement.html +6 -0
- package/docs/classes/qasm3_ast.Tau.html +3 -0
- package/docs/classes/qasm3_ast.TrigFunction.html +5 -0
- package/docs/classes/qasm3_ast.UIntType.html +4 -0
- package/docs/classes/qasm3_ast.Unary.html +5 -0
- package/docs/classes/qasm3_ast.Version.html +6 -0
- package/docs/classes/qasm3_ast.WhileLoopStatement.html +6 -0
- package/docs/classes/qasm3_lexer.default.html +60 -0
- package/docs/classes/qasm3_parser.default.html +227 -0
- package/docs/classes/version.OpenQASMVersion.html +16 -0
- package/docs/enums/qasm2_token.Token.html +39 -0
- package/docs/enums/qasm3_ast.ArithmeticOp.html +9 -0
- package/docs/enums/qasm3_ast.ArrayReferenceModifier.html +4 -0
- package/docs/enums/qasm3_ast.BinaryOp.html +15 -0
- package/docs/enums/qasm3_ast.DurationUnit.html +7 -0
- package/docs/enums/qasm3_ast.IOModifier.html +4 -0
- package/docs/enums/qasm3_ast.MathFunctionTypes.html +12 -0
- package/docs/enums/qasm3_ast.QuantumGateModifierName.html +6 -0
- package/docs/enums/qasm3_ast.TrigFunctionTypes.html +8 -0
- package/docs/enums/qasm3_ast.UnaryOp.html +5 -0
- package/docs/enums/qasm3_token.Token.html +101 -0
- package/docs/enums/version.OpenQASMMajorVersion.html +4 -0
- package/docs/functions/lexer.lex.html +1 -0
- package/docs/functions/main.parseFile.html +4 -0
- package/docs/functions/main.parseString.html +4 -0
- package/docs/functions/parser.parse.html +1 -0
- package/docs/functions/qasm2_token.inverseLookup.html +3 -0
- package/docs/functions/qasm2_token.lookup.html +4 -0
- package/docs/functions/qasm2_token.notParam.html +3 -0
- package/docs/functions/qasm3_token.inverseLookup.html +3 -0
- package/docs/functions/qasm3_token.lookup.html +4 -0
- package/docs/functions/qasm3_token.notParam.html +3 -0
- package/docs/hierarchy.html +1 -0
- package/docs/index.html +55 -0
- package/docs/modules/errors.html +21 -0
- package/docs/modules/lexer.html +2 -0
- package/docs/modules/main.html +3 -0
- package/docs/modules/parser.html +2 -0
- package/docs/modules/qasm2_ast.html +28 -0
- package/docs/modules/qasm2_lexer.html +2 -0
- package/docs/modules/qasm2_parser.html +2 -0
- package/docs/modules/qasm2_token.html +5 -0
- package/docs/modules/qasm3_ast.html +83 -0
- package/docs/modules/qasm3_lexer.html +2 -0
- package/docs/modules/qasm3_parser.html +2 -0
- package/docs/modules/qasm3_token.html +5 -0
- package/docs/modules/version.html +3 -0
- package/docs/modules.html +14 -0
- package/docs/types/errors.ReturnErrorConstructor.html +2 -0
- package/package.json +5 -4
- package/readme.md +67 -51
- package/dist/example.js +0 -22
|
@@ -0,0 +1,2030 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
var token_1 = require("./token");
|
|
5
|
+
var version_1 = require("../version");
|
|
6
|
+
var errors_1 = require("../errors");
|
|
7
|
+
var ast_1 = require("./ast");
|
|
8
|
+
/**
|
|
9
|
+
* Handles throwing parser errors with basic stack trace.
|
|
10
|
+
* @param error - The error to throw.
|
|
11
|
+
* @param token - The source token for the error.
|
|
12
|
+
* @param index - The token index.
|
|
13
|
+
* @param message - Optional additional error context.
|
|
14
|
+
*/
|
|
15
|
+
function throwParserError(error, token, index, message) {
|
|
16
|
+
var errorMessage = message
|
|
17
|
+
? "index: ".concat(index, " at token [").concat(token, "], ").concat(message)
|
|
18
|
+
: "index: ".concat(index, " at token [").concat(token, "]");
|
|
19
|
+
throw new error(errorMessage);
|
|
20
|
+
}
|
|
21
|
+
/** Class representing a token parser. */
|
|
22
|
+
var Parser = /** @class */ (function () {
|
|
23
|
+
/**
|
|
24
|
+
* Creates a parser.
|
|
25
|
+
* @param tokens - Tokens to parse.
|
|
26
|
+
* @param defaultFloatWidth - Optional default float width override.
|
|
27
|
+
* @param machineIntSize - Optional default int size override.
|
|
28
|
+
*/
|
|
29
|
+
function Parser(tokens, defaultFloatWidth, machineIntSize) {
|
|
30
|
+
this.tokens = tokens;
|
|
31
|
+
this.gates = new Set(["U", "gphase"]);
|
|
32
|
+
this.standardGates = new Set();
|
|
33
|
+
this.customGates = new Set();
|
|
34
|
+
this.subroutines = new Set();
|
|
35
|
+
this.customArrays = new Set();
|
|
36
|
+
this.aliases = new Map();
|
|
37
|
+
this.index = 0;
|
|
38
|
+
this.machineFloatWidth = defaultFloatWidth ? defaultFloatWidth : 64;
|
|
39
|
+
this.machineIntSize = machineIntSize ? machineIntSize : 32;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Loads the standard library gates.
|
|
43
|
+
*/
|
|
44
|
+
Parser.prototype.stdGates = function () {
|
|
45
|
+
var gates = [
|
|
46
|
+
"p",
|
|
47
|
+
"x",
|
|
48
|
+
"y",
|
|
49
|
+
"z",
|
|
50
|
+
"h",
|
|
51
|
+
"s",
|
|
52
|
+
"sdg",
|
|
53
|
+
"t",
|
|
54
|
+
"tdg",
|
|
55
|
+
"sx",
|
|
56
|
+
"rx",
|
|
57
|
+
"ry",
|
|
58
|
+
"rz",
|
|
59
|
+
"cx",
|
|
60
|
+
"cy",
|
|
61
|
+
"cz",
|
|
62
|
+
"cp",
|
|
63
|
+
"crx",
|
|
64
|
+
"cry",
|
|
65
|
+
"crz",
|
|
66
|
+
"ch",
|
|
67
|
+
"swap",
|
|
68
|
+
"ccx",
|
|
69
|
+
"cswap",
|
|
70
|
+
"cu",
|
|
71
|
+
// OpenQASM 2 backwards compatibility gates
|
|
72
|
+
"CX",
|
|
73
|
+
"phase",
|
|
74
|
+
"cphase",
|
|
75
|
+
"id",
|
|
76
|
+
"u1",
|
|
77
|
+
"u2",
|
|
78
|
+
"u3",
|
|
79
|
+
];
|
|
80
|
+
gates.forEach(this.standardGates.add, this.standardGates);
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Parses the token stream and generates an abstract syntax tree.
|
|
84
|
+
* @return The abstract syntax tree.
|
|
85
|
+
*/
|
|
86
|
+
Parser.prototype.parse = function () {
|
|
87
|
+
var ast = [];
|
|
88
|
+
while (this.index < this.tokens.length - 1) {
|
|
89
|
+
var _a = this.parseNode(this.tokens.slice(this.index)), nodes = _a[0], consumed = _a[1];
|
|
90
|
+
ast = ast.concat(nodes ? nodes : []);
|
|
91
|
+
this.index += consumed;
|
|
92
|
+
}
|
|
93
|
+
return ast;
|
|
94
|
+
// let i = 0;
|
|
95
|
+
// while (i < this.tokens.length - 1) {
|
|
96
|
+
// this.index = i;
|
|
97
|
+
// const nodes = this.parseNode(this.tokens.slice(i))[0];
|
|
98
|
+
// ast = ast.concat(nodes ? nodes : []);
|
|
99
|
+
// while (!this.matchNext(this.tokens.slice(i), [Token.Semicolon])) {
|
|
100
|
+
// if (this.matchNext(this.tokens.slice(i), [Token.LCParen])) {
|
|
101
|
+
// while (!this.matchNext(this.tokens.slice(i), [Token.RCParen])) {
|
|
102
|
+
// i++;
|
|
103
|
+
// }
|
|
104
|
+
// break;
|
|
105
|
+
// } else if (this.matchNext(this.tokens.slice(i), [Token.RCParen])) {
|
|
106
|
+
// break;
|
|
107
|
+
// }
|
|
108
|
+
// i++;
|
|
109
|
+
// }
|
|
110
|
+
// i++;
|
|
111
|
+
// }
|
|
112
|
+
// return ast;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Parses a single statement or declaration by delegating the parsing of the next set of tokens to the appropriate method.
|
|
116
|
+
* @param tokens - Remaining tokens to parse.
|
|
117
|
+
* @param allowVariables - Whether encountered identifiers should be consider
|
|
118
|
+
variable initializations or references.
|
|
119
|
+
* @return A set of AST nodes and the number of consumed tokens.
|
|
120
|
+
*/
|
|
121
|
+
Parser.prototype.parseNode = function (tokens, allowVariables) {
|
|
122
|
+
if (allowVariables === void 0) { allowVariables = true; }
|
|
123
|
+
var token = tokens[0];
|
|
124
|
+
switch (token[0]) {
|
|
125
|
+
case token_1.Token.DefcalGrammar: {
|
|
126
|
+
var _a = this.defcalGrammarDeclaration(tokens), defcalGrammarNode = _a[0], consumed = _a[1];
|
|
127
|
+
return [[defcalGrammarNode], consumed];
|
|
128
|
+
}
|
|
129
|
+
case token_1.Token.Include: {
|
|
130
|
+
var _b = this.include(tokens), includeNode = _b[0], consumed = _b[1];
|
|
131
|
+
if (includeNode.filename === '"stdgates.inc"') {
|
|
132
|
+
this.stdGates();
|
|
133
|
+
}
|
|
134
|
+
return [[includeNode], consumed];
|
|
135
|
+
}
|
|
136
|
+
case token_1.Token.OpenQASM: {
|
|
137
|
+
var _c = this.versionHeader(tokens), qasmNode = _c[0], consumed = _c[1];
|
|
138
|
+
return [[qasmNode], consumed];
|
|
139
|
+
}
|
|
140
|
+
case token_1.Token.Const: {
|
|
141
|
+
var _d = this.classicalDeclaration(tokens.slice(1), true), constNode = _d[0], consumed = _d[1];
|
|
142
|
+
return [[constNode], consumed + 1];
|
|
143
|
+
}
|
|
144
|
+
case token_1.Token.Input:
|
|
145
|
+
case token_1.Token.Output: {
|
|
146
|
+
var _e = this.ioType(tokens), ioType = _e[0], consumed = _e[1];
|
|
147
|
+
return [[ioType], consumed];
|
|
148
|
+
}
|
|
149
|
+
case token_1.Token.Float:
|
|
150
|
+
case token_1.Token.Int:
|
|
151
|
+
case token_1.Token.UInt:
|
|
152
|
+
case token_1.Token.Bool:
|
|
153
|
+
case token_1.Token.Angle:
|
|
154
|
+
case token_1.Token.Stretch:
|
|
155
|
+
case token_1.Token.Complex:
|
|
156
|
+
case token_1.Token.Duration: {
|
|
157
|
+
var _f = this.classicalDeclaration(tokens, false), classicalNode = _f[0], consumed = _f[1];
|
|
158
|
+
return [[classicalNode], consumed];
|
|
159
|
+
}
|
|
160
|
+
case token_1.Token.Qubit:
|
|
161
|
+
case token_1.Token.QReg: {
|
|
162
|
+
var _g = this.quantumDeclaration(tokens), qregNode = _g[0], qregConsumed = _g[1];
|
|
163
|
+
return [[qregNode], qregConsumed];
|
|
164
|
+
}
|
|
165
|
+
case token_1.Token.Break:
|
|
166
|
+
return [[new ast_1.BreakStatement()], 1];
|
|
167
|
+
case token_1.Token.Reset: {
|
|
168
|
+
var _h = this.resetStatement(tokens), resetNode = _h[0], resetConsumed = _h[1];
|
|
169
|
+
return [[resetNode], resetConsumed];
|
|
170
|
+
}
|
|
171
|
+
case token_1.Token.Continue:
|
|
172
|
+
return [[new ast_1.ContinueStatement()], 1];
|
|
173
|
+
case token_1.Token.Let: {
|
|
174
|
+
var _j = this.aliasStatement(tokens), letNode = _j[0], letConsumed = _j[1];
|
|
175
|
+
return [[letNode], letConsumed];
|
|
176
|
+
}
|
|
177
|
+
case token_1.Token.Bit:
|
|
178
|
+
if (this.isMeasurement(tokens.slice(1))) {
|
|
179
|
+
var _k = this.measureStatement(tokens), measureNode = _k[0], measureConsumed = _k[1];
|
|
180
|
+
return [[measureNode], measureConsumed];
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
var _l = this.classicalDeclaration(tokens, false), classicalNode = _l[0], consumed = _l[1];
|
|
184
|
+
return [[classicalNode], consumed];
|
|
185
|
+
}
|
|
186
|
+
case token_1.Token.CReg: {
|
|
187
|
+
var _m = this.classicalDeclaration(tokens, false), classicalNode = _m[0], consumed = _m[1];
|
|
188
|
+
return [[classicalNode], consumed];
|
|
189
|
+
}
|
|
190
|
+
case token_1.Token.Measure: {
|
|
191
|
+
var _o = this.measureStatement(tokens), measureNode = _o[0], measureConsumed = _o[1];
|
|
192
|
+
return [[measureNode], measureConsumed];
|
|
193
|
+
}
|
|
194
|
+
case token_1.Token.Gate: {
|
|
195
|
+
var _p = this.quantumGateDefinition(tokens), gateNode = _p[0], gateConsumed = _p[1];
|
|
196
|
+
this.customGates.add(gateNode.name.name);
|
|
197
|
+
return [[gateNode], gateConsumed];
|
|
198
|
+
}
|
|
199
|
+
case token_1.Token.Return: {
|
|
200
|
+
var _q = this.returnStatement(tokens), returnNode = _q[0], returnConsumed = _q[1];
|
|
201
|
+
return [[returnNode], returnConsumed];
|
|
202
|
+
}
|
|
203
|
+
case token_1.Token.Def: {
|
|
204
|
+
var _r = this.subroutineDefinition(tokens), subroutineNode = _r[0], subroutineConsumed = _r[1];
|
|
205
|
+
this.subroutines.add(subroutineNode.name.name);
|
|
206
|
+
return [[subroutineNode], subroutineConsumed];
|
|
207
|
+
}
|
|
208
|
+
case token_1.Token.Extern: {
|
|
209
|
+
var _s = this.externSignature(tokens), externNode = _s[0], consumed = _s[1];
|
|
210
|
+
this.subroutines.add(externNode.name.name);
|
|
211
|
+
return [[externNode], consumed];
|
|
212
|
+
}
|
|
213
|
+
case token_1.Token.Ctrl:
|
|
214
|
+
case token_1.Token.NegCtrl:
|
|
215
|
+
case token_1.Token.Inv:
|
|
216
|
+
case token_1.Token.PowM: {
|
|
217
|
+
var _t = this.quantumGateCall(tokens), gateCallNode = _t[0], gateCallConsumed = _t[1];
|
|
218
|
+
return [[gateCallNode], gateCallConsumed];
|
|
219
|
+
}
|
|
220
|
+
case token_1.Token.Ceiling:
|
|
221
|
+
case token_1.Token.Exp:
|
|
222
|
+
case token_1.Token.Floor:
|
|
223
|
+
case token_1.Token.Log:
|
|
224
|
+
case token_1.Token.Mod:
|
|
225
|
+
case token_1.Token.Popcount:
|
|
226
|
+
case token_1.Token.Pow:
|
|
227
|
+
case token_1.Token.Sqrt:
|
|
228
|
+
case token_1.Token.Rotr:
|
|
229
|
+
case token_1.Token.Rotl: {
|
|
230
|
+
var _u = this.binaryExpression(tokens.slice(1)), expr = _u[0], exprConsumed = _u[1];
|
|
231
|
+
var consumed = exprConsumed + 1;
|
|
232
|
+
var _v = this.createMathOrTrigFunction(token[0], expr), math = _v[0], mathConsumed = _v[1];
|
|
233
|
+
consumed += mathConsumed;
|
|
234
|
+
return [[math], consumed];
|
|
235
|
+
}
|
|
236
|
+
case token_1.Token.Opaque: {
|
|
237
|
+
var consumed = 1;
|
|
238
|
+
while (consumed < this.tokens.length &&
|
|
239
|
+
!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
240
|
+
consumed++;
|
|
241
|
+
}
|
|
242
|
+
return [[], consumed];
|
|
243
|
+
}
|
|
244
|
+
case token_1.Token.DurationOf: {
|
|
245
|
+
var _w = this.durationOf(tokens), durationOfNOde = _w[0], consumed = _w[1];
|
|
246
|
+
return [[durationOfNOde], consumed];
|
|
247
|
+
}
|
|
248
|
+
case token_1.Token.SizeOf: {
|
|
249
|
+
var _x = this.sizeOf(tokens), sizeOfNode = _x[0], consumed = _x[1];
|
|
250
|
+
return [[sizeOfNode], consumed];
|
|
251
|
+
}
|
|
252
|
+
case token_1.Token.Delay: {
|
|
253
|
+
var _y = this.delay(tokens), delayNode = _y[0], delayConsumed = _y[1];
|
|
254
|
+
return [[delayNode], delayConsumed];
|
|
255
|
+
}
|
|
256
|
+
case token_1.Token.If: {
|
|
257
|
+
var _z = this.ifStatement(tokens), ifNode = _z[0], ifConsumed = _z[1];
|
|
258
|
+
return [[ifNode], ifConsumed];
|
|
259
|
+
}
|
|
260
|
+
case token_1.Token.For: {
|
|
261
|
+
var _0 = this.forLoopStatement(tokens), forNode = _0[0], forConsumed = _0[1];
|
|
262
|
+
return [[forNode], forConsumed];
|
|
263
|
+
}
|
|
264
|
+
case token_1.Token.While: {
|
|
265
|
+
var _1 = this.whileLoopStatement(tokens), whileNode = _1[0], whileConsumed = _1[1];
|
|
266
|
+
return [[whileNode], whileConsumed];
|
|
267
|
+
}
|
|
268
|
+
case token_1.Token.Switch: {
|
|
269
|
+
var _2 = this.switchStatement(tokens), switchNode = _2[0], switchConsumed = _2[1];
|
|
270
|
+
return [[switchNode], switchConsumed];
|
|
271
|
+
}
|
|
272
|
+
case token_1.Token.Array: {
|
|
273
|
+
var _3 = this.arrayDeclaration(tokens), arrayNode = _3[0], arrayConsumed = _3[1];
|
|
274
|
+
this.customArrays.add(arrayNode.identifier.name);
|
|
275
|
+
return [[arrayNode], arrayConsumed];
|
|
276
|
+
}
|
|
277
|
+
case token_1.Token.Box: {
|
|
278
|
+
var _4 = this.box(tokens), boxNode = _4[0], boxConsumed = _4[1];
|
|
279
|
+
return [[boxNode], boxConsumed];
|
|
280
|
+
}
|
|
281
|
+
case token_1.Token.Barrier: {
|
|
282
|
+
var _5 = this.barrier(tokens), barrierNode = _5[0], barrierConsumed = _5[1];
|
|
283
|
+
return [[barrierNode], barrierConsumed];
|
|
284
|
+
}
|
|
285
|
+
case token_1.Token.Id:
|
|
286
|
+
if (this.isQuantumGateCall(tokens)) {
|
|
287
|
+
var _6 = this.quantumGateCall(tokens), gateCallNode = _6[0], gateCallConsumed = _6[1];
|
|
288
|
+
return [[gateCallNode], gateCallConsumed];
|
|
289
|
+
}
|
|
290
|
+
else if (this.isSubroutineCall(tokens)) {
|
|
291
|
+
var _7 = this.subroutineCall(tokens), subroutineCallNode = _7[0], subroutineCallConsumed = _7[1];
|
|
292
|
+
return [[subroutineCallNode], subroutineCallConsumed];
|
|
293
|
+
}
|
|
294
|
+
else if (this.isMeasurement(tokens)) {
|
|
295
|
+
var _8 = this.measureStatement(tokens), measureNode = _8[0], measureConsumed = _8[1];
|
|
296
|
+
return [[measureNode], measureConsumed];
|
|
297
|
+
}
|
|
298
|
+
else if (this.matchNext(tokens.slice(1), [token_1.Token.EqualsAssmt]) ||
|
|
299
|
+
this.matchNext(tokens.slice(1), [token_1.Token.CompoundArithmeticOp]) ||
|
|
300
|
+
this.matchNext(tokens.slice(1), [token_1.Token.CompoundBinaryOp]) ||
|
|
301
|
+
this.isAssignment(tokens)) {
|
|
302
|
+
var _9 = this.assignment(tokens), assignmentNode = _9[0], consumed = _9[1];
|
|
303
|
+
return [[assignmentNode], consumed];
|
|
304
|
+
}
|
|
305
|
+
else if (allowVariables) {
|
|
306
|
+
var _10 = this.binaryExpression(tokens), expr = _10[0], consumed = _10[1];
|
|
307
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
308
|
+
return [[expr], consumed + 1];
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
throwParserError(errors_1.MissingSemicolonError, tokens[consumed], this.index + consumed, "expected semicolon");
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
break;
|
|
315
|
+
default:
|
|
316
|
+
return [[], 1];
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
/**
|
|
320
|
+
* Checks if the next tokens match those expected.
|
|
321
|
+
* @param tokens - Remaining tokens to parse.
|
|
322
|
+
* @param expectedTokens - Expected tokens.
|
|
323
|
+
* @return Whether these is a match.
|
|
324
|
+
*/
|
|
325
|
+
Parser.prototype.matchNext = function (tokens, expectedTokens) {
|
|
326
|
+
var matches = true;
|
|
327
|
+
var i = 0;
|
|
328
|
+
if (tokens.length == 0) {
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
while (i < expectedTokens.length) {
|
|
332
|
+
if (tokens[i][0] != expectedTokens[i]) {
|
|
333
|
+
matches = false;
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
i++;
|
|
337
|
+
}
|
|
338
|
+
return matches;
|
|
339
|
+
};
|
|
340
|
+
/**
|
|
341
|
+
* Parses a `defcalgrammar` declaration.
|
|
342
|
+
*
|
|
343
|
+
* calibrationGrammarStatement:
|
|
344
|
+
* DEFCALGRAMMAR StringLiteral SEMICOLON
|
|
345
|
+
*
|
|
346
|
+
* @param tokens - Remaining tokens to parse.
|
|
347
|
+
* @return The parsed CalibrationGrammarDeclaration AstNode node and the number of consumed tokens.
|
|
348
|
+
*/
|
|
349
|
+
Parser.prototype.defcalGrammarDeclaration = function (tokens) {
|
|
350
|
+
var consumed = 1;
|
|
351
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.String, token_1.Token.Semicolon])) {
|
|
352
|
+
return [
|
|
353
|
+
new ast_1.CalibrationGrammarDeclaration(tokens[0][1].toString()),
|
|
354
|
+
consumed + 2,
|
|
355
|
+
];
|
|
356
|
+
}
|
|
357
|
+
throwParserError(errors_1.BadStringLiteralError, tokens[consumed], this.index + consumed, "expected string literal following `defcalgrammar` keyword");
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* Parses a classical type declaration.
|
|
361
|
+
* @param tokens - Remaining tokens to parse.
|
|
362
|
+
* @param isConst - Whether the declaration is for a constant, defaults to False.
|
|
363
|
+
* @return The parsed ClassicalDeclaration AstNode and the number of consumed tokens.
|
|
364
|
+
*/
|
|
365
|
+
Parser.prototype.classicalDeclaration = function (tokens, isConst) {
|
|
366
|
+
var isConstParam = isConst ? isConst : false;
|
|
367
|
+
var id = null;
|
|
368
|
+
var initialValue;
|
|
369
|
+
var consumed = 0;
|
|
370
|
+
var _a = this.parseClassicalType(tokens), classicalType = _a[0], classicalTypeConsumed = _a[1];
|
|
371
|
+
consumed += classicalTypeConsumed;
|
|
372
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen]) &&
|
|
373
|
+
!this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
374
|
+
var _b = this.unaryExpression(tokens.slice(consumed)), identifier = _b[0], idConsumed = _b[1];
|
|
375
|
+
id = identifier;
|
|
376
|
+
consumed += idConsumed;
|
|
377
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.EqualsAssmt])) {
|
|
378
|
+
consumed++;
|
|
379
|
+
var _c = this.binaryExpression(tokens.slice(consumed)), value = _c[0], valueConsumed = _c[1];
|
|
380
|
+
initialValue = value;
|
|
381
|
+
consumed += valueConsumed;
|
|
382
|
+
}
|
|
383
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
384
|
+
consumed++;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return [
|
|
388
|
+
new ast_1.ClassicalDeclaration(classicalType, id, initialValue, isConstParam),
|
|
389
|
+
consumed,
|
|
390
|
+
];
|
|
391
|
+
};
|
|
392
|
+
/**
|
|
393
|
+
* Parses an IO declaration statement.
|
|
394
|
+
* @param tokens - Remaining tokens to parse.
|
|
395
|
+
* @return A tuple containing the parsed IODeclaration and the number of tokens consumed.
|
|
396
|
+
*/
|
|
397
|
+
Parser.prototype.ioType = function (tokens) {
|
|
398
|
+
var consumed = 0;
|
|
399
|
+
var modifier;
|
|
400
|
+
switch (tokens[consumed][0]) {
|
|
401
|
+
case token_1.Token.Input:
|
|
402
|
+
modifier = ast_1.IOModifier.INPUT;
|
|
403
|
+
break;
|
|
404
|
+
case token_1.Token.Output:
|
|
405
|
+
modifier = ast_1.IOModifier.OUTPUT;
|
|
406
|
+
break;
|
|
407
|
+
default:
|
|
408
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "unsupported IO modifier");
|
|
409
|
+
}
|
|
410
|
+
consumed++;
|
|
411
|
+
var _a = this.classicalDeclaration(tokens.slice(consumed)), classicalDeclaration = _a[0], typeConsumed = _a[1];
|
|
412
|
+
consumed += typeConsumed;
|
|
413
|
+
return [new ast_1.IODeclaration(modifier, classicalDeclaration), consumed];
|
|
414
|
+
};
|
|
415
|
+
/**
|
|
416
|
+
* Parses a unary expression.
|
|
417
|
+
* @param tokens - Remaining tokens to parse.
|
|
418
|
+
* @return A tuple containing the parsed Expression and the number of tokens consumed.
|
|
419
|
+
*/
|
|
420
|
+
Parser.prototype.unaryExpression = function (tokens) {
|
|
421
|
+
var token = tokens[0];
|
|
422
|
+
var consumed = 1;
|
|
423
|
+
switch (token[0]) {
|
|
424
|
+
case token_1.Token.NNInteger: {
|
|
425
|
+
if (this.isImaginary(tokens[consumed])) {
|
|
426
|
+
return [
|
|
427
|
+
new ast_1.ImaginaryLiteral("".concat(token[1].toString(), "im")),
|
|
428
|
+
consumed + 1,
|
|
429
|
+
];
|
|
430
|
+
}
|
|
431
|
+
else if (this.isDuration(tokens.slice(consumed))) {
|
|
432
|
+
return [
|
|
433
|
+
new ast_1.DurationLiteral(Number(token[1]), tokens[consumed][1].toString()),
|
|
434
|
+
consumed + 1,
|
|
435
|
+
];
|
|
436
|
+
}
|
|
437
|
+
return [new ast_1.IntegerLiteral(Number(token[1])), consumed];
|
|
438
|
+
}
|
|
439
|
+
case token_1.Token.Integer: {
|
|
440
|
+
if (this.isImaginary(tokens[consumed])) {
|
|
441
|
+
return [
|
|
442
|
+
new ast_1.ImaginaryLiteral("".concat(token[1].toString(), "im")),
|
|
443
|
+
consumed + 1,
|
|
444
|
+
];
|
|
445
|
+
}
|
|
446
|
+
return [new ast_1.IntegerLiteral(token[1].toString()), consumed];
|
|
447
|
+
}
|
|
448
|
+
case token_1.Token.BinaryLiteral:
|
|
449
|
+
case token_1.Token.OctalLiteral:
|
|
450
|
+
case token_1.Token.HexLiteral:
|
|
451
|
+
case token_1.Token.ScientificNotation:
|
|
452
|
+
return [new ast_1.NumericLiteral(token[1].toString()), consumed];
|
|
453
|
+
case token_1.Token.Real:
|
|
454
|
+
if (this.isImaginary(tokens[consumed])) {
|
|
455
|
+
return [
|
|
456
|
+
new ast_1.ImaginaryLiteral("".concat(token[1].toString(), "im")),
|
|
457
|
+
consumed + 1,
|
|
458
|
+
];
|
|
459
|
+
}
|
|
460
|
+
return [new ast_1.FloatLiteral(Number(token[1])), consumed];
|
|
461
|
+
case token_1.Token.BoolLiteral:
|
|
462
|
+
return [new ast_1.BooleanLiteral(token[1] === "true"), consumed];
|
|
463
|
+
case token_1.Token.Arccos:
|
|
464
|
+
case token_1.Token.Arcsin:
|
|
465
|
+
case token_1.Token.Arctan:
|
|
466
|
+
case token_1.Token.Cos:
|
|
467
|
+
case token_1.Token.Sin:
|
|
468
|
+
case token_1.Token.Tan:
|
|
469
|
+
case token_1.Token.Ceiling:
|
|
470
|
+
case token_1.Token.Exp:
|
|
471
|
+
case token_1.Token.Floor:
|
|
472
|
+
case token_1.Token.Log:
|
|
473
|
+
case token_1.Token.Mod:
|
|
474
|
+
case token_1.Token.Popcount:
|
|
475
|
+
case token_1.Token.Pow:
|
|
476
|
+
case token_1.Token.Sqrt:
|
|
477
|
+
case token_1.Token.Rotr:
|
|
478
|
+
case token_1.Token.Rotl: {
|
|
479
|
+
var _a = this.unaryExpression(tokens.slice(1)), funcExpr = _a[0], funcConsumed = _a[1];
|
|
480
|
+
consumed += funcConsumed;
|
|
481
|
+
return [
|
|
482
|
+
this.createMathOrTrigFunction(tokens[0][0], funcExpr),
|
|
483
|
+
consumed,
|
|
484
|
+
];
|
|
485
|
+
}
|
|
486
|
+
case token_1.Token.Id:
|
|
487
|
+
// Handle array identifiers, identifiers, and subscripted identifiers
|
|
488
|
+
if (this.matchNext(tokens.slice(1), [token_1.Token.LSParen])) {
|
|
489
|
+
if (this.isArray(tokens)) {
|
|
490
|
+
var _b = this.parseArrayAccess(tokens), arrayAccess = _b[0], arrayAccessConsumed = _b[1];
|
|
491
|
+
return [arrayAccess, arrayAccessConsumed];
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
var identifier = new ast_1.Identifier(token[1].toString());
|
|
495
|
+
var _c = this.parseSubscript(tokens.slice(1)), subscript = _c[0], subscriptConsumed = _c[1];
|
|
496
|
+
consumed += subscriptConsumed;
|
|
497
|
+
return [
|
|
498
|
+
new ast_1.SubscriptedIdentifier(identifier.name, subscript),
|
|
499
|
+
consumed,
|
|
500
|
+
];
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return [new ast_1.Identifier(token[1].toString()), consumed];
|
|
504
|
+
case token_1.Token.Pi:
|
|
505
|
+
return [new ast_1.Pi(), consumed];
|
|
506
|
+
case token_1.Token.Euler:
|
|
507
|
+
return [new ast_1.Euler(), consumed];
|
|
508
|
+
case token_1.Token.Tau:
|
|
509
|
+
return [new ast_1.Tau(), consumed];
|
|
510
|
+
case token_1.Token.String:
|
|
511
|
+
return [new ast_1.BitstringLiteral(token[1].toString()), consumed];
|
|
512
|
+
case token_1.Token.DurationOf:
|
|
513
|
+
return this.durationOf(tokens);
|
|
514
|
+
case token_1.Token.SizeOf:
|
|
515
|
+
return this.sizeOf(tokens);
|
|
516
|
+
case token_1.Token.UnaryOp: {
|
|
517
|
+
var _d = this.unaryExpression(tokens.slice(1)), expr = _d[0], exprConsumed = _d[1];
|
|
518
|
+
return [new ast_1.Unary(token[1], expr), consumed + exprConsumed];
|
|
519
|
+
}
|
|
520
|
+
case token_1.Token.LParen: {
|
|
521
|
+
var i = 1;
|
|
522
|
+
var parenCount = 1;
|
|
523
|
+
while (parenCount > 0 && i < tokens.length) {
|
|
524
|
+
if (tokens[i][0] === token_1.Token.LParen) {
|
|
525
|
+
parenCount++;
|
|
526
|
+
}
|
|
527
|
+
else if (tokens[i][0] === token_1.Token.RParen) {
|
|
528
|
+
parenCount--;
|
|
529
|
+
}
|
|
530
|
+
else if (parenCount === 1 && tokens[i][0] === token_1.Token.Comma) {
|
|
531
|
+
return this.parseParameters(tokens);
|
|
532
|
+
}
|
|
533
|
+
i++;
|
|
534
|
+
}
|
|
535
|
+
var _e = this.binaryExpression(tokens.slice(1)), expr = _e[0], exprConsumed = _e[1];
|
|
536
|
+
consumed += exprConsumed;
|
|
537
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
538
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing parenthesis");
|
|
539
|
+
}
|
|
540
|
+
consumed++;
|
|
541
|
+
return [expr, consumed];
|
|
542
|
+
}
|
|
543
|
+
default:
|
|
544
|
+
if (isTypeToken(token[0])) {
|
|
545
|
+
return this.parseTypeCast(tokens);
|
|
546
|
+
}
|
|
547
|
+
throwParserError(errors_1.BadExpressionError, token, this.index, "invalid expression");
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
/**
|
|
551
|
+
* Parses a binary expression.
|
|
552
|
+
* @param tokens - Remaining tokens to parse.
|
|
553
|
+
* @return A tuple containing the parsed Expression and the number of tokens consumed.
|
|
554
|
+
*/
|
|
555
|
+
Parser.prototype.binaryExpression = function (tokens) {
|
|
556
|
+
var unaryExpr = this.unaryExpression(tokens);
|
|
557
|
+
var leftExpr = unaryExpr[0];
|
|
558
|
+
var leftConsumed = unaryExpr[1];
|
|
559
|
+
var consumed = leftConsumed;
|
|
560
|
+
while (consumed < tokens.length) {
|
|
561
|
+
var token = tokens[consumed];
|
|
562
|
+
if (token[0] === token_1.Token.BinaryOp ||
|
|
563
|
+
token[0] === token_1.Token.ArithmeticOp ||
|
|
564
|
+
(token[0] === token_1.Token.UnaryOp && token[1] === "-")) {
|
|
565
|
+
consumed++;
|
|
566
|
+
var _a = this.unaryExpression(tokens.slice(consumed)), rightExpr = _a[0], rightConsumed = _a[1];
|
|
567
|
+
if (token[0] === token_1.Token.BinaryOp) {
|
|
568
|
+
leftExpr = new ast_1.Binary(token[1], leftExpr, rightExpr);
|
|
569
|
+
}
|
|
570
|
+
else if (token[0] === token_1.Token.UnaryOp && token[1] === "-") {
|
|
571
|
+
leftExpr = new ast_1.Arithmetic(ast_1.ArithmeticOp.MINUS, leftExpr, rightExpr);
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
leftExpr = new ast_1.Arithmetic(token[1], leftExpr, rightExpr);
|
|
575
|
+
}
|
|
576
|
+
consumed += rightConsumed;
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
break;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
return [leftExpr, consumed];
|
|
583
|
+
};
|
|
584
|
+
/**
|
|
585
|
+
* Parses an assignment statement.
|
|
586
|
+
* @param tokens - Remaining tokens to parse.
|
|
587
|
+
* @return The parsed AssignmentStatement AstNode and the number of consumed tokens.
|
|
588
|
+
*/
|
|
589
|
+
Parser.prototype.assignment = function (tokens) {
|
|
590
|
+
var consumed = 0;
|
|
591
|
+
var _a = this.unaryExpression(tokens), lhs = _a[0], lhsConsumed = _a[1];
|
|
592
|
+
consumed += lhsConsumed;
|
|
593
|
+
// Handle compound assignments
|
|
594
|
+
var operatorToken = tokens[consumed][0];
|
|
595
|
+
if (operatorToken === token_1.Token.CompoundArithmeticOp ||
|
|
596
|
+
operatorToken === token_1.Token.CompoundBinaryOp) {
|
|
597
|
+
consumed++;
|
|
598
|
+
var operator = tokens[lhsConsumed][1].toString();
|
|
599
|
+
var _b = this.binaryExpression(tokens.slice(consumed)), rhs_1 = _b[0], rhsConsumed = _b[1];
|
|
600
|
+
consumed += rhsConsumed;
|
|
601
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
602
|
+
throwParserError(errors_1.MissingSemicolonError, tokens[consumed], this.index + consumed, "expected semicolon");
|
|
603
|
+
}
|
|
604
|
+
consumed++;
|
|
605
|
+
var op = void 0;
|
|
606
|
+
var expression = void 0;
|
|
607
|
+
switch (operatorToken) {
|
|
608
|
+
case token_1.Token.CompoundArithmeticOp:
|
|
609
|
+
op = operator.slice(0, -1);
|
|
610
|
+
expression = new ast_1.Arithmetic(op, lhs, rhs_1);
|
|
611
|
+
break;
|
|
612
|
+
case token_1.Token.CompoundBinaryOp:
|
|
613
|
+
op = operator.slice(0, -1);
|
|
614
|
+
expression = new ast_1.Binary(op, lhs, rhs_1);
|
|
615
|
+
break;
|
|
616
|
+
default:
|
|
617
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "invalid compound operator");
|
|
618
|
+
}
|
|
619
|
+
return [
|
|
620
|
+
new ast_1.AssignmentStatement(lhs, expression),
|
|
621
|
+
consumed,
|
|
622
|
+
];
|
|
623
|
+
}
|
|
624
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.EqualsAssmt])) {
|
|
625
|
+
consumed++;
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected `=` in assignment statement");
|
|
629
|
+
}
|
|
630
|
+
var rhs;
|
|
631
|
+
if (this.isSubroutineCall(tokens.slice(consumed))) {
|
|
632
|
+
var _c = this.subroutineCall(tokens.slice(consumed)), subroutineCall = _c[0], subroutineCallConsumed = _c[1];
|
|
633
|
+
rhs = subroutineCall;
|
|
634
|
+
consumed += subroutineCallConsumed;
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
var _d = this.binaryExpression(tokens.slice(consumed)), rhsExpression = _d[0], rhsConsumed = _d[1];
|
|
638
|
+
rhs = rhsExpression;
|
|
639
|
+
consumed += rhsConsumed;
|
|
640
|
+
}
|
|
641
|
+
// if (!this.matchNext(tokens.slice(consumed), [Token.Semicolon])) {
|
|
642
|
+
// throwParserError(
|
|
643
|
+
// MissingSemicolonError,
|
|
644
|
+
// tokens[consumed],
|
|
645
|
+
// this.index + consumed,
|
|
646
|
+
// "expected semicolon",
|
|
647
|
+
// );
|
|
648
|
+
// }
|
|
649
|
+
// consumed++;
|
|
650
|
+
return [
|
|
651
|
+
new ast_1.AssignmentStatement(lhs, rhs),
|
|
652
|
+
consumed,
|
|
653
|
+
];
|
|
654
|
+
};
|
|
655
|
+
/**
|
|
656
|
+
* Parses a quantum declaration.
|
|
657
|
+
* @param tokens - Tokens to parse.
|
|
658
|
+
* @return A QuantumDeclaration node and the number of tokens consumed.
|
|
659
|
+
*/
|
|
660
|
+
Parser.prototype.quantumDeclaration = function (tokens) {
|
|
661
|
+
var consumed = 1;
|
|
662
|
+
var isQubit = tokens[0][0] === token_1.Token.Qubit;
|
|
663
|
+
var size = null;
|
|
664
|
+
// Qubit
|
|
665
|
+
if (isQubit) {
|
|
666
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LSParen])) {
|
|
667
|
+
consumed++;
|
|
668
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), sizeExpr = _a[0], sizeConsumed = _a[1];
|
|
669
|
+
consumed += sizeConsumed;
|
|
670
|
+
size = sizeExpr;
|
|
671
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
672
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing bracket ] for qubit declaration size");
|
|
673
|
+
}
|
|
674
|
+
consumed++;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
678
|
+
throwParserError(errors_1.BadQregError, tokens[consumed], this.index + consumed, "expected identifier for quantum declaration");
|
|
679
|
+
}
|
|
680
|
+
var _b = this.unaryExpression(tokens.slice(consumed, consumed + 1)), identifier = _b[0], idConsumed = _b[1];
|
|
681
|
+
consumed += idConsumed;
|
|
682
|
+
// Qreg
|
|
683
|
+
if (!isQubit && this.matchNext(tokens.slice(consumed), [token_1.Token.LSParen])) {
|
|
684
|
+
consumed++;
|
|
685
|
+
var _c = this.binaryExpression(tokens.slice(consumed)), sizeExpr = _c[0], sizeConsumed = _c[1];
|
|
686
|
+
size = sizeExpr;
|
|
687
|
+
consumed += sizeConsumed;
|
|
688
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
689
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing bracket ] for quantum register size");
|
|
690
|
+
}
|
|
691
|
+
consumed++;
|
|
692
|
+
}
|
|
693
|
+
if (!(this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon]) ||
|
|
694
|
+
this.matchNext(tokens.slice(consumed), [token_1.Token.Comma]) ||
|
|
695
|
+
this.matchNext(tokens.slice(consumed), [token_1.Token.RParen]))) {
|
|
696
|
+
throwParserError(errors_1.BadQregError, tokens[consumed], this.index + consumed, "expected semicolon, comma, or closing parenthesis after quantum register declaration");
|
|
697
|
+
}
|
|
698
|
+
// Only consume semicolon, if paren or comma that token will be handled in calling function
|
|
699
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
700
|
+
consumed++;
|
|
701
|
+
}
|
|
702
|
+
return [new ast_1.QuantumDeclaration(identifier, size), consumed];
|
|
703
|
+
};
|
|
704
|
+
/**
|
|
705
|
+
* Parses a measure statement.
|
|
706
|
+
* @param tokens - Remaining tokens to parse.
|
|
707
|
+
* @return A tuple containing the QuantumMeasurementAssignment or QuantumMeasurement and the number of tokens consumed.
|
|
708
|
+
*/
|
|
709
|
+
Parser.prototype.measureStatement = function (tokens) {
|
|
710
|
+
var consumed = 0;
|
|
711
|
+
// Legacy syntax: measure qubit|qubit[] -> bit|bit[];
|
|
712
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Measure])) {
|
|
713
|
+
consumed++;
|
|
714
|
+
var qubitIdentifiers = [];
|
|
715
|
+
while (!(this.matchNext(tokens.slice(consumed), [token_1.Token.Arrow]) ||
|
|
716
|
+
this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon]))) {
|
|
717
|
+
var _a = this.unaryExpression(tokens.slice(consumed)), identifier = _a[0], idConsumed = _a[1];
|
|
718
|
+
qubitIdentifiers.push(identifier);
|
|
719
|
+
consumed += idConsumed;
|
|
720
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
721
|
+
consumed++;
|
|
722
|
+
}
|
|
723
|
+
else if (!(this.matchNext(tokens.slice(consumed), [token_1.Token.Arrow]) ||
|
|
724
|
+
this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon]))) {
|
|
725
|
+
throwParserError(errors_1.BadMeasurementError, tokens[consumed], this.index + consumed, "expected comma or arrow in measurement statement");
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
var measurement = new ast_1.QuantumMeasurement(qubitIdentifiers);
|
|
729
|
+
// If there's an arrow, build a QuantumMeasurementAssignment
|
|
730
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Arrow])) {
|
|
731
|
+
consumed++;
|
|
732
|
+
var _b = this.unaryExpression(tokens.slice(consumed)), identifier = _b[0], idConsumed = _b[1];
|
|
733
|
+
var classicalBit = identifier;
|
|
734
|
+
consumed += idConsumed;
|
|
735
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
736
|
+
throwParserError(errors_1.MissingSemicolonError, tokens[consumed], this.index + consumed);
|
|
737
|
+
}
|
|
738
|
+
consumed++;
|
|
739
|
+
return [
|
|
740
|
+
new ast_1.QuantumMeasurementAssignment(classicalBit, measurement),
|
|
741
|
+
consumed,
|
|
742
|
+
];
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
746
|
+
throwParserError(errors_1.MissingSemicolonError, tokens[consumed], this.index + consumed);
|
|
747
|
+
}
|
|
748
|
+
consumed++;
|
|
749
|
+
return [measurement, consumed];
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
// New syntax: bit|bit[] = measure qubit|qreg;
|
|
753
|
+
else {
|
|
754
|
+
var _c = this.unaryExpression(tokens.slice(consumed)), leftIdentifier = _c[0], leftIdConsumed = _c[1];
|
|
755
|
+
var classicalBit = leftIdentifier;
|
|
756
|
+
consumed += leftIdConsumed;
|
|
757
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.EqualsAssmt])) {
|
|
758
|
+
throwParserError(errors_1.BadMeasurementError, tokens[consumed], this.index + consumed, "expected `=` in measurement assignment");
|
|
759
|
+
}
|
|
760
|
+
consumed++;
|
|
761
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Measure])) {
|
|
762
|
+
throwParserError(errors_1.BadMeasurementError, tokens[consumed], this.index + consumed, "expected `measure` keyword in measurement assignment");
|
|
763
|
+
}
|
|
764
|
+
consumed++;
|
|
765
|
+
var _d = this.unaryExpression(tokens.slice(consumed)), rightIdentifier = _d[0], rightIdConsumed = _d[1];
|
|
766
|
+
var qubitIdentifier = rightIdentifier;
|
|
767
|
+
consumed += rightIdConsumed;
|
|
768
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
769
|
+
throwParserError(errors_1.MissingSemicolonError, tokens[consumed], this.index + consumed);
|
|
770
|
+
}
|
|
771
|
+
consumed++;
|
|
772
|
+
var measurement = new ast_1.QuantumMeasurement([
|
|
773
|
+
qubitIdentifier,
|
|
774
|
+
]);
|
|
775
|
+
return [
|
|
776
|
+
new ast_1.QuantumMeasurementAssignment(classicalBit, measurement),
|
|
777
|
+
consumed,
|
|
778
|
+
];
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
/**
|
|
782
|
+
* Parses a subroutine return statement.
|
|
783
|
+
* @param tokens - Remaining tokens to parse.
|
|
784
|
+
* @return A tuple containing the SubroutineDefinition and the number of tokens consumed.
|
|
785
|
+
*/
|
|
786
|
+
Parser.prototype.returnStatement = function (tokens) {
|
|
787
|
+
var consumed = 1;
|
|
788
|
+
var expression = null;
|
|
789
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
790
|
+
var _a = this.parseNode(tokens.slice(consumed)), expr = _a[0], exprConsumed = _a[1];
|
|
791
|
+
expression = expr;
|
|
792
|
+
consumed += exprConsumed;
|
|
793
|
+
}
|
|
794
|
+
return [new ast_1.ReturnStatement(expression), consumed];
|
|
795
|
+
};
|
|
796
|
+
/**
|
|
797
|
+
* Parses an extern signature.
|
|
798
|
+
* @param tokens - Remaining tokens to parse.
|
|
799
|
+
* @return A tuple containing the ExternSignature and the number of tokens consumed.
|
|
800
|
+
*/
|
|
801
|
+
Parser.prototype.externSignature = function (tokens) {
|
|
802
|
+
var consumed = 1;
|
|
803
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
804
|
+
throwParserError(errors_1.BadSubroutineError, tokens[consumed], this.index + consumed, "expected identifier following extern keyword");
|
|
805
|
+
}
|
|
806
|
+
var _a = this.unaryExpression(tokens.slice(consumed)), identifier = _a[0], identifierConsumed = _a[1];
|
|
807
|
+
consumed += identifierConsumed;
|
|
808
|
+
var externParams = null;
|
|
809
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
810
|
+
var _b = this.parseParameters(tokens.slice(consumed)), params = _b[0], paramsConsumed = _b[1];
|
|
811
|
+
externParams = params;
|
|
812
|
+
consumed += paramsConsumed;
|
|
813
|
+
}
|
|
814
|
+
var returnType = null;
|
|
815
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Arrow])) {
|
|
816
|
+
consumed++;
|
|
817
|
+
var _c = this.parseClassicalType(tokens.slice(consumed)), type = _c[0], typeConsumed = _c[1];
|
|
818
|
+
returnType = type;
|
|
819
|
+
consumed += typeConsumed;
|
|
820
|
+
}
|
|
821
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
822
|
+
throwParserError(errors_1.MissingSemicolonError, tokens[consumed], this.index + consumed, "expected semicolon");
|
|
823
|
+
}
|
|
824
|
+
consumed++;
|
|
825
|
+
return [
|
|
826
|
+
new ast_1.ExternSignature(identifier, externParams, returnType),
|
|
827
|
+
consumed,
|
|
828
|
+
];
|
|
829
|
+
};
|
|
830
|
+
/**
|
|
831
|
+
* Parses a subroutine definition.
|
|
832
|
+
* @param tokens - Remaining tokens to parse.
|
|
833
|
+
* @return A tuple containing the SubroutineDefinition and the number of tokens consumed.
|
|
834
|
+
*/
|
|
835
|
+
Parser.prototype.subroutineDefinition = function (tokens) {
|
|
836
|
+
var consumed = 1;
|
|
837
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
838
|
+
throwParserError(errors_1.BadSubroutineError, tokens[consumed], this.index + consumed, "expected subroutine name");
|
|
839
|
+
}
|
|
840
|
+
var _a = this.unaryExpression(tokens.slice(consumed)), name = _a[0], nameConsumed = _a[1];
|
|
841
|
+
consumed += nameConsumed;
|
|
842
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
843
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening parenthesis for subroutine definition");
|
|
844
|
+
}
|
|
845
|
+
var _b = this.parseParameters(tokens.slice(consumed)), params = _b[0], paramsConsumed = _b[1];
|
|
846
|
+
consumed += paramsConsumed;
|
|
847
|
+
var returnType = null;
|
|
848
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Arrow])) {
|
|
849
|
+
consumed++;
|
|
850
|
+
var _c = this.parseClassicalType(tokens.slice(consumed)), type = _c[0], typeConsumed = _c[1];
|
|
851
|
+
returnType = type;
|
|
852
|
+
consumed += typeConsumed;
|
|
853
|
+
}
|
|
854
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
855
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening brace for subroutine body");
|
|
856
|
+
}
|
|
857
|
+
var _d = this.programBlock(tokens.slice(consumed)), body = _d[0], bodyConsumed = _d[1];
|
|
858
|
+
consumed += bodyConsumed;
|
|
859
|
+
return [
|
|
860
|
+
new ast_1.SubroutineDefinition(name, body, params, returnType),
|
|
861
|
+
consumed,
|
|
862
|
+
];
|
|
863
|
+
};
|
|
864
|
+
/**
|
|
865
|
+
* Parses a subroutine call.
|
|
866
|
+
* @param tokens - Remaining tokens to parse.
|
|
867
|
+
* @return A tuple containing the SubroutineCall and the number of tokens consumed.
|
|
868
|
+
*/
|
|
869
|
+
Parser.prototype.subroutineCall = function (tokens) {
|
|
870
|
+
var consumed = 0;
|
|
871
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
872
|
+
throwParserError(errors_1.BadSubroutineError, tokens[consumed], this.index + consumed, "expected subroutine name");
|
|
873
|
+
}
|
|
874
|
+
var _a = this.unaryExpression(tokens.slice(consumed)), subroutineName = _a[0], subroutineNameConsumed = _a[1];
|
|
875
|
+
consumed += subroutineNameConsumed;
|
|
876
|
+
var callParams = null;
|
|
877
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
878
|
+
var _b = this.parseParameters(tokens.slice(consumed)), params = _b[0], paramsConsumed = _b[1];
|
|
879
|
+
callParams = params;
|
|
880
|
+
consumed += paramsConsumed;
|
|
881
|
+
}
|
|
882
|
+
// if (!this.matchNext(tokens.slice(consumed), [Token.Semicolon])) {
|
|
883
|
+
// throwParserError(
|
|
884
|
+
// MissingSemicolonError,
|
|
885
|
+
// tokens[consumed],
|
|
886
|
+
// this.index + consumed,
|
|
887
|
+
// "expected semicolon after subroutine call",
|
|
888
|
+
// );
|
|
889
|
+
// }
|
|
890
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
891
|
+
consumed++;
|
|
892
|
+
}
|
|
893
|
+
return [
|
|
894
|
+
new ast_1.SubroutineCall(subroutineName, callParams),
|
|
895
|
+
consumed,
|
|
896
|
+
];
|
|
897
|
+
};
|
|
898
|
+
/**
|
|
899
|
+
* Parses a quantum gate definition.
|
|
900
|
+
* @param tokens - Remaining tokens to parse.
|
|
901
|
+
* @return A tuple containing the QuantumGateDefinition and the number of tokens consumed.
|
|
902
|
+
*/
|
|
903
|
+
Parser.prototype.quantumGateDefinition = function (tokens) {
|
|
904
|
+
var consumed = 1;
|
|
905
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
906
|
+
throwParserError(errors_1.BadGateError, tokens[consumed], this.index + consumed, "expected gate name");
|
|
907
|
+
}
|
|
908
|
+
var _a = this.unaryExpression(tokens.slice(consumed)), name = _a[0], nameConsumed = _a[1];
|
|
909
|
+
consumed += nameConsumed;
|
|
910
|
+
// Parse optional parameters
|
|
911
|
+
var _b = this.parseParameters(tokens.slice(consumed)), params = _b[0], paramsConsumed = _b[1];
|
|
912
|
+
consumed += paramsConsumed;
|
|
913
|
+
// Parse qubits
|
|
914
|
+
var qubits = [];
|
|
915
|
+
while (!this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
916
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
917
|
+
throwParserError(errors_1.BadGateError, tokens[consumed], this.index + consumed, "expected qubit argument");
|
|
918
|
+
}
|
|
919
|
+
var _c = this.unaryExpression(tokens.slice(consumed)), qubit = _c[0], qubitConsumed = _c[1];
|
|
920
|
+
qubits.push(qubit);
|
|
921
|
+
consumed += qubitConsumed;
|
|
922
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
923
|
+
consumed++;
|
|
924
|
+
}
|
|
925
|
+
else if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
926
|
+
throwParserError(errors_1.BadGateError, tokens[consumed], this.index + consumed, "expected comma or opening brace for gate body");
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
var _d = this.programBlock(tokens.slice(consumed)), body = _d[0], bodyConsumed = _d[1];
|
|
930
|
+
consumed += bodyConsumed;
|
|
931
|
+
return [
|
|
932
|
+
new ast_1.QuantumGateDefinition(name, params, qubits, body),
|
|
933
|
+
consumed,
|
|
934
|
+
];
|
|
935
|
+
};
|
|
936
|
+
/**
|
|
937
|
+
* Parses a quantum gate call.
|
|
938
|
+
* @param tokens - Remaining tokens to parse.
|
|
939
|
+
* @return A tuple containing the QuantumGateCall and the number of tokens consumed.
|
|
940
|
+
*/
|
|
941
|
+
Parser.prototype.quantumGateCall = function (tokens) {
|
|
942
|
+
var consumed = 0;
|
|
943
|
+
var modifiers = [];
|
|
944
|
+
// Parse modifier(s)
|
|
945
|
+
while (this.matchNext(tokens.slice(consumed), [token_1.Token.Ctrl]) ||
|
|
946
|
+
this.matchNext(tokens.slice(consumed), [token_1.Token.NegCtrl]) ||
|
|
947
|
+
this.matchNext(tokens.slice(consumed), [token_1.Token.Inv]) ||
|
|
948
|
+
this.matchNext(tokens.slice(consumed), [token_1.Token.PowM])) {
|
|
949
|
+
var _a = this.parseQuantumGateModifier(tokens.slice(consumed)), modifier = _a[0], modifierConsumed = _a[1];
|
|
950
|
+
modifiers.push(modifier);
|
|
951
|
+
consumed += modifierConsumed;
|
|
952
|
+
}
|
|
953
|
+
// Parse gate name
|
|
954
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
955
|
+
throwParserError(errors_1.BadGateError, tokens[consumed], this.index + consumed, "expected gate name");
|
|
956
|
+
}
|
|
957
|
+
var _b = this.unaryExpression(tokens.slice(consumed)), gateName = _b[0], gateNameConsumed = _b[1];
|
|
958
|
+
consumed += gateNameConsumed;
|
|
959
|
+
var callParams = null;
|
|
960
|
+
// Parse optional parameters
|
|
961
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
962
|
+
var _c = this.parseParameters(tokens.slice(consumed)), params = _c[0], paramsConsumed = _c[1];
|
|
963
|
+
callParams = params;
|
|
964
|
+
consumed += paramsConsumed;
|
|
965
|
+
}
|
|
966
|
+
// Parse qubit arguments
|
|
967
|
+
var _d = this.parseQubitList(tokens.slice(consumed)), qubits = _d[0], qubitsConsumed = _d[1];
|
|
968
|
+
consumed += qubitsConsumed;
|
|
969
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
970
|
+
throwParserError(errors_1.MissingSemicolonError, tokens[consumed], this.index + consumed, "expected semicolon");
|
|
971
|
+
}
|
|
972
|
+
consumed++;
|
|
973
|
+
return [
|
|
974
|
+
new ast_1.QuantumGateCall(gateName, qubits, callParams, modifiers),
|
|
975
|
+
consumed,
|
|
976
|
+
];
|
|
977
|
+
};
|
|
978
|
+
/**
|
|
979
|
+
* Parses a list of qubits.
|
|
980
|
+
* @param tokens - Remaining tokens to parse.
|
|
981
|
+
* @return A tuple containing the list of qubits and the number of tokens consumed.
|
|
982
|
+
*/
|
|
983
|
+
Parser.prototype.parseQubitList = function (tokens) {
|
|
984
|
+
var consumed = 0;
|
|
985
|
+
var qubits = [];
|
|
986
|
+
while (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
987
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Dollar, token_1.Token.NNInteger])) {
|
|
988
|
+
var _a = this.parseHardwareQubit(tokens.slice(consumed)), hardwareQubit = _a[0], hardwareQubitConsumed = _a[1];
|
|
989
|
+
qubits.push(hardwareQubit);
|
|
990
|
+
consumed += hardwareQubitConsumed;
|
|
991
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
992
|
+
consumed++;
|
|
993
|
+
}
|
|
994
|
+
continue;
|
|
995
|
+
}
|
|
996
|
+
else if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
997
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected qubit argument");
|
|
998
|
+
}
|
|
999
|
+
var _b = this.unaryExpression(tokens.slice(consumed)), qubit = _b[0], qubitConsumed = _b[1];
|
|
1000
|
+
qubits.push(qubit);
|
|
1001
|
+
consumed += qubitConsumed;
|
|
1002
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
1003
|
+
consumed++;
|
|
1004
|
+
}
|
|
1005
|
+
else if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
1006
|
+
break;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
return [qubits, consumed];
|
|
1010
|
+
};
|
|
1011
|
+
/**
|
|
1012
|
+
* Parses a hardware qubit.
|
|
1013
|
+
* @param tokens - Remaining tokens to parse.
|
|
1014
|
+
* @return A tuple containing the HardwareQubit and the number of tokens consumed.
|
|
1015
|
+
*/
|
|
1016
|
+
Parser.prototype.parseHardwareQubit = function (tokens) {
|
|
1017
|
+
var consumed = 0;
|
|
1018
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Dollar])) {
|
|
1019
|
+
throwParserError(errors_1.BadGateError, tokens[consumed], this.index + consumed, "expected dollar sign for hardware qubit");
|
|
1020
|
+
}
|
|
1021
|
+
consumed++;
|
|
1022
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.NNInteger])) {
|
|
1023
|
+
throwParserError(errors_1.BadGateError, tokens[consumed], this.index + consumed, "expected non-negative integer for hardware qubit");
|
|
1024
|
+
}
|
|
1025
|
+
return [new ast_1.HardwareQubit(Number(tokens[consumed][1])), consumed + 1];
|
|
1026
|
+
};
|
|
1027
|
+
/**
|
|
1028
|
+
* Parses a gate modifier.
|
|
1029
|
+
* @param tokens - Remaining tokens to parse.
|
|
1030
|
+
* @return A tuple containing the gate modifier and the number of tokens consumed.
|
|
1031
|
+
*/
|
|
1032
|
+
Parser.prototype.parseQuantumGateModifier = function (tokens) {
|
|
1033
|
+
var consumed = 1;
|
|
1034
|
+
var modifierToken = tokens[0][0];
|
|
1035
|
+
var modifier;
|
|
1036
|
+
var argument = null;
|
|
1037
|
+
switch (modifierToken) {
|
|
1038
|
+
case token_1.Token.Ctrl:
|
|
1039
|
+
modifier = ast_1.QuantumGateModifierName.CTRL;
|
|
1040
|
+
break;
|
|
1041
|
+
case token_1.Token.NegCtrl:
|
|
1042
|
+
modifier = ast_1.QuantumGateModifierName.NRGCTRL;
|
|
1043
|
+
break;
|
|
1044
|
+
case token_1.Token.Inv:
|
|
1045
|
+
modifier = ast_1.QuantumGateModifierName.INV;
|
|
1046
|
+
break;
|
|
1047
|
+
case token_1.Token.PowM:
|
|
1048
|
+
modifier = ast_1.QuantumGateModifierName.POW;
|
|
1049
|
+
break;
|
|
1050
|
+
default:
|
|
1051
|
+
throwParserError(errors_1.BadGateError, tokens[0], this.index, "invalid gate modifier");
|
|
1052
|
+
}
|
|
1053
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
1054
|
+
consumed++;
|
|
1055
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), arg = _a[0], argConsumed = _a[1];
|
|
1056
|
+
argument = arg;
|
|
1057
|
+
consumed += argConsumed;
|
|
1058
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
1059
|
+
throwParserError(errors_1.BadGateError, tokens[consumed], this.index + consumed, "expected closing parenthesis after gate modifier argument");
|
|
1060
|
+
}
|
|
1061
|
+
consumed++;
|
|
1062
|
+
}
|
|
1063
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.At])) {
|
|
1064
|
+
throwParserError(errors_1.BadGateError, tokens[consumed], this.index + consumed, "expected `@` symbol after gate modifier");
|
|
1065
|
+
}
|
|
1066
|
+
consumed++;
|
|
1067
|
+
return [new ast_1.QuantumGateModifier(modifier, argument), consumed];
|
|
1068
|
+
};
|
|
1069
|
+
/**
|
|
1070
|
+
* Parses a set of parameters.
|
|
1071
|
+
* @param tokens - Remaining tokens to parse.
|
|
1072
|
+
* @return A tuple containing the Parameters and the number of tokens consumed.
|
|
1073
|
+
*/
|
|
1074
|
+
Parser.prototype.parseParameters = function (tokens) {
|
|
1075
|
+
var consumed = 0;
|
|
1076
|
+
var args = [];
|
|
1077
|
+
if (this.matchNext(tokens, [token_1.Token.LParen])) {
|
|
1078
|
+
consumed++;
|
|
1079
|
+
while (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
1080
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Qubit])) {
|
|
1081
|
+
var _a = this.parseNode(tokens.slice(consumed)), qubitParam = _a[0], qubitConsumed = _a[1];
|
|
1082
|
+
args.push(qubitParam);
|
|
1083
|
+
consumed += qubitConsumed;
|
|
1084
|
+
}
|
|
1085
|
+
else if (this.matchNext(tokens.slice(consumed), [token_1.Token.Bit]) ||
|
|
1086
|
+
this.matchNext(tokens.slice(consumed), [token_1.Token.CReg])) {
|
|
1087
|
+
var _b = this.parseNode(tokens.slice(consumed)), bitParam = _b[0], bitConsumed = _b[1];
|
|
1088
|
+
args.push(bitParam);
|
|
1089
|
+
consumed += bitConsumed;
|
|
1090
|
+
}
|
|
1091
|
+
else if (isTypeToken(tokens[consumed][0])) {
|
|
1092
|
+
var _c = this.classicalDeclaration(tokens.slice(consumed)), param = _c[0], paramConsumed = _c[1];
|
|
1093
|
+
args.push(param);
|
|
1094
|
+
consumed += paramConsumed;
|
|
1095
|
+
}
|
|
1096
|
+
else if (this.matchNext(tokens.slice(consumed), [token_1.Token.ReadOnly]) ||
|
|
1097
|
+
this.matchNext(tokens.slice(consumed), [token_1.Token.Mutable])) {
|
|
1098
|
+
var _d = this.parseArrayReference(tokens.slice(consumed)), arrayRef = _d[0], arrayRefConsumed = _d[1];
|
|
1099
|
+
args.push(arrayRef);
|
|
1100
|
+
consumed += arrayRefConsumed;
|
|
1101
|
+
}
|
|
1102
|
+
else {
|
|
1103
|
+
var _e = this.binaryExpression(tokens.slice(consumed)), param = _e[0], paramConsumed = _e[1];
|
|
1104
|
+
args.push(param);
|
|
1105
|
+
consumed += paramConsumed;
|
|
1106
|
+
}
|
|
1107
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
1108
|
+
consumed++;
|
|
1109
|
+
}
|
|
1110
|
+
else if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
1111
|
+
throwParserError(errors_1.BadParameterError, tokens[consumed], this.index + consumed, "expected comma or closing parenthesis in parameter list");
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
consumed++;
|
|
1115
|
+
}
|
|
1116
|
+
return [new ast_1.Parameters(args), consumed];
|
|
1117
|
+
};
|
|
1118
|
+
/**
|
|
1119
|
+
* Parses an array reference.
|
|
1120
|
+
* @param tokens - Remaining tokens to parse.
|
|
1121
|
+
* @return A tuple containing the ArrayReference and the number of tokens consumed.
|
|
1122
|
+
*/
|
|
1123
|
+
Parser.prototype.parseArrayReference = function (tokens) {
|
|
1124
|
+
var consumed = 0;
|
|
1125
|
+
var modifier;
|
|
1126
|
+
switch (tokens[consumed][0]) {
|
|
1127
|
+
case token_1.Token.Mutable:
|
|
1128
|
+
modifier = ast_1.ArrayReferenceModifier.MUTABLE;
|
|
1129
|
+
break;
|
|
1130
|
+
case token_1.Token.ReadOnly:
|
|
1131
|
+
modifier = ast_1.ArrayReferenceModifier.READONLY;
|
|
1132
|
+
break;
|
|
1133
|
+
default:
|
|
1134
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "unsupported array reference modifier");
|
|
1135
|
+
}
|
|
1136
|
+
consumed++;
|
|
1137
|
+
var _a = this.arrayDeclaration(tokens.slice(consumed)), arrayNode = _a[0], arrayConsumed = _a[1];
|
|
1138
|
+
consumed += arrayConsumed;
|
|
1139
|
+
return [new ast_1.ArrayReference(arrayNode, modifier), consumed];
|
|
1140
|
+
};
|
|
1141
|
+
/**
|
|
1142
|
+
* Parses an alias statement.
|
|
1143
|
+
* @param tokens - Remaining tokens to parse.
|
|
1144
|
+
* @return A tuple containing the AliasStatement and the number of tokens consumed.
|
|
1145
|
+
*/
|
|
1146
|
+
Parser.prototype.aliasStatement = function (tokens) {
|
|
1147
|
+
var consumed = 1;
|
|
1148
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
1149
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected identifier for alias statement");
|
|
1150
|
+
}
|
|
1151
|
+
var _a = this.unaryExpression(tokens.slice(consumed)), identifier = _a[0], identifierConsumed = _a[1];
|
|
1152
|
+
consumed += identifierConsumed;
|
|
1153
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.EqualsAssmt])) {
|
|
1154
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected `=` symbol following identifier for alias statement");
|
|
1155
|
+
}
|
|
1156
|
+
consumed++;
|
|
1157
|
+
var _b = this.binaryExpression(tokens.slice(consumed)), aliasExpression = _b[0], aliasExpressionConsumed = _b[1];
|
|
1158
|
+
consumed += aliasExpressionConsumed;
|
|
1159
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
1160
|
+
throwParserError(errors_1.MissingSemicolonError, tokens[consumed], this.index + consumed, "expected semicolon");
|
|
1161
|
+
}
|
|
1162
|
+
consumed++;
|
|
1163
|
+
return [
|
|
1164
|
+
new ast_1.AliasStatement(identifier, aliasExpression),
|
|
1165
|
+
consumed,
|
|
1166
|
+
];
|
|
1167
|
+
};
|
|
1168
|
+
/**
|
|
1169
|
+
* Parses a quantum reset.
|
|
1170
|
+
* @param tokens - Remaining tokens to parse.
|
|
1171
|
+
* @return A tuple containing the QuantumReset and the number of tokens consumed.
|
|
1172
|
+
*/
|
|
1173
|
+
Parser.prototype.resetStatement = function (tokens) {
|
|
1174
|
+
var consumed = 1;
|
|
1175
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
1176
|
+
throwParserError(errors_1.BadQuantumInstructionError, tokens[consumed], this.index + consumed, "expected identifier after reset keyword");
|
|
1177
|
+
}
|
|
1178
|
+
var _a = this.unaryExpression(tokens.slice(consumed)), idNode = _a[0], idConsumed = _a[1];
|
|
1179
|
+
consumed += idConsumed;
|
|
1180
|
+
var id = null;
|
|
1181
|
+
if (idNode instanceof ast_1.SubscriptedIdentifier) {
|
|
1182
|
+
id = idNode;
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
id = idNode;
|
|
1186
|
+
}
|
|
1187
|
+
consumed++;
|
|
1188
|
+
return [new ast_1.QuantumReset(id), consumed];
|
|
1189
|
+
};
|
|
1190
|
+
/**
|
|
1191
|
+
* Parses a subscript expression as a Range.
|
|
1192
|
+
* @param tokens - Remaining tokens to parse.
|
|
1193
|
+
* @return A tuple containing the parsed Expression or Range and the number of tokens consumed.
|
|
1194
|
+
*/
|
|
1195
|
+
Parser.prototype.parseSubscript = function (tokens) {
|
|
1196
|
+
var consumed = 1;
|
|
1197
|
+
var start = null;
|
|
1198
|
+
var step = new ast_1.IntegerLiteral(1);
|
|
1199
|
+
var stop = null;
|
|
1200
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
1201
|
+
var _a = this.parseIndexSet(tokens.slice(consumed)), indexSet = _a[0], indexSetConsumed = _a[1];
|
|
1202
|
+
consumed += indexSetConsumed;
|
|
1203
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1204
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing curly bracket } for index set");
|
|
1205
|
+
}
|
|
1206
|
+
consumed++;
|
|
1207
|
+
return [indexSet, consumed];
|
|
1208
|
+
}
|
|
1209
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Colon])) {
|
|
1210
|
+
// Parse start
|
|
1211
|
+
var _b = this.binaryExpression(tokens.slice(consumed)), startExpr = _b[0], startConsumed = _b[1];
|
|
1212
|
+
start = startExpr;
|
|
1213
|
+
consumed += startConsumed;
|
|
1214
|
+
}
|
|
1215
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1216
|
+
return [start, consumed + 1];
|
|
1217
|
+
}
|
|
1218
|
+
// Check for colon after start
|
|
1219
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Colon])) {
|
|
1220
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected colon in range expression");
|
|
1221
|
+
}
|
|
1222
|
+
consumed++;
|
|
1223
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1224
|
+
var _c = this.binaryExpression(tokens.slice(consumed)), expr = _c[0], exprConsumed = _c[1];
|
|
1225
|
+
consumed += exprConsumed;
|
|
1226
|
+
// Check if its a step or stop
|
|
1227
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Colon])) {
|
|
1228
|
+
step = expr;
|
|
1229
|
+
consumed++;
|
|
1230
|
+
// Parse stop
|
|
1231
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1232
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected stop value in range expression");
|
|
1233
|
+
}
|
|
1234
|
+
var _d = this.binaryExpression(tokens.slice(consumed)), stopExpr = _d[0], stopConsumed = _d[1];
|
|
1235
|
+
stop = stopExpr;
|
|
1236
|
+
consumed += stopConsumed;
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
stop = expr;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
// Check for closing square bracket
|
|
1243
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1244
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing bracket ] for range expression");
|
|
1245
|
+
}
|
|
1246
|
+
consumed++;
|
|
1247
|
+
// Validate that both start and stop are provided
|
|
1248
|
+
if (start === null || stop === null) {
|
|
1249
|
+
throwParserError(errors_1.BadExpressionError, tokens[0], this.index, "both start and stop must be provided in range expression");
|
|
1250
|
+
}
|
|
1251
|
+
return [new ast_1.Range(start, stop, step), consumed];
|
|
1252
|
+
};
|
|
1253
|
+
/**
|
|
1254
|
+
* Parses a type cast expression.
|
|
1255
|
+
* @param tokens - Remaining tokens to parse.
|
|
1256
|
+
* @return A tuple containing the parsed Cast Expression and the number of tokens consumed.
|
|
1257
|
+
*/
|
|
1258
|
+
Parser.prototype.parseTypeCast = function (tokens) {
|
|
1259
|
+
var consumed = 1;
|
|
1260
|
+
var widthExpr = null;
|
|
1261
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LSParen])) {
|
|
1262
|
+
consumed++;
|
|
1263
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), width = _a[0], widthConsumed = _a[1];
|
|
1264
|
+
consumed += widthConsumed;
|
|
1265
|
+
widthExpr = width;
|
|
1266
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1267
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "missing closing bracket ] for type designator");
|
|
1268
|
+
}
|
|
1269
|
+
consumed++;
|
|
1270
|
+
}
|
|
1271
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
1272
|
+
throwParserError(errors_1.MissingBraceError, tokens[0], this.index, "expected opening parenthesis ( for type cast");
|
|
1273
|
+
}
|
|
1274
|
+
consumed++;
|
|
1275
|
+
var _b = this.binaryExpression(tokens.slice(consumed)), castExpr = _b[0], castConsumed = _b[1];
|
|
1276
|
+
consumed += castConsumed;
|
|
1277
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
1278
|
+
throwParserError(errors_1.MissingBraceError, tokens[0], this.index, "expected closing parenthesis ) for type cast");
|
|
1279
|
+
}
|
|
1280
|
+
consumed++;
|
|
1281
|
+
var castType = this.createClassicalType(tokens[0][0], widthExpr);
|
|
1282
|
+
return [new ast_1.Cast(castType, castExpr), consumed];
|
|
1283
|
+
};
|
|
1284
|
+
/**
|
|
1285
|
+
* Parses a branching condition (if) statement.
|
|
1286
|
+
* @param tokens - Tokens to parse.
|
|
1287
|
+
* @return A BranchingStatement node representing the if statement and the number of tokens consumed.
|
|
1288
|
+
*/
|
|
1289
|
+
Parser.prototype.ifStatement = function (tokens) {
|
|
1290
|
+
var consumed = 1;
|
|
1291
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
1292
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening parenthesis after if");
|
|
1293
|
+
}
|
|
1294
|
+
consumed++;
|
|
1295
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), condition = _a[0], conditionConsumed = _a[1];
|
|
1296
|
+
consumed += conditionConsumed;
|
|
1297
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
1298
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing parenthesis after if statement condition");
|
|
1299
|
+
}
|
|
1300
|
+
consumed++;
|
|
1301
|
+
var _b = this.programBlock(tokens.slice(consumed)), trueBody = _b[0], trueBodyConsumed = _b[1];
|
|
1302
|
+
consumed += trueBodyConsumed;
|
|
1303
|
+
var falseBody = null;
|
|
1304
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Else])) {
|
|
1305
|
+
consumed++;
|
|
1306
|
+
var _c = this.programBlock(tokens.slice(consumed)), elseBody = _c[0], elseBodyConsumed = _c[1];
|
|
1307
|
+
falseBody = elseBody;
|
|
1308
|
+
consumed += elseBodyConsumed;
|
|
1309
|
+
}
|
|
1310
|
+
return [new ast_1.BranchingStatement(condition, trueBody, falseBody), consumed];
|
|
1311
|
+
};
|
|
1312
|
+
/**
|
|
1313
|
+
* Parses a for loop.
|
|
1314
|
+
* @param tokens - Tokens to parse.
|
|
1315
|
+
* @return A ForLoopStatement node and the number of tokens consumed.
|
|
1316
|
+
*/
|
|
1317
|
+
Parser.prototype.forLoopStatement = function (tokens) {
|
|
1318
|
+
var consumed = 1;
|
|
1319
|
+
// Parse the type of the loop variable
|
|
1320
|
+
var _a = this.parseClassicalType(tokens.slice(consumed)), loopVarType = _a[0], loopVarTypeConsumed = _a[1];
|
|
1321
|
+
consumed += loopVarTypeConsumed;
|
|
1322
|
+
// Expect an identifier (loop variable)
|
|
1323
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
1324
|
+
throwParserError(errors_1.BadLoopError, tokens[consumed], this.index + consumed, "expected identifier for loop variable");
|
|
1325
|
+
}
|
|
1326
|
+
var _b = this.unaryExpression(tokens.slice(consumed)), loopVar = _b[0], loopVarConsumed = _b[1];
|
|
1327
|
+
if (!(loopVar instanceof ast_1.Identifier)) {
|
|
1328
|
+
throwParserError(errors_1.BadLoopError, tokens[consumed], this.index + consumed, "expected identifier for loop variable");
|
|
1329
|
+
}
|
|
1330
|
+
consumed += loopVarConsumed;
|
|
1331
|
+
// Expect `in` keyword
|
|
1332
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.In])) {
|
|
1333
|
+
throwParserError(errors_1.BadLoopError, tokens[consumed], this.index + consumed, "expected `in` keyword in for loop");
|
|
1334
|
+
}
|
|
1335
|
+
consumed++;
|
|
1336
|
+
var _c = this.parseSetDeclaration(tokens.slice(consumed)), indexSet = _c[0], indexSetConsumed = _c[1];
|
|
1337
|
+
consumed += indexSetConsumed;
|
|
1338
|
+
var _d = this.programBlock(tokens.slice(consumed)), body = _d[0], bodyConsumed = _d[1];
|
|
1339
|
+
consumed += bodyConsumed;
|
|
1340
|
+
return [
|
|
1341
|
+
new ast_1.ForLoopStatement(indexSet, loopVarType, loopVar, body),
|
|
1342
|
+
consumed,
|
|
1343
|
+
];
|
|
1344
|
+
};
|
|
1345
|
+
/**
|
|
1346
|
+
* Parses a while loop.
|
|
1347
|
+
* @param tokens - Tokens to parse.
|
|
1348
|
+
* @return A ForLoopStatement node and the number of tokens consumed.
|
|
1349
|
+
*/
|
|
1350
|
+
Parser.prototype.whileLoopStatement = function (tokens) {
|
|
1351
|
+
var consumed = 1;
|
|
1352
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
1353
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening parenthesis after while keyword");
|
|
1354
|
+
}
|
|
1355
|
+
consumed++;
|
|
1356
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), condition = _a[0], conditionConsumed = _a[1];
|
|
1357
|
+
consumed += conditionConsumed;
|
|
1358
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
1359
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing parenthesis after while loop condition");
|
|
1360
|
+
}
|
|
1361
|
+
consumed++;
|
|
1362
|
+
var _b = this.programBlock(tokens.slice(consumed)), body = _b[0], bodyConsumed = _b[1];
|
|
1363
|
+
consumed += bodyConsumed;
|
|
1364
|
+
return [new ast_1.WhileLoopStatement(condition, body), consumed];
|
|
1365
|
+
};
|
|
1366
|
+
/**
|
|
1367
|
+
* Parses a barrier statement.
|
|
1368
|
+
* @param tokens - Tokens to parse.
|
|
1369
|
+
* @return An QuantumBarrier node and the number of tokens consumed.
|
|
1370
|
+
*/
|
|
1371
|
+
Parser.prototype.barrier = function (tokens) {
|
|
1372
|
+
var consumed = 1;
|
|
1373
|
+
var _a = this.parseQubitList(tokens.slice(consumed)), qubits = _a[0], qubitsConsumed = _a[1];
|
|
1374
|
+
consumed += qubitsConsumed;
|
|
1375
|
+
return [new ast_1.QuantumBarrier(qubits), consumed];
|
|
1376
|
+
};
|
|
1377
|
+
/**
|
|
1378
|
+
* Parses a box statement.
|
|
1379
|
+
* @param tokens - Tokens to parse.
|
|
1380
|
+
* @return An BoxDefinition node and the number of tokens consumed.
|
|
1381
|
+
*/
|
|
1382
|
+
Parser.prototype.box = function (tokens) {
|
|
1383
|
+
var consumed = 1;
|
|
1384
|
+
var designator = null;
|
|
1385
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LSParen])) {
|
|
1386
|
+
consumed++;
|
|
1387
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), desginatorNode = _a[0], designatorConsumed = _a[1];
|
|
1388
|
+
consumed += designatorConsumed;
|
|
1389
|
+
designator = desginatorNode;
|
|
1390
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1391
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing ] bracket following box designator");
|
|
1392
|
+
}
|
|
1393
|
+
consumed++;
|
|
1394
|
+
}
|
|
1395
|
+
var _b = this.programBlock(tokens.slice(consumed)), scope = _b[0], scopeConsumed = _b[1];
|
|
1396
|
+
consumed += scopeConsumed;
|
|
1397
|
+
return [new ast_1.BoxDefinition(scope, designator), consumed];
|
|
1398
|
+
};
|
|
1399
|
+
/**
|
|
1400
|
+
* Parses an array statement.
|
|
1401
|
+
* @param tokens - Tokens to parse.
|
|
1402
|
+
* @return An ArrayDeclaration node and the number of tokens consumed.
|
|
1403
|
+
*/
|
|
1404
|
+
Parser.prototype.arrayDeclaration = function (tokens) {
|
|
1405
|
+
var consumed = 1;
|
|
1406
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LSParen])) {
|
|
1407
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected [ after array keyword");
|
|
1408
|
+
}
|
|
1409
|
+
consumed++;
|
|
1410
|
+
var _a = this.parseClassicalType(tokens.slice(consumed)), baseType = _a[0], baseTypeConsumed = _a[1];
|
|
1411
|
+
consumed += baseTypeConsumed;
|
|
1412
|
+
var dimensions = [];
|
|
1413
|
+
while (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
1414
|
+
consumed++;
|
|
1415
|
+
if (this.matchNext(tokens.slice(consumed), [
|
|
1416
|
+
token_1.Token.Dim,
|
|
1417
|
+
token_1.Token.EqualsAssmt,
|
|
1418
|
+
token_1.Token.NNInteger,
|
|
1419
|
+
])) {
|
|
1420
|
+
consumed += 2;
|
|
1421
|
+
dimensions = Number(tokens[consumed][1]);
|
|
1422
|
+
consumed++;
|
|
1423
|
+
break;
|
|
1424
|
+
}
|
|
1425
|
+
var _b = this.binaryExpression(tokens.slice(consumed)), dimension = _b[0], dimensionConsumed = _b[1];
|
|
1426
|
+
dimensions.push(dimension);
|
|
1427
|
+
consumed += dimensionConsumed;
|
|
1428
|
+
}
|
|
1429
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1430
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected ] after array type declaration");
|
|
1431
|
+
}
|
|
1432
|
+
consumed++;
|
|
1433
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
1434
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected identifier for array declaration");
|
|
1435
|
+
}
|
|
1436
|
+
var _c = this.unaryExpression(tokens.slice(consumed)), identifier = _c[0], identifierConsumed = _c[1];
|
|
1437
|
+
consumed += identifierConsumed;
|
|
1438
|
+
var initializer = null;
|
|
1439
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.EqualsAssmt])) {
|
|
1440
|
+
consumed++;
|
|
1441
|
+
var _d = this.parseArrayInitializer(tokens.slice(consumed)), parsedInitializer = _d[0], initializerConsumed = _d[1];
|
|
1442
|
+
initializer = parsedInitializer;
|
|
1443
|
+
consumed += initializerConsumed;
|
|
1444
|
+
}
|
|
1445
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
1446
|
+
consumed++;
|
|
1447
|
+
}
|
|
1448
|
+
return [
|
|
1449
|
+
new ast_1.ArrayDeclaration(baseType, dimensions, identifier, initializer),
|
|
1450
|
+
consumed,
|
|
1451
|
+
];
|
|
1452
|
+
};
|
|
1453
|
+
/**
|
|
1454
|
+
* Parses an array initializer.
|
|
1455
|
+
* @param tokens - Tokens to parse.
|
|
1456
|
+
* @return An ArrayInitializer node and the number of tokens consumed.
|
|
1457
|
+
*/
|
|
1458
|
+
Parser.prototype.parseArrayInitializer = function (tokens) {
|
|
1459
|
+
var consumed = 0;
|
|
1460
|
+
if (!this.matchNext(tokens, [token_1.Token.LCParen])) {
|
|
1461
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), expr = _a[0], exprConsumed = _a[1];
|
|
1462
|
+
consumed += exprConsumed;
|
|
1463
|
+
return [expr, consumed];
|
|
1464
|
+
}
|
|
1465
|
+
consumed++;
|
|
1466
|
+
var values = [];
|
|
1467
|
+
while (!this.matchNext(tokens.slice(consumed), [token_1.Token.RCParen])) {
|
|
1468
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
1469
|
+
var _b = this.parseArrayInitializer(tokens.slice(consumed)), subInitializer = _b[0], subConsumed = _b[1];
|
|
1470
|
+
values.push(subInitializer);
|
|
1471
|
+
consumed += subConsumed;
|
|
1472
|
+
}
|
|
1473
|
+
else {
|
|
1474
|
+
var _c = this.binaryExpression(tokens.slice(consumed)), expr = _c[0], exprConsumed = _c[1];
|
|
1475
|
+
values.push(expr);
|
|
1476
|
+
consumed += exprConsumed;
|
|
1477
|
+
}
|
|
1478
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
1479
|
+
consumed++;
|
|
1480
|
+
}
|
|
1481
|
+
else if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RCParen])) {
|
|
1482
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected comma or } in array initializer");
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
consumed++;
|
|
1486
|
+
return [new ast_1.ArrayInitializer(values), consumed];
|
|
1487
|
+
};
|
|
1488
|
+
/**
|
|
1489
|
+
* Parses an array access.
|
|
1490
|
+
* @param tokens - Tokens to parse.
|
|
1491
|
+
* @return An ArrayAccess node and the number of tokens consumed.
|
|
1492
|
+
*/
|
|
1493
|
+
Parser.prototype.parseArrayAccess = function (tokens) {
|
|
1494
|
+
var consumed = 0;
|
|
1495
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Id])) {
|
|
1496
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected identifier for array access");
|
|
1497
|
+
}
|
|
1498
|
+
var identifier = new ast_1.Identifier(tokens[0][1].toString());
|
|
1499
|
+
consumed++;
|
|
1500
|
+
var indices = [];
|
|
1501
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LSParen])) {
|
|
1502
|
+
consumed++;
|
|
1503
|
+
while (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1504
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), index1 = _a[0], index1Consumed = _a[1];
|
|
1505
|
+
indices.push(index1);
|
|
1506
|
+
consumed += index1Consumed;
|
|
1507
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
1508
|
+
consumed++;
|
|
1509
|
+
}
|
|
1510
|
+
else if (this.matchNext(tokens.slice(consumed), [token_1.Token.Colon])) {
|
|
1511
|
+
consumed++;
|
|
1512
|
+
var step = new ast_1.IntegerLiteral(1);
|
|
1513
|
+
var stop_1 = void 0;
|
|
1514
|
+
var _b = this.binaryExpression(tokens.slice(consumed)), index2 = _b[0], index2Consumed = _b[1];
|
|
1515
|
+
consumed += index2Consumed;
|
|
1516
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Colon])) {
|
|
1517
|
+
consumed++;
|
|
1518
|
+
var _c = this.binaryExpression(tokens.slice(consumed)), index3 = _c[0], index3Consumed = _c[1];
|
|
1519
|
+
consumed += index3Consumed;
|
|
1520
|
+
stop_1 = index3;
|
|
1521
|
+
step = index2;
|
|
1522
|
+
}
|
|
1523
|
+
else {
|
|
1524
|
+
stop_1 = index2;
|
|
1525
|
+
}
|
|
1526
|
+
indices = new ast_1.Range(index1, stop_1, step);
|
|
1527
|
+
break;
|
|
1528
|
+
}
|
|
1529
|
+
else if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1530
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected comma or closing bracket for array access");
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1534
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing bracket ] for array access");
|
|
1535
|
+
}
|
|
1536
|
+
consumed++;
|
|
1537
|
+
}
|
|
1538
|
+
return [new ast_1.ArrayAccess(identifier, indices), consumed];
|
|
1539
|
+
};
|
|
1540
|
+
/**
|
|
1541
|
+
* Parses a switch statement.
|
|
1542
|
+
* @param tokens - Tokens to parse.
|
|
1543
|
+
* @return A SwitchStatement node and the number of tokens consumed.
|
|
1544
|
+
*/
|
|
1545
|
+
Parser.prototype.switchStatement = function (tokens) {
|
|
1546
|
+
var consumed = 1;
|
|
1547
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
1548
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening parenthesis after switch keywork");
|
|
1549
|
+
}
|
|
1550
|
+
consumed++;
|
|
1551
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), controlExpr = _a[0], controlExprConsumed = _a[1];
|
|
1552
|
+
consumed += controlExprConsumed;
|
|
1553
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
1554
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing parenthesis after switch control expression");
|
|
1555
|
+
}
|
|
1556
|
+
consumed++;
|
|
1557
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
1558
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening curly brace for switch body");
|
|
1559
|
+
}
|
|
1560
|
+
consumed++;
|
|
1561
|
+
var cases = [];
|
|
1562
|
+
var defaultCase = null;
|
|
1563
|
+
while (!this.matchNext(tokens.slice(consumed), [token_1.Token.RCParen])) {
|
|
1564
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Case])) {
|
|
1565
|
+
var _b = this.parseCaseStatement(tokens.slice(consumed)), caseStmt = _b[0], caseConsumed = _b[1];
|
|
1566
|
+
cases.push(caseStmt);
|
|
1567
|
+
consumed += caseConsumed;
|
|
1568
|
+
}
|
|
1569
|
+
else if (this.matchNext(tokens.slice(consumed), [token_1.Token.Default])) {
|
|
1570
|
+
if (defaultCase !== null) {
|
|
1571
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "multiple default statements not allowed in a swtich statement");
|
|
1572
|
+
}
|
|
1573
|
+
var _c = this.parseDefaultStatement(tokens.slice(consumed)), defaultStmt = _c[0], defaultConsumed = _c[1];
|
|
1574
|
+
defaultCase = defaultStmt;
|
|
1575
|
+
consumed += defaultConsumed;
|
|
1576
|
+
}
|
|
1577
|
+
else {
|
|
1578
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected case or default statement in switch body");
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
if (cases.length === 0) {
|
|
1582
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "swtich statement must contain at least one case statement");
|
|
1583
|
+
}
|
|
1584
|
+
consumed++;
|
|
1585
|
+
return [new ast_1.SwitchStatement(controlExpr, cases, defaultCase), consumed];
|
|
1586
|
+
};
|
|
1587
|
+
/**
|
|
1588
|
+
* Parses a case statement.
|
|
1589
|
+
* @param tokens - Tokens to parse.
|
|
1590
|
+
* @return A CaseStatement node and the number of tokens consumed.
|
|
1591
|
+
*/
|
|
1592
|
+
Parser.prototype.parseCaseStatement = function (tokens) {
|
|
1593
|
+
var consumed = 1;
|
|
1594
|
+
var labels = [];
|
|
1595
|
+
while (!this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
1596
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), label = _a[0], labelConsumed = _a[1];
|
|
1597
|
+
labels.push(label);
|
|
1598
|
+
consumed += labelConsumed;
|
|
1599
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
1600
|
+
consumed++;
|
|
1601
|
+
}
|
|
1602
|
+
else if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
1603
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected comma or opening brace in case statement");
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
var _b = this.programBlock(tokens.slice(consumed)), body = _b[0], bodyConsumed = _b[1];
|
|
1607
|
+
consumed += bodyConsumed;
|
|
1608
|
+
return [new ast_1.CaseStatement(labels, body), consumed];
|
|
1609
|
+
};
|
|
1610
|
+
/**
|
|
1611
|
+
* Parses a default statement.
|
|
1612
|
+
* @param tokens - Tokens to parse.
|
|
1613
|
+
* @return A DefaultStatement node and the number of tokens consumed.
|
|
1614
|
+
*/
|
|
1615
|
+
Parser.prototype.parseDefaultStatement = function (tokens) {
|
|
1616
|
+
var consumed = 1;
|
|
1617
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
1618
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expecting opening brace for default statement");
|
|
1619
|
+
}
|
|
1620
|
+
var _a = this.programBlock(tokens.slice(consumed)), body = _a[0], bodyConsumed = _a[1];
|
|
1621
|
+
consumed += bodyConsumed;
|
|
1622
|
+
return [new ast_1.DefaultStatement(body), consumed];
|
|
1623
|
+
};
|
|
1624
|
+
/**
|
|
1625
|
+
* Parses a delay statement.
|
|
1626
|
+
* @param tokens - Tokens to parse.
|
|
1627
|
+
* @return A QuantumDelay node and the number of tokens consumed.
|
|
1628
|
+
*/
|
|
1629
|
+
Parser.prototype.delay = function (tokens) {
|
|
1630
|
+
var consumed = 1;
|
|
1631
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LSParen])) {
|
|
1632
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening bracket [ after delay keyword");
|
|
1633
|
+
}
|
|
1634
|
+
consumed++;
|
|
1635
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), duration = _a[0], durationConsumed = _a[1];
|
|
1636
|
+
consumed += durationConsumed;
|
|
1637
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1638
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing bracket ] after delay designator");
|
|
1639
|
+
}
|
|
1640
|
+
consumed++;
|
|
1641
|
+
var _b = this.parseQubitList(tokens.slice(consumed)), qubits = _b[0], qubitsConsumed = _b[1];
|
|
1642
|
+
consumed += qubitsConsumed;
|
|
1643
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
1644
|
+
throwParserError(errors_1.MissingSemicolonError, tokens[consumed], this.index + consumed, "expected semicolon");
|
|
1645
|
+
}
|
|
1646
|
+
consumed++;
|
|
1647
|
+
return [new ast_1.QuantumDelay(duration, qubits), consumed];
|
|
1648
|
+
};
|
|
1649
|
+
/**
|
|
1650
|
+
* Parses a durationof function call.
|
|
1651
|
+
* @param tokens - Tokens to parse.
|
|
1652
|
+
* @return A DurationOf node and the number of tokens consumed.
|
|
1653
|
+
*/
|
|
1654
|
+
Parser.prototype.durationOf = function (tokens) {
|
|
1655
|
+
var consumed = 1;
|
|
1656
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
1657
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening parenthesis after durationof");
|
|
1658
|
+
}
|
|
1659
|
+
consumed++;
|
|
1660
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
1661
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening brace for durationof scope");
|
|
1662
|
+
}
|
|
1663
|
+
var _a = this.programBlock(tokens.slice(consumed)), scope = _a[0], scopeConsumed = _a[1];
|
|
1664
|
+
consumed += scopeConsumed;
|
|
1665
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
1666
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing parenthesis after durationof scope");
|
|
1667
|
+
}
|
|
1668
|
+
consumed++;
|
|
1669
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
1670
|
+
consumed++;
|
|
1671
|
+
}
|
|
1672
|
+
return [new ast_1.DurationOf(scope), consumed];
|
|
1673
|
+
};
|
|
1674
|
+
/**
|
|
1675
|
+
* Parses a sizeof function call.
|
|
1676
|
+
* @param tokens - Tokens to parse.
|
|
1677
|
+
* @return A SizeOf node and the number of tokens consumed.
|
|
1678
|
+
*/
|
|
1679
|
+
Parser.prototype.sizeOf = function (tokens) {
|
|
1680
|
+
var consumed = 1;
|
|
1681
|
+
var dimensions = null;
|
|
1682
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LParen])) {
|
|
1683
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected opening parenthesis for sizeof function call");
|
|
1684
|
+
}
|
|
1685
|
+
consumed++;
|
|
1686
|
+
var _a = this.unaryExpression(tokens.slice(consumed)), arrayId = _a[0], arrayIdConsumed = _a[1];
|
|
1687
|
+
consumed += arrayIdConsumed;
|
|
1688
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
1689
|
+
consumed++;
|
|
1690
|
+
var _b = this.binaryExpression(tokens.slice(consumed)), dim = _b[0], dimConsumed = _b[1];
|
|
1691
|
+
consumed += dimConsumed;
|
|
1692
|
+
dimensions = dim;
|
|
1693
|
+
}
|
|
1694
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RParen])) {
|
|
1695
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing parenthesis for sizeof function call");
|
|
1696
|
+
}
|
|
1697
|
+
consumed++;
|
|
1698
|
+
return [new ast_1.SizeOf(arrayId, dimensions), consumed];
|
|
1699
|
+
};
|
|
1700
|
+
/**
|
|
1701
|
+
* Parses a program block.
|
|
1702
|
+
* @param tokens - Tokens to parse.
|
|
1703
|
+
* @return A ProgramBlock node and the number of tokens consumed.
|
|
1704
|
+
*/
|
|
1705
|
+
Parser.prototype.programBlock = function (tokens) {
|
|
1706
|
+
var statements = [];
|
|
1707
|
+
var consumed = 0;
|
|
1708
|
+
var braceCount = 0;
|
|
1709
|
+
if (this.matchNext(tokens, [token_1.Token.LCParen])) {
|
|
1710
|
+
consumed++;
|
|
1711
|
+
braceCount++;
|
|
1712
|
+
while (braceCount > 0 && consumed < tokens.length) {
|
|
1713
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LCParen])) {
|
|
1714
|
+
braceCount++;
|
|
1715
|
+
}
|
|
1716
|
+
else if (this.matchNext(tokens.slice(consumed), [token_1.Token.RCParen])) {
|
|
1717
|
+
braceCount--;
|
|
1718
|
+
}
|
|
1719
|
+
if (braceCount === 0) {
|
|
1720
|
+
break;
|
|
1721
|
+
}
|
|
1722
|
+
var _a = this.parseNode(tokens.slice(consumed)), node = _a[0], nodeConsumed = _a[1];
|
|
1723
|
+
if (node && node.length > 0) {
|
|
1724
|
+
statements.push(node[0]);
|
|
1725
|
+
}
|
|
1726
|
+
consumed += nodeConsumed;
|
|
1727
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
1728
|
+
consumed++;
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
if (braceCount !== 0) {
|
|
1732
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "mismatched curly braces in program block");
|
|
1733
|
+
}
|
|
1734
|
+
consumed++;
|
|
1735
|
+
}
|
|
1736
|
+
else {
|
|
1737
|
+
var _b = this.parseNode(tokens.slice(consumed)), node = _b[0], nodeConsumed = _b[1];
|
|
1738
|
+
if (node && node.length > 0) {
|
|
1739
|
+
statements.push(node[0]);
|
|
1740
|
+
}
|
|
1741
|
+
consumed += nodeConsumed;
|
|
1742
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Semicolon])) {
|
|
1743
|
+
consumed++;
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
return [new ast_1.ProgramBlock(statements), consumed];
|
|
1747
|
+
};
|
|
1748
|
+
/**
|
|
1749
|
+
* Parses an include statement.
|
|
1750
|
+
* @param tokens - Tokens to parse.
|
|
1751
|
+
* @return An Include node representing the include statement and the number of consumed tokens.
|
|
1752
|
+
*/
|
|
1753
|
+
Parser.prototype.include = function (tokens) {
|
|
1754
|
+
var filename;
|
|
1755
|
+
var consumed = 1;
|
|
1756
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.String, token_1.Token.Semicolon])) {
|
|
1757
|
+
filename = tokens[consumed][1].toString();
|
|
1758
|
+
return [new ast_1.Include(filename), consumed + 2];
|
|
1759
|
+
}
|
|
1760
|
+
throwParserError(errors_1.BadStringLiteralError, tokens[consumed], this.index + consumed, "expected string literal following `include` keyword");
|
|
1761
|
+
};
|
|
1762
|
+
/**
|
|
1763
|
+
* Parses the version header and sets the parser version.
|
|
1764
|
+
* @param tokens - Tokens to parse.
|
|
1765
|
+
* @return A Version node representing the version statement and the number of consumed tokens.
|
|
1766
|
+
*/
|
|
1767
|
+
Parser.prototype.versionHeader = function (tokens) {
|
|
1768
|
+
var version;
|
|
1769
|
+
var consumed = 1;
|
|
1770
|
+
var slicedTokens = tokens.slice(consumed);
|
|
1771
|
+
if (this.matchNext(slicedTokens, [token_1.Token.NNInteger, token_1.Token.Semicolon])) {
|
|
1772
|
+
version = new version_1.OpenQASMVersion(Number(tokens[0][1]));
|
|
1773
|
+
if (!version.isVersion3()) {
|
|
1774
|
+
throwParserError(errors_1.UnsupportedOpenQASMVersionError, tokens[consumed], this.index + consumed, "expected QASM version 3");
|
|
1775
|
+
}
|
|
1776
|
+
consumed += 2;
|
|
1777
|
+
return [new ast_1.Version(version), consumed];
|
|
1778
|
+
}
|
|
1779
|
+
else if (this.matchNext(slicedTokens, [token_1.Token.Real, token_1.Token.Semicolon])) {
|
|
1780
|
+
var versionSplits = tokens[consumed][1].toString().split(".");
|
|
1781
|
+
version = new version_1.OpenQASMVersion(Number(versionSplits[0]), Number(versionSplits[1]));
|
|
1782
|
+
if (!version.isVersion3()) {
|
|
1783
|
+
throwParserError(errors_1.UnsupportedOpenQASMVersionError, tokens[consumed], this.index + consumed, "expected QASM version 3");
|
|
1784
|
+
}
|
|
1785
|
+
consumed += 2;
|
|
1786
|
+
return [new ast_1.Version(version), consumed];
|
|
1787
|
+
}
|
|
1788
|
+
throwParserError(errors_1.UnsupportedOpenQASMVersionError, tokens[consumed], this.index + consumed, "expected QASM version 3");
|
|
1789
|
+
};
|
|
1790
|
+
/**
|
|
1791
|
+
* Parses a classical type.
|
|
1792
|
+
* @param token - The token that represents the type.
|
|
1793
|
+
* @return The ClassicalType and the number of consumed tokens.
|
|
1794
|
+
*/
|
|
1795
|
+
Parser.prototype.parseClassicalType = function (tokens) {
|
|
1796
|
+
var typeToken = tokens[0][0];
|
|
1797
|
+
var consumed = 1;
|
|
1798
|
+
var width;
|
|
1799
|
+
var isComplex = false;
|
|
1800
|
+
if (typeToken === token_1.Token.Complex) {
|
|
1801
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.LSParen, token_1.Token.Float])) {
|
|
1802
|
+
throwParserError(errors_1.BadClassicalTypeError, tokens[consumed], this.index + consumed, "expected float type for complex number");
|
|
1803
|
+
}
|
|
1804
|
+
isComplex = true;
|
|
1805
|
+
consumed += 2;
|
|
1806
|
+
typeToken = tokens[2][0];
|
|
1807
|
+
}
|
|
1808
|
+
// Check if there's a width or size specification
|
|
1809
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.LSParen])) {
|
|
1810
|
+
consumed++;
|
|
1811
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), widthExpr = _a[0], widthConsumed = _a[1];
|
|
1812
|
+
width = widthExpr;
|
|
1813
|
+
consumed += widthConsumed;
|
|
1814
|
+
if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RSParen])) {
|
|
1815
|
+
throwParserError(errors_1.MissingBraceError, tokens[consumed], this.index + consumed, "expected closing bracket ] for type width");
|
|
1816
|
+
}
|
|
1817
|
+
if (isComplex) {
|
|
1818
|
+
consumed++;
|
|
1819
|
+
}
|
|
1820
|
+
consumed++;
|
|
1821
|
+
}
|
|
1822
|
+
var classicalType = this.createClassicalType(typeToken, width);
|
|
1823
|
+
if (isComplex) {
|
|
1824
|
+
return [new ast_1.ComplexType(classicalType), consumed];
|
|
1825
|
+
}
|
|
1826
|
+
else {
|
|
1827
|
+
return [classicalType, consumed];
|
|
1828
|
+
}
|
|
1829
|
+
};
|
|
1830
|
+
/**
|
|
1831
|
+
* Parses a set declaration.
|
|
1832
|
+
* @param token - The token that represents the type.
|
|
1833
|
+
* @return The resulting Identifier, IndexSet, or Range node and the number of consumed tokens.
|
|
1834
|
+
*/
|
|
1835
|
+
Parser.prototype.parseSetDeclaration = function (tokens) {
|
|
1836
|
+
if (this.matchNext(tokens, [token_1.Token.Id])) {
|
|
1837
|
+
var _a = this.unaryExpression(tokens), identifier = _a[0], identifierConsumed = _a[1];
|
|
1838
|
+
return [identifier, identifierConsumed];
|
|
1839
|
+
}
|
|
1840
|
+
else if (this.matchNext(tokens, [token_1.Token.LCParen])) {
|
|
1841
|
+
return this.parseIndexSet(tokens);
|
|
1842
|
+
}
|
|
1843
|
+
else if (this.matchNext(tokens, [token_1.Token.LSParen])) {
|
|
1844
|
+
return this.parseSubscript(tokens);
|
|
1845
|
+
}
|
|
1846
|
+
else {
|
|
1847
|
+
return this.binaryExpression(tokens);
|
|
1848
|
+
}
|
|
1849
|
+
};
|
|
1850
|
+
/**
|
|
1851
|
+
* Parses an index set.
|
|
1852
|
+
* @param token - The token that represents the type.
|
|
1853
|
+
* @return The resulting Identifier, IndexSet, or Range node and the number of consumed tokens.
|
|
1854
|
+
*/
|
|
1855
|
+
Parser.prototype.parseIndexSet = function (tokens) {
|
|
1856
|
+
var consumed = 1;
|
|
1857
|
+
var values = [];
|
|
1858
|
+
while (!this.matchNext(tokens.slice(consumed), [token_1.Token.RCParen])) {
|
|
1859
|
+
var _a = this.binaryExpression(tokens.slice(consumed)), expr = _a[0], exprConsumed = _a[1];
|
|
1860
|
+
values.push(expr);
|
|
1861
|
+
consumed += exprConsumed;
|
|
1862
|
+
if (this.matchNext(tokens.slice(consumed), [token_1.Token.Comma])) {
|
|
1863
|
+
consumed++;
|
|
1864
|
+
}
|
|
1865
|
+
else if (!this.matchNext(tokens.slice(consumed), [token_1.Token.RCParen])) {
|
|
1866
|
+
throwParserError(errors_1.BadExpressionError, tokens[consumed], this.index + consumed, "expected comma or closing curly brace in index set");
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
consumed++;
|
|
1870
|
+
return [new ast_1.IndexSet(values), consumed];
|
|
1871
|
+
};
|
|
1872
|
+
/**
|
|
1873
|
+
* Creates a classical type.
|
|
1874
|
+
* @param token - The token that represents the type.
|
|
1875
|
+
* @width - The type's width or size, if applicable.
|
|
1876
|
+
* @return The created ClassicalType.
|
|
1877
|
+
*/
|
|
1878
|
+
Parser.prototype.createClassicalType = function (token, width) {
|
|
1879
|
+
switch (token) {
|
|
1880
|
+
case token_1.Token.Int:
|
|
1881
|
+
return new ast_1.IntType(width || this.machineIntSize);
|
|
1882
|
+
case token_1.Token.UInt:
|
|
1883
|
+
return new ast_1.UIntType(width || this.machineIntSize);
|
|
1884
|
+
case token_1.Token.Float:
|
|
1885
|
+
return new ast_1.FloatType(width || this.machineFloatWidth);
|
|
1886
|
+
case token_1.Token.Bool:
|
|
1887
|
+
return new ast_1.BoolType();
|
|
1888
|
+
case token_1.Token.Bit:
|
|
1889
|
+
return new ast_1.BitType(width);
|
|
1890
|
+
case token_1.Token.CReg:
|
|
1891
|
+
return new ast_1.BitType(width);
|
|
1892
|
+
case token_1.Token.Stretch:
|
|
1893
|
+
return new ast_1.StretchType();
|
|
1894
|
+
case token_1.Token.Duration:
|
|
1895
|
+
return new ast_1.DurationType();
|
|
1896
|
+
case token_1.Token.Angle:
|
|
1897
|
+
return new ast_1.AngleType(width);
|
|
1898
|
+
default:
|
|
1899
|
+
throwParserError(errors_1.BadClassicalTypeError, token, this.index, "unsupported classical type");
|
|
1900
|
+
}
|
|
1901
|
+
};
|
|
1902
|
+
/**
|
|
1903
|
+
* Creates a math or trigonometric function node.
|
|
1904
|
+
* @param token - The token representing the function.
|
|
1905
|
+
* @param expr - The expression to which the function is applied.
|
|
1906
|
+
* @return The created MathFunction or TrigFunction node and the number of consumed tokens.
|
|
1907
|
+
*/
|
|
1908
|
+
Parser.prototype.createMathOrTrigFunction = function (token, expr) {
|
|
1909
|
+
switch (token) {
|
|
1910
|
+
case token_1.Token.Arccos:
|
|
1911
|
+
return [new ast_1.TrigFunction(ast_1.TrigFunctionTypes.ARCCOS, expr), 1];
|
|
1912
|
+
case token_1.Token.Arcsin:
|
|
1913
|
+
return [new ast_1.TrigFunction(ast_1.TrigFunctionTypes.ARCSIN, expr), 1];
|
|
1914
|
+
case token_1.Token.Arctan:
|
|
1915
|
+
return [new ast_1.TrigFunction(ast_1.TrigFunctionTypes.ARCTAN, expr), 1];
|
|
1916
|
+
case token_1.Token.Cos:
|
|
1917
|
+
return [new ast_1.TrigFunction(ast_1.TrigFunctionTypes.COS, expr), 1];
|
|
1918
|
+
case token_1.Token.Sin:
|
|
1919
|
+
return [new ast_1.TrigFunction(ast_1.TrigFunctionTypes.SIN, expr), 1];
|
|
1920
|
+
case token_1.Token.Tan:
|
|
1921
|
+
return [new ast_1.TrigFunction(ast_1.TrigFunctionTypes.TAN, expr), 1];
|
|
1922
|
+
case token_1.Token.Ceiling:
|
|
1923
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.CEILING, expr), 1];
|
|
1924
|
+
case token_1.Token.Exp:
|
|
1925
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.EXP, expr), 1];
|
|
1926
|
+
case token_1.Token.Floor:
|
|
1927
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.FLOOR, expr), 1];
|
|
1928
|
+
case token_1.Token.Log:
|
|
1929
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.LOG, expr), 1];
|
|
1930
|
+
case token_1.Token.Mod:
|
|
1931
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.MOD, expr), 1];
|
|
1932
|
+
case token_1.Token.Popcount:
|
|
1933
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.POPCOUNT, expr), 1];
|
|
1934
|
+
case token_1.Token.Pow:
|
|
1935
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.POW, expr), 1];
|
|
1936
|
+
case token_1.Token.Rotl:
|
|
1937
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.ROTL, expr), 1];
|
|
1938
|
+
case token_1.Token.Rotr:
|
|
1939
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.ROTR, expr), 1];
|
|
1940
|
+
case token_1.Token.Sqrt:
|
|
1941
|
+
return [new ast_1.MathFunction(ast_1.MathFunctionTypes.SQRT, expr), 1];
|
|
1942
|
+
default:
|
|
1943
|
+
throwParserError(errors_1.BadExpressionError, token, this.index, "unsupported math or trig function");
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1946
|
+
/** Checks whether a Bit token precedes a measurement statement. */
|
|
1947
|
+
Parser.prototype.isMeasurement = function (tokens) {
|
|
1948
|
+
var i = 0;
|
|
1949
|
+
while (i < tokens.length - 1 &&
|
|
1950
|
+
tokens[i][0] !== token_1.Token.LCParen &&
|
|
1951
|
+
tokens[i][0] !== token_1.Token.Semicolon &&
|
|
1952
|
+
tokens[i][0] !== token_1.Token.EqualsAssmt) {
|
|
1953
|
+
i++;
|
|
1954
|
+
}
|
|
1955
|
+
return (tokens[i][0] === token_1.Token.EqualsAssmt && tokens[i + 1][0] === token_1.Token.Measure);
|
|
1956
|
+
};
|
|
1957
|
+
/** Checks whether the statement is part of an assignment. */
|
|
1958
|
+
Parser.prototype.isAssignment = function (tokens) {
|
|
1959
|
+
var i = 0;
|
|
1960
|
+
while (i < tokens.length - 1 &&
|
|
1961
|
+
tokens[i][0] !== token_1.Token.LCParen &&
|
|
1962
|
+
tokens[i][0] !== token_1.Token.Semicolon &&
|
|
1963
|
+
tokens[i][0] !== token_1.Token.EqualsAssmt) {
|
|
1964
|
+
i++;
|
|
1965
|
+
}
|
|
1966
|
+
return tokens[i][0] === token_1.Token.EqualsAssmt;
|
|
1967
|
+
};
|
|
1968
|
+
/** Checks whether an identifier is a quantum gate call. */
|
|
1969
|
+
Parser.prototype.isQuantumGateCall = function (tokens) {
|
|
1970
|
+
var gateName = tokens[0][1];
|
|
1971
|
+
return (this.gates.has(gateName) ||
|
|
1972
|
+
this.standardGates.has(gateName) ||
|
|
1973
|
+
this.customGates.has(gateName));
|
|
1974
|
+
};
|
|
1975
|
+
/** Checks whether an identifier is a subroutine call. */
|
|
1976
|
+
Parser.prototype.isSubroutineCall = function (tokens) {
|
|
1977
|
+
var subroutineName = tokens[0][1];
|
|
1978
|
+
return this.subroutines.has(subroutineName);
|
|
1979
|
+
};
|
|
1980
|
+
/** Checks whether a number is imaginary. */
|
|
1981
|
+
Parser.prototype.isImaginary = function (token) {
|
|
1982
|
+
if (token.length !== 2) {
|
|
1983
|
+
return false;
|
|
1984
|
+
}
|
|
1985
|
+
return token[1].toString() === "im";
|
|
1986
|
+
};
|
|
1987
|
+
/** Checks whether an identifier is an array. */
|
|
1988
|
+
Parser.prototype.isArray = function (tokens) {
|
|
1989
|
+
if (tokens[0][0] !== token_1.Token.Id) {
|
|
1990
|
+
return false;
|
|
1991
|
+
}
|
|
1992
|
+
var identifierName = tokens[0][1].toString();
|
|
1993
|
+
return this.customArrays.has(identifierName);
|
|
1994
|
+
};
|
|
1995
|
+
/** Checks whether an identifier represents a duration literal unit. */
|
|
1996
|
+
Parser.prototype.isDuration = function (tokens) {
|
|
1997
|
+
var checkToken = tokens[0];
|
|
1998
|
+
if (checkToken.length !== 2 || checkToken[0] !== token_1.Token.Id) {
|
|
1999
|
+
return false;
|
|
2000
|
+
}
|
|
2001
|
+
if (Object.values(ast_1.DurationUnit).includes(checkToken[1].toString())) {
|
|
2002
|
+
return true;
|
|
2003
|
+
}
|
|
2004
|
+
return false;
|
|
2005
|
+
};
|
|
2006
|
+
/** TODO : update this
|
|
2007
|
+
* Validates whether a register or gate identifier.
|
|
2008
|
+
* @param identifier - The identifier to validate.
|
|
2009
|
+
* @return Boolean indicating successful validation or not.
|
|
2010
|
+
*/
|
|
2011
|
+
Parser.prototype.validateIdentifier = function (identifier) {
|
|
2012
|
+
var firstChar = identifier[0];
|
|
2013
|
+
return /^[a-z]$/.test(firstChar);
|
|
2014
|
+
};
|
|
2015
|
+
return Parser;
|
|
2016
|
+
}());
|
|
2017
|
+
/**
|
|
2018
|
+
* Checks if a token represents a type.
|
|
2019
|
+
*/
|
|
2020
|
+
function isTypeToken(token) {
|
|
2021
|
+
return (token === token_1.Token.Float ||
|
|
2022
|
+
token === token_1.Token.Int ||
|
|
2023
|
+
token === token_1.Token.UInt ||
|
|
2024
|
+
token === token_1.Token.Bool ||
|
|
2025
|
+
token === token_1.Token.Duration ||
|
|
2026
|
+
token === token_1.Token.Angle ||
|
|
2027
|
+
token === token_1.Token.Stretch ||
|
|
2028
|
+
token === token_1.Token.Bit);
|
|
2029
|
+
}
|
|
2030
|
+
exports.default = Parser;
|