qasm-ts 1.1.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +13 -0
- package/.github/workflows/draft-pdf.yml +24 -0
- package/CONTRIBUTING.md +3 -0
- package/LICENSE +201 -0
- package/dist/errors.js +128 -2
- package/dist/lexer.js +110 -291
- package/dist/main.js +123 -18
- package/dist/parser.js +117 -482
- package/dist/{ast.js → qasm2/ast.js} +71 -2
- package/dist/qasm2/lexer.js +489 -0
- package/dist/qasm2/parser.js +659 -0
- package/dist/qasm2/token.js +160 -0
- package/dist/qasm3/ast.js +1081 -0
- package/dist/qasm3/lexer.js +673 -0
- package/dist/qasm3/parser.js +2083 -0
- package/dist/qasm3/token.js +425 -0
- package/dist/version.js +57 -0
- package/docs/assets/hierarchy.js +1 -0
- package/docs/custom.css +3 -0
- package/docs/docs-readme.md +208 -0
- package/docs/index.html +17 -0
- package/docs/typedoc/.nojekyll +1 -0
- package/docs/typedoc/assets/custom.css +3 -0
- package/docs/typedoc/assets/hierarchy.js +1 -0
- package/docs/typedoc/assets/highlight.css +99 -0
- package/docs/typedoc/assets/icons.js +18 -0
- package/docs/typedoc/assets/icons.svg +1 -0
- package/docs/typedoc/assets/main.js +60 -0
- package/docs/typedoc/assets/navigation.js +1 -0
- package/docs/typedoc/assets/search.js +1 -0
- package/docs/typedoc/assets/style.css +1633 -0
- package/docs/typedoc/classes/Error_Handling.BadArgumentError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadBarrierError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadClassicalTypeError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadConditionalError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadCregError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadEqualsError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadExpressionError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadGateError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadIncludeError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadLoopError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadMeasurementError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadParameterError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadQregError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadQuantumInstructionError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadStringLiteralError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.BadSubroutineError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.MissingBraceError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.MissingSemicolonError.html +12 -0
- package/docs/typedoc/classes/Error_Handling.UnsupportedOpenQASMVersionError.html +12 -0
- package/docs/typedoc/classes/Version_Management.OpenQASMVersion.html +16 -0
- package/docs/typedoc/classes/qasm2_ast.ApplyGate.html +6 -0
- package/docs/typedoc/classes/qasm2_ast.AstNode.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Barrier.html +5 -0
- package/docs/typedoc/classes/qasm2_ast.CReg.html +5 -0
- package/docs/typedoc/classes/qasm2_ast.Cos.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Divide.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Exp.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Gate.html +7 -0
- package/docs/typedoc/classes/qasm2_ast.Id.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.If.html +6 -0
- package/docs/typedoc/classes/qasm2_ast.Include.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.Ln.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Measure.html +7 -0
- package/docs/typedoc/classes/qasm2_ast.Minus.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.NNInteger.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.Opaque.html +6 -0
- package/docs/typedoc/classes/qasm2_ast.Pi.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Plus.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Power.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.QReg.html +5 -0
- package/docs/typedoc/classes/qasm2_ast.Real.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.Sin.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Sqrt.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Tan.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Times.html +3 -0
- package/docs/typedoc/classes/qasm2_ast.Variable.html +4 -0
- package/docs/typedoc/classes/qasm2_ast.Version.html +4 -0
- package/docs/typedoc/classes/qasm2_lexer.default.html +57 -0
- package/docs/typedoc/classes/qasm2_parser.default.html +93 -0
- package/docs/typedoc/classes/qasm3_ast.AliasStatement.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.AngleType.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Arithmetic.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.ArrayAccess.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.ArrayDeclaration.html +7 -0
- package/docs/typedoc/classes/qasm3_ast.ArrayInitializer.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.ArrayReference.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.AssignmentStatement.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.AstNode.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.Binary.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.BitType.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.BitstringLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.BoolType.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.BooleanLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.BoxDefinition.html +7 -0
- package/docs/typedoc/classes/qasm3_ast.BranchingStatement.html +8 -0
- package/docs/typedoc/classes/qasm3_ast.BreakStatement.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.CalibrationGrammarDeclaration.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.CaseStatement.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.Cast.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.ClassicalDeclaration.html +7 -0
- package/docs/typedoc/classes/qasm3_ast.ClassicalType.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.ComplexType.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.ContinueStatement.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.DefaultStatement.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.DurationLiteral.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.DurationOf.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.DurationType.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.Euler.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.Expression.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.ExternSignature.html +8 -0
- package/docs/typedoc/classes/qasm3_ast.FloatLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.FloatType.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.ForLoopStatement.html +12 -0
- package/docs/typedoc/classes/qasm3_ast.HardwareQubit.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.IODeclaration.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.Identifier.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.ImaginaryLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Include.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.IndexSet.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.IntType.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.IntegerLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.MathFunction.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.NumericLiteral.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Parameters.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Pi.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.ProgramBlock.html +7 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumBarrier.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumBlock.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumDeclaration.html +8 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumDelay.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumGateCall.html +9 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumGateDefinition.html +9 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumGateModifier.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumMeasurement.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumMeasurementAssignment.html +8 -0
- package/docs/typedoc/classes/qasm3_ast.QuantumReset.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Range.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.ReturnStatement.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.SizeOf.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.Statement.html +12 -0
- package/docs/typedoc/classes/qasm3_ast.StretchType.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.SubroutineBlock.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.SubroutineCall.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.SubroutineDefinition.html +10 -0
- package/docs/typedoc/classes/qasm3_ast.SubscriptedIdentifier.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.SwitchStatement.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.Tau.html +3 -0
- package/docs/typedoc/classes/qasm3_ast.TrigFunction.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.UIntType.html +4 -0
- package/docs/typedoc/classes/qasm3_ast.Unary.html +5 -0
- package/docs/typedoc/classes/qasm3_ast.Version.html +6 -0
- package/docs/typedoc/classes/qasm3_ast.WhileLoopStatement.html +6 -0
- package/docs/typedoc/classes/qasm3_lexer.default.html +71 -0
- package/docs/typedoc/classes/qasm3_parser.default.html +237 -0
- package/docs/typedoc/enums/Version_Management.OpenQASMMajorVersion.html +4 -0
- package/docs/typedoc/enums/qasm2_token.Token.html +42 -0
- package/docs/typedoc/enums/qasm3_ast.ArithmeticOp.html +9 -0
- package/docs/typedoc/enums/qasm3_ast.ArrayReferenceModifier.html +4 -0
- package/docs/typedoc/enums/qasm3_ast.BinaryOp.html +15 -0
- package/docs/typedoc/enums/qasm3_ast.DurationUnit.html +7 -0
- package/docs/typedoc/enums/qasm3_ast.IOModifier.html +4 -0
- package/docs/typedoc/enums/qasm3_ast.MathFunctionTypes.html +12 -0
- package/docs/typedoc/enums/qasm3_ast.QuantumGateModifierName.html +6 -0
- package/docs/typedoc/enums/qasm3_ast.TrigFunctionTypes.html +8 -0
- package/docs/typedoc/enums/qasm3_ast.UnaryOp.html +5 -0
- package/docs/typedoc/enums/qasm3_token.Token.html +113 -0
- package/docs/typedoc/functions/Lexing.lex.html +24 -0
- package/docs/typedoc/functions/Main_Functions.parseFile.html +13 -0
- package/docs/typedoc/functions/Main_Functions.parseString.html +19 -0
- package/docs/typedoc/functions/Parsing.parse.html +15 -0
- package/docs/typedoc/functions/qasm2_token.inverseLookup.html +3 -0
- package/docs/typedoc/functions/qasm2_token.lookup.html +4 -0
- package/docs/typedoc/functions/qasm2_token.notParam.html +3 -0
- package/docs/typedoc/functions/qasm3_token.inverseLookup.html +9 -0
- package/docs/typedoc/functions/qasm3_token.lookup.html +10 -0
- package/docs/typedoc/functions/qasm3_token.notParam.html +11 -0
- package/docs/typedoc/hierarchy.html +1 -0
- package/docs/typedoc/index.html +76 -0
- package/docs/typedoc/modules/Error_Handling.html +5 -0
- package/docs/typedoc/modules/Lexing.html +20 -0
- package/docs/typedoc/modules/Main_Functions.html +2 -0
- package/docs/typedoc/modules/Parsing.html +24 -0
- package/docs/typedoc/modules/Version_Management.html +8 -0
- package/docs/typedoc/modules/qasm2_ast.html +22 -0
- package/docs/typedoc/modules/qasm2_lexer.html +24 -0
- package/docs/typedoc/modules/qasm2_parser.html +21 -0
- package/docs/typedoc/modules/qasm2_token.html +15 -0
- package/docs/typedoc/modules/qasm3_ast.html +26 -0
- package/docs/typedoc/modules/qasm3_lexer.html +25 -0
- package/docs/typedoc/modules/qasm3_parser.html +25 -0
- package/docs/typedoc/modules/qasm3_token.html +15 -0
- package/docs/typedoc/modules.html +1 -0
- package/docs/typedoc/types/Error_Handling.ReturnErrorConstructor.html +2 -0
- package/docs/typedoc.json +47 -0
- package/package.json +10 -5
- package/paper/jats/paper.jats +464 -0
- package/paper/main.bib +191 -0
- package/paper/paper.md +166 -0
- package/paper/paper.pdf +0 -0
- package/readme.md +117 -47
- package/dist/example.js +0 -22
- package/dist/token.js +0 -89
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenQASM 2.0 Abstract Syntax Tree Node Definitions
|
|
4
|
+
*
|
|
5
|
+
* This module defines the AST node classes for OpenQASM 2.0, which provides
|
|
6
|
+
* a simpler and more limited set of constructs compared to OpenQASM 3.0.
|
|
7
|
+
*
|
|
8
|
+
* OpenQASM 2.0 focuses on:
|
|
9
|
+
* - Basic quantum register (`qreg`) and classical register (`creg`) declarations
|
|
10
|
+
* - Gate definitions and applications
|
|
11
|
+
* - Measurement operations
|
|
12
|
+
* - Simple conditional statements
|
|
13
|
+
* - Basic arithmetic expressions
|
|
14
|
+
*
|
|
15
|
+
* Key limitations compared to 3.0:
|
|
16
|
+
* - No advanced classical types (only registers)
|
|
17
|
+
* - No control flow structures (loops, complex conditionals)
|
|
18
|
+
* - No function definitions or subroutines
|
|
19
|
+
* - Limited expression capabilities
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*
|
|
23
|
+
* @example Basic OpenQASM 2.0 constructs
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Quantum register: qreg q[2];
|
|
26
|
+
* new QReg('q', 2)
|
|
27
|
+
*
|
|
28
|
+
* // Gate application: h q[0];
|
|
29
|
+
* new ApplyGate('h', [['q', 0]], [])
|
|
30
|
+
*
|
|
31
|
+
* // Measurement: measure q[0] -> c[0];
|
|
32
|
+
* new Measure('q', 'c', 0, 0)
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
2
35
|
var __extends = (this && this.__extends) || (function () {
|
|
3
36
|
var extendStatics = function (d, b) {
|
|
4
37
|
extendStatics = Object.setPrototypeOf ||
|
|
@@ -14,8 +47,8 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
14
47
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
48
|
};
|
|
16
49
|
})();
|
|
17
|
-
exports
|
|
18
|
-
exports.Variable = exports.Real = exports.NNInteger = exports.Pi = exports.Sqrt = exports.Ln = exports.Exp = exports.Tan = exports.Cos = exports.Sin = exports.Power = exports.Times = exports.Minus = exports.Plus = exports.Divide = exports.Id = exports.If = exports.Gate = exports.ApplyGate = exports.Measure = exports.Barrier = exports.CReg = exports.QReg = exports.AstNode = void 0;
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.Variable = exports.Real = exports.NNInteger = exports.Pi = exports.Sqrt = exports.Ln = exports.Exp = exports.Tan = exports.Cos = exports.Sin = exports.Power = exports.Times = exports.Minus = exports.Plus = exports.Divide = exports.Id = exports.If = exports.Opaque = exports.Gate = exports.ApplyGate = exports.Measure = exports.Barrier = exports.CReg = exports.QReg = exports.Include = exports.Version = exports.AstNode = void 0;
|
|
19
52
|
/** Base class representing a basic AST node. */
|
|
20
53
|
var AstNode = /** @class */ (function () {
|
|
21
54
|
function AstNode() {
|
|
@@ -23,6 +56,28 @@ var AstNode = /** @class */ (function () {
|
|
|
23
56
|
return AstNode;
|
|
24
57
|
}());
|
|
25
58
|
exports.AstNode = AstNode;
|
|
59
|
+
/** Class representing the version statement. */
|
|
60
|
+
var Version = /** @class */ (function (_super) {
|
|
61
|
+
__extends(Version, _super);
|
|
62
|
+
function Version(version) {
|
|
63
|
+
var _this = _super.call(this) || this;
|
|
64
|
+
_this.version = version;
|
|
65
|
+
return _this;
|
|
66
|
+
}
|
|
67
|
+
return Version;
|
|
68
|
+
}(AstNode));
|
|
69
|
+
exports.Version = Version;
|
|
70
|
+
/** Class representing an include statement. */
|
|
71
|
+
var Include = /** @class */ (function (_super) {
|
|
72
|
+
__extends(Include, _super);
|
|
73
|
+
function Include(filename) {
|
|
74
|
+
var _this = _super.call(this) || this;
|
|
75
|
+
_this.filename = filename;
|
|
76
|
+
return _this;
|
|
77
|
+
}
|
|
78
|
+
return Include;
|
|
79
|
+
}(AstNode));
|
|
80
|
+
exports.Include = Include;
|
|
26
81
|
/** Class representing a qubit register. */
|
|
27
82
|
var QReg = /** @class */ (function (_super) {
|
|
28
83
|
__extends(QReg, _super);
|
|
@@ -122,6 +177,20 @@ var Gate = /** @class */ (function (_super) {
|
|
|
122
177
|
return Gate;
|
|
123
178
|
}(AstNode));
|
|
124
179
|
exports.Gate = Gate;
|
|
180
|
+
/** Class representing an opaque gate declaration (only available in OpenQASM 2.x versions) */
|
|
181
|
+
var Opaque = /** @class */ (function (_super) {
|
|
182
|
+
__extends(Opaque, _super);
|
|
183
|
+
function Opaque(name, qubits, params) {
|
|
184
|
+
if (params === void 0) { params = []; }
|
|
185
|
+
var _this = _super.call(this) || this;
|
|
186
|
+
_this.name = name;
|
|
187
|
+
_this.qubits = qubits;
|
|
188
|
+
_this.params = params;
|
|
189
|
+
return _this;
|
|
190
|
+
}
|
|
191
|
+
return Opaque;
|
|
192
|
+
}(AstNode));
|
|
193
|
+
exports.Opaque = Opaque;
|
|
125
194
|
/** Class representing conditional. */
|
|
126
195
|
var If = /** @class */ (function (_super) {
|
|
127
196
|
__extends(If, _super);
|
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenQASM 2.0 Lexical Analyzer
|
|
4
|
+
*
|
|
5
|
+
* This module implements the lexer for OpenQASM 2.0, which provides a simpler
|
|
6
|
+
* token set compared to OpenQASM 3.0. The lexer focuses on basic quantum circuit
|
|
7
|
+
* constructs without the advanced classical programming features of version 3.0.
|
|
8
|
+
*
|
|
9
|
+
* Key characteristics of OpenQASM 2.0 lexing:
|
|
10
|
+
* - **Limited token set**: Basic quantum and classical registers only
|
|
11
|
+
* - **Simple operators**: Basic arithmetic and comparison operators
|
|
12
|
+
* - **No control flow**: No tokens for loops, conditionals, or functions
|
|
13
|
+
* - **Gate-focused**: Emphasis on gate definitions and applications
|
|
14
|
+
* - **Mathematical functions**: Built-in math functions (sin, cos, etc.)
|
|
15
|
+
*
|
|
16
|
+
* Supported constructs:
|
|
17
|
+
* - Quantum registers (`qreg`) and classical registers (`creg`)
|
|
18
|
+
* - Gate definitions and applications
|
|
19
|
+
* - Measurements with arrow notation (`->`)
|
|
20
|
+
* - Basic arithmetic expressions for gate parameters
|
|
21
|
+
* - Include statements for library files
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
24
|
+
*
|
|
25
|
+
* @example OpenQASM 2.0 lexing
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const lexer = new Lexer('qreg q[2]; h q[0]; measure q -> c;');
|
|
28
|
+
* const tokens = lexer.lex();
|
|
29
|
+
* // Produces tokens for register declaration, gate, and measurement
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
var token_1 = require("./token");
|
|
34
|
+
var errors_1 = require("../errors");
|
|
35
|
+
/**
|
|
36
|
+
* Handles throwing lexer errors with basic stack trace.
|
|
37
|
+
* @param error - The error to throw.
|
|
38
|
+
* @param number - The line number in the source code.
|
|
39
|
+
* @param code - The source code that the error is about.
|
|
40
|
+
*/
|
|
41
|
+
function throwLexerError(error, line, code) {
|
|
42
|
+
throw new error("Line ".concat(line, ": ").concat(code));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns whether a given character could be an element of a numeric value.
|
|
46
|
+
* @param c - The character.
|
|
47
|
+
* @return Whether the character is numeric.
|
|
48
|
+
*/
|
|
49
|
+
function isNumeric(c) {
|
|
50
|
+
return c == "." || !isNaN(parseInt(c));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Returns whether a given character is a letter.
|
|
54
|
+
* @param c - The character.
|
|
55
|
+
* @param matchCase - Whether to check for a letter that is upper case, lower case, or either. (optional)
|
|
56
|
+
* @return Whether the character is a letter.
|
|
57
|
+
*/
|
|
58
|
+
function isLetter(c, matchCase) {
|
|
59
|
+
switch (matchCase) {
|
|
60
|
+
case "upper":
|
|
61
|
+
return /^[A-Z]$/.test(c);
|
|
62
|
+
case "lower":
|
|
63
|
+
return /^[a-z]$/.test(c);
|
|
64
|
+
default:
|
|
65
|
+
return /^[A-Za-z]$/.test(c);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns whether a given character is unicode.
|
|
70
|
+
* @param c - The character.
|
|
71
|
+
* @param excludePi - Whether to exclude the Pi symbol from consideration.
|
|
72
|
+
* @return - Whether the given character is valid unicode.
|
|
73
|
+
*/
|
|
74
|
+
function isUnicode(c, excludePi) {
|
|
75
|
+
var isBasicUnicode = /^\u0000-\u00ff/.test(c);
|
|
76
|
+
switch (excludePi) {
|
|
77
|
+
case true:
|
|
78
|
+
return isBasicUnicode && c !== "\u03C0";
|
|
79
|
+
case false:
|
|
80
|
+
return isBasicUnicode;
|
|
81
|
+
default:
|
|
82
|
+
return isBasicUnicode;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Returns whether a given character is alphanumeric.
|
|
87
|
+
* @param c - The character.
|
|
88
|
+
* @return Whether the character is alphanumeric.
|
|
89
|
+
*/
|
|
90
|
+
function isAlpha(c) {
|
|
91
|
+
return /^[0-9a-zA-Z]+$/.test(c);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Returns whether a given character is a newline character.
|
|
95
|
+
* @param c - The character.
|
|
96
|
+
* @return Whether the character is a newline.
|
|
97
|
+
*/
|
|
98
|
+
function isNewline(c) {
|
|
99
|
+
return /\n|\r(?!\n)|\u2028|\u2029|\r\n/.test(c);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* OpenQASM 2.0 Lexical Analyzer
|
|
103
|
+
*
|
|
104
|
+
* A simpler lexer implementation focused on the core quantum circuit description
|
|
105
|
+
* features of OpenQASM 2.0. This lexer handles the essential constructs needed
|
|
106
|
+
* for basic quantum programming without the complexity of classical programming
|
|
107
|
+
* language features.
|
|
108
|
+
*
|
|
109
|
+
* @example Basic OpenQASM 2.0 tokenization
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const source = `
|
|
112
|
+
* OPENQASM 2.0;
|
|
113
|
+
* include "qelib1.inc";
|
|
114
|
+
* qreg q[2];
|
|
115
|
+
* creg c[2];
|
|
116
|
+
* h q[0];
|
|
117
|
+
* cx q[0],q[1];
|
|
118
|
+
* measure q -> c;
|
|
119
|
+
* `;
|
|
120
|
+
*
|
|
121
|
+
* const lexer = new Lexer(source);
|
|
122
|
+
* const tokens = lexer.lex();
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
var Lexer = /** @class */ (function () {
|
|
126
|
+
/**
|
|
127
|
+
* Creates a lexer.
|
|
128
|
+
* @param input - The string to lex.
|
|
129
|
+
* @param cursor - The starting cursor position.
|
|
130
|
+
*/
|
|
131
|
+
function Lexer(input, cursor) {
|
|
132
|
+
if (cursor === void 0) { cursor = 0; }
|
|
133
|
+
var _this = this;
|
|
134
|
+
/**
|
|
135
|
+
* Verifies that all appropriate lines end with a semicolon.
|
|
136
|
+
* @return A tuple of the status and if False, returns the problematic line.
|
|
137
|
+
*/
|
|
138
|
+
this.verifyInput = function () {
|
|
139
|
+
var lines = _this.input.split(/\n|\r(?!\n)|\u2028|\u2029|\r\n/g);
|
|
140
|
+
for (var i = 0; i < lines.length; i++) {
|
|
141
|
+
if (!lines[i].startsWith("//") &&
|
|
142
|
+
!(lines[i].length == 0) &&
|
|
143
|
+
!lines[i].includes("gate") &&
|
|
144
|
+
!(lines[i].trim() == "{" || lines[i].trim() == "}") &&
|
|
145
|
+
!lines[i].includes(";")) {
|
|
146
|
+
return [false, i + 1, lines[i]];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return [true, null, null];
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Calling this method lexes the code represented by the provided string.
|
|
153
|
+
* @return An array of tokens and their corresponding values.
|
|
154
|
+
*/
|
|
155
|
+
this.lex = function () {
|
|
156
|
+
var tokens = [];
|
|
157
|
+
var token;
|
|
158
|
+
var verifyInputResult = _this.verifyInput();
|
|
159
|
+
if (!verifyInputResult[0]) {
|
|
160
|
+
throwLexerError(errors_1.MissingSemicolonError, verifyInputResult[1], verifyInputResult[2]);
|
|
161
|
+
}
|
|
162
|
+
while (_this.cursor < _this.input.length) {
|
|
163
|
+
token = _this.nextToken();
|
|
164
|
+
if (token) {
|
|
165
|
+
tokens.push(token);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return tokens;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Reads a character and advances the cursor.
|
|
172
|
+
* @param num - Optional cursor position modifier.
|
|
173
|
+
*/
|
|
174
|
+
this.readChar = function (num) {
|
|
175
|
+
if (num === void 0) { num = 1; }
|
|
176
|
+
_this.cursor += num;
|
|
177
|
+
return _this.input[_this.cursor - num];
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Advances the cusor past the next comment.
|
|
181
|
+
*/
|
|
182
|
+
this.skipComment = function () {
|
|
183
|
+
var char = "";
|
|
184
|
+
while (!isNewline(char)) {
|
|
185
|
+
char = _this.readChar();
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Determines whether the next character to process equals a given character.
|
|
190
|
+
* @param c - The given character.
|
|
191
|
+
* @return Whether the next character equals the given character.
|
|
192
|
+
*/
|
|
193
|
+
this.peekEq = function (c) { return _this.peek() == c; };
|
|
194
|
+
/**
|
|
195
|
+
* Reads a character without advancing the cursor.
|
|
196
|
+
* @param index - Optional peek position offset.
|
|
197
|
+
*/
|
|
198
|
+
this.peek = function () { return _this.input[_this.cursor]; };
|
|
199
|
+
/**
|
|
200
|
+
* Reads a numeric value.
|
|
201
|
+
* @return The numeric value as a string.
|
|
202
|
+
*/
|
|
203
|
+
this.readNumeric = function () {
|
|
204
|
+
var num = "";
|
|
205
|
+
while (isNumeric(_this.peek())) {
|
|
206
|
+
num += _this.readChar();
|
|
207
|
+
}
|
|
208
|
+
return num;
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* Reads an identifier.
|
|
212
|
+
* @return The identifier as a string.
|
|
213
|
+
*/
|
|
214
|
+
this.readIdentifier = function () {
|
|
215
|
+
var id = "";
|
|
216
|
+
var next = _this.peek();
|
|
217
|
+
while (isAlpha(next) || next == "_" || isUnicode(next)) {
|
|
218
|
+
id += _this.readChar();
|
|
219
|
+
next = _this.peek();
|
|
220
|
+
}
|
|
221
|
+
return id;
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* Reads a string literal.
|
|
225
|
+
* @param terminator - The literal's termination character.
|
|
226
|
+
* @return The literal as a string.
|
|
227
|
+
*/
|
|
228
|
+
this.readStringLiteral = function (terminator) {
|
|
229
|
+
var lit = "";
|
|
230
|
+
var char = "";
|
|
231
|
+
while (!(terminator == char)) {
|
|
232
|
+
char = _this.readChar();
|
|
233
|
+
lit += char;
|
|
234
|
+
}
|
|
235
|
+
return lit;
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Advances the cusor past the next block of whitespace.
|
|
239
|
+
*/
|
|
240
|
+
this.skipWhitespace = function () {
|
|
241
|
+
while (" \t\n\r\v".indexOf(_this.peek()) > -1) {
|
|
242
|
+
_this.cursor += 1;
|
|
243
|
+
}
|
|
244
|
+
return null;
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Lexes the next token.
|
|
248
|
+
* @return The next token and its corresponding value.
|
|
249
|
+
*/
|
|
250
|
+
this.nextToken = function () {
|
|
251
|
+
_this.skipWhitespace();
|
|
252
|
+
if (_this.cursor == _this.input.length) {
|
|
253
|
+
return [token_1.Token.EndOfFile];
|
|
254
|
+
}
|
|
255
|
+
var char = _this.peek();
|
|
256
|
+
_this.readChar();
|
|
257
|
+
switch (char) {
|
|
258
|
+
case "=":
|
|
259
|
+
if (_this.peekEq("=")) {
|
|
260
|
+
_this.readChar();
|
|
261
|
+
return [token_1.Token.Equals];
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
throwLexerError(errors_1.BadEqualsError, _this.getLineNumber(_this.cursor), _this.getCurrentLine(_this.cursor));
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case "-":
|
|
268
|
+
if (_this.peekEq(">")) {
|
|
269
|
+
_this.readChar();
|
|
270
|
+
return [token_1.Token.Arrow];
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
return [token_1.Token.Minus];
|
|
274
|
+
}
|
|
275
|
+
case "+":
|
|
276
|
+
return [token_1.Token.Plus];
|
|
277
|
+
case "*":
|
|
278
|
+
return [token_1.Token.Times];
|
|
279
|
+
case "^":
|
|
280
|
+
return [token_1.Token.Power];
|
|
281
|
+
case ";":
|
|
282
|
+
return [token_1.Token.Semicolon];
|
|
283
|
+
case ",":
|
|
284
|
+
return [token_1.Token.Comma];
|
|
285
|
+
case "(":
|
|
286
|
+
return [token_1.Token.LParen];
|
|
287
|
+
case "[":
|
|
288
|
+
return [token_1.Token.LSParen];
|
|
289
|
+
case "{":
|
|
290
|
+
return [token_1.Token.LCParen];
|
|
291
|
+
case ")":
|
|
292
|
+
return [token_1.Token.RParen];
|
|
293
|
+
case "]":
|
|
294
|
+
return [token_1.Token.RSParen];
|
|
295
|
+
case "}":
|
|
296
|
+
return [token_1.Token.RCParen];
|
|
297
|
+
case "/":
|
|
298
|
+
if (_this.peekEq("/")) {
|
|
299
|
+
_this.skipComment();
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
return [token_1.Token.Divide];
|
|
304
|
+
}
|
|
305
|
+
case "g":
|
|
306
|
+
if (_this.input[_this.cursor] == "a" &&
|
|
307
|
+
_this.input[_this.cursor + 1] == "t" &&
|
|
308
|
+
_this.input[_this.cursor + 2] == "e") {
|
|
309
|
+
_this.readChar(3);
|
|
310
|
+
return [token_1.Token.Gate];
|
|
311
|
+
}
|
|
312
|
+
{
|
|
313
|
+
var literal = char + _this.readIdentifier();
|
|
314
|
+
return [(0, token_1.lookup)(literal), literal];
|
|
315
|
+
}
|
|
316
|
+
case "q":
|
|
317
|
+
if (_this.input[_this.cursor] == "r" &&
|
|
318
|
+
_this.input[_this.cursor + 1] == "e" &&
|
|
319
|
+
_this.input[_this.cursor + 2] == "g") {
|
|
320
|
+
_this.readChar(3);
|
|
321
|
+
return [token_1.Token.QReg];
|
|
322
|
+
}
|
|
323
|
+
{
|
|
324
|
+
var qregLit = char + _this.readIdentifier();
|
|
325
|
+
return [(0, token_1.lookup)(qregLit), qregLit];
|
|
326
|
+
}
|
|
327
|
+
case "c":
|
|
328
|
+
if (_this.input[_this.cursor] == "r" &&
|
|
329
|
+
_this.input[_this.cursor + 1] == "e" &&
|
|
330
|
+
_this.input[_this.cursor + 2] == "g") {
|
|
331
|
+
_this.readChar(3);
|
|
332
|
+
return [token_1.Token.CReg];
|
|
333
|
+
}
|
|
334
|
+
{
|
|
335
|
+
var cregLit = char + _this.readIdentifier();
|
|
336
|
+
return [(0, token_1.lookup)(cregLit), cregLit];
|
|
337
|
+
}
|
|
338
|
+
case "b":
|
|
339
|
+
if (_this.input[_this.cursor] == "a" &&
|
|
340
|
+
_this.input[_this.cursor + 1] == "r" &&
|
|
341
|
+
_this.input[_this.cursor + 2] == "r" &&
|
|
342
|
+
_this.input[_this.cursor + 3] == "i" &&
|
|
343
|
+
_this.input[_this.cursor + 4] == "e" &&
|
|
344
|
+
_this.input[_this.cursor + 5] == "r") {
|
|
345
|
+
_this.readChar(6);
|
|
346
|
+
return [token_1.Token.Barrier];
|
|
347
|
+
}
|
|
348
|
+
{
|
|
349
|
+
var barLit = char + _this.readIdentifier();
|
|
350
|
+
return [(0, token_1.lookup)(barLit), barLit];
|
|
351
|
+
}
|
|
352
|
+
case "m":
|
|
353
|
+
if (_this.input[_this.cursor] == "e" &&
|
|
354
|
+
_this.input[_this.cursor + 1] == "a" &&
|
|
355
|
+
_this.input[_this.cursor + 2] == "s" &&
|
|
356
|
+
_this.input[_this.cursor + 3] == "u" &&
|
|
357
|
+
_this.input[_this.cursor + 4] == "r" &&
|
|
358
|
+
_this.input[_this.cursor + 5] == "e") {
|
|
359
|
+
_this.readChar(6);
|
|
360
|
+
return [token_1.Token.Measure];
|
|
361
|
+
}
|
|
362
|
+
{
|
|
363
|
+
var measureLit = char + _this.readIdentifier();
|
|
364
|
+
return [(0, token_1.lookup)(measureLit), measureLit];
|
|
365
|
+
}
|
|
366
|
+
case "O":
|
|
367
|
+
if (_this.input[_this.cursor].toLowerCase() == "p" &&
|
|
368
|
+
_this.input[_this.cursor + 1].toLowerCase() == "e" &&
|
|
369
|
+
_this.input[_this.cursor + 2].toLowerCase() == "n" &&
|
|
370
|
+
_this.input[_this.cursor + 3] == "Q" &&
|
|
371
|
+
_this.input[_this.cursor + 4] == "A" &&
|
|
372
|
+
_this.input[_this.cursor + 5] == "S" &&
|
|
373
|
+
_this.input[_this.cursor + 6] == "M") {
|
|
374
|
+
_this.readChar(7);
|
|
375
|
+
var offset = 0;
|
|
376
|
+
while (_this.cursor + offset < _this.input.length &&
|
|
377
|
+
" \t".indexOf(_this.input[_this.cursor + offset]) > -1) {
|
|
378
|
+
offset++;
|
|
379
|
+
}
|
|
380
|
+
// Read the major version
|
|
381
|
+
var majorVersion = "";
|
|
382
|
+
while (_this.cursor + offset < _this.input.length &&
|
|
383
|
+
!isNaN(parseInt(_this.input[_this.cursor + offset], 10))) {
|
|
384
|
+
majorVersion += _this.input[_this.cursor + offset];
|
|
385
|
+
offset++;
|
|
386
|
+
}
|
|
387
|
+
// Attempt to read the minor version
|
|
388
|
+
var minorVersion = undefined;
|
|
389
|
+
if (_this.input[_this.cursor + offset] == ".") {
|
|
390
|
+
offset++;
|
|
391
|
+
minorVersion = "";
|
|
392
|
+
while (_this.cursor + offset < _this.input.length &&
|
|
393
|
+
!isNaN(parseInt(_this.input[_this.cursor + offset], 10))) {
|
|
394
|
+
minorVersion += _this.input[_this.cursor + offset];
|
|
395
|
+
offset++;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// Parse major and minor versions
|
|
399
|
+
var major = parseInt(majorVersion, 10);
|
|
400
|
+
var minor = minorVersion ? parseInt(minorVersion, 10) : undefined;
|
|
401
|
+
if (major !== 2) {
|
|
402
|
+
throw new errors_1.UnsupportedOpenQASMVersionError("Unsupported OpenQASM version detected: ".concat(majorVersion, ".").concat(minor !== null && minor !== void 0 ? minor : 0));
|
|
403
|
+
}
|
|
404
|
+
return [token_1.Token.OpenQASM];
|
|
405
|
+
}
|
|
406
|
+
{
|
|
407
|
+
var openQasmLit = char + _this.readIdentifier();
|
|
408
|
+
return [token_1.lookup[openQasmLit], openQasmLit];
|
|
409
|
+
}
|
|
410
|
+
case "i":
|
|
411
|
+
if (_this.input[_this.cursor] == "n" &&
|
|
412
|
+
_this.input[_this.cursor + 1] == "c" &&
|
|
413
|
+
_this.input[_this.cursor + 2] == "l" &&
|
|
414
|
+
_this.input[_this.cursor + 3] == "u" &&
|
|
415
|
+
_this.input[_this.cursor + 4] == "d" &&
|
|
416
|
+
_this.input[_this.cursor + 5] == "e") {
|
|
417
|
+
_this.readChar(6);
|
|
418
|
+
return [token_1.Token.Include];
|
|
419
|
+
}
|
|
420
|
+
{
|
|
421
|
+
var includeLit = char + _this.readIdentifier();
|
|
422
|
+
return [(0, token_1.lookup)(includeLit), includeLit];
|
|
423
|
+
}
|
|
424
|
+
case "o":
|
|
425
|
+
if (_this.input[_this.cursor] == "p" &&
|
|
426
|
+
_this.input[_this.cursor + 1] == "a" &&
|
|
427
|
+
_this.input[_this.cursor + 2] == "q" &&
|
|
428
|
+
_this.input[_this.cursor + 3] == "u" &&
|
|
429
|
+
_this.input[_this.cursor + 4] == "e") {
|
|
430
|
+
_this.readChar(5);
|
|
431
|
+
return [token_1.Token.Opaque];
|
|
432
|
+
}
|
|
433
|
+
{
|
|
434
|
+
var opaqueLit = char + _this.readIdentifier();
|
|
435
|
+
return [(0, token_1.lookup)(opaqueLit), opaqueLit];
|
|
436
|
+
}
|
|
437
|
+
case '"': {
|
|
438
|
+
var stringLiteral = char + _this.readStringLiteral('"');
|
|
439
|
+
return [token_1.Token.String, stringLiteral];
|
|
440
|
+
}
|
|
441
|
+
case "’": {
|
|
442
|
+
var singleStringLiteral = char + _this.readStringLiteral("’");
|
|
443
|
+
return [token_1.Token.String, singleStringLiteral];
|
|
444
|
+
}
|
|
445
|
+
default:
|
|
446
|
+
if (isLetter(char)) {
|
|
447
|
+
var literal = char + _this.readIdentifier();
|
|
448
|
+
return [(0, token_1.lookup)(literal), literal];
|
|
449
|
+
}
|
|
450
|
+
else if (isNumeric(char)) {
|
|
451
|
+
var num = char + _this.readNumeric();
|
|
452
|
+
if (num.indexOf(".") != -1) {
|
|
453
|
+
return [token_1.Token.Real, parseFloat(num)];
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
return [token_1.Token.NNInteger, parseFloat(num)];
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
return [token_1.Token.Illegal];
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
/**
|
|
465
|
+
* Returns the line number where the current cursor is located.
|
|
466
|
+
* @param cursor - The current cursor position in the input string.
|
|
467
|
+
* @return The line number.
|
|
468
|
+
*/
|
|
469
|
+
this.getLineNumber = function (cursor) {
|
|
470
|
+
return _this.input
|
|
471
|
+
.substring(0, cursor)
|
|
472
|
+
.split(/\n|\r(?!\n)|\u2028|\u2029|\r\n/).length;
|
|
473
|
+
};
|
|
474
|
+
/**
|
|
475
|
+
* Returns the current line of code where the cursor is located.
|
|
476
|
+
* @param cursor - The current cursor position in the input string.
|
|
477
|
+
* @return The specific line where the cursor is located.
|
|
478
|
+
*/
|
|
479
|
+
this.getCurrentLine = function (cursor) {
|
|
480
|
+
var lines = _this.input.split(/\n|\r(?!\n)|\u2028|\u2029|\r\n/);
|
|
481
|
+
var lineNumber = _this.getLineNumber(cursor);
|
|
482
|
+
return lines[lineNumber - 1];
|
|
483
|
+
};
|
|
484
|
+
this.input = input;
|
|
485
|
+
this.cursor = cursor;
|
|
486
|
+
}
|
|
487
|
+
return Lexer;
|
|
488
|
+
}());
|
|
489
|
+
exports.default = Lexer;
|