├── .gitignore ├── crates ├── oq3_semantics │ ├── .gitignore │ ├── src │ │ ├── initialize_ast.rs │ │ ├── display.rs │ │ ├── utils.rs │ │ └── lib.rs │ ├── Cargo.toml │ └── tests │ │ ├── symbol_tests.rs │ │ ├── specification_example_tests.rs │ │ ├── types_test.rs │ │ └── ast_tests.rs ├── pipeline-tests │ ├── tests │ │ ├── snippets │ │ │ ├── reference │ │ │ │ ├── expression │ │ │ │ │ ├── unary_expr.qasm │ │ │ │ │ ├── order_of_ops.qasm │ │ │ │ │ ├── binary_expr.qasm │ │ │ │ │ ├── sub_and_extern_call.qasm │ │ │ │ │ └── built_in_call.qasm │ │ │ │ ├── scope │ │ │ │ │ ├── anonymous_block.qasm │ │ │ │ │ └── nop.qasm │ │ │ │ ├── directives │ │ │ │ │ ├── pragma.qasm │ │ │ │ │ ├── include.qasm │ │ │ │ │ ├── defcalgrammar.qasm │ │ │ │ │ ├── annotations2.qasm │ │ │ │ │ └── annotations.qasm │ │ │ │ ├── control_flow │ │ │ │ │ ├── branch_binop.qasm │ │ │ │ │ ├── loop.qasm │ │ │ │ │ ├── branching.qasm │ │ │ │ │ └── switch.qasm │ │ │ │ ├── pulse │ │ │ │ │ ├── cal.qasm │ │ │ │ │ ├── cal2.qasm │ │ │ │ │ └── defcal.qasm │ │ │ │ ├── subroutine │ │ │ │ │ ├── extern.qasm │ │ │ │ │ ├── subroutine.qasm │ │ │ │ │ └── array.qasm │ │ │ │ ├── declaration │ │ │ │ │ ├── complex2.qasm │ │ │ │ │ ├── complex.qasm │ │ │ │ │ ├── array.qasm │ │ │ │ │ └── declaration.qasm │ │ │ │ ├── gate │ │ │ │ │ ├── gate_modifiers.qasm │ │ │ │ │ └── quantum_gate.qasm │ │ │ │ ├── header.qasm │ │ │ │ ├── assignment │ │ │ │ │ ├── alias.qasm │ │ │ │ │ ├── assignment.qasm │ │ │ │ │ └── slices.qasm │ │ │ │ └── comments │ │ │ │ │ ├── comments.qasm │ │ │ │ │ └── comments_cnot.qasm │ │ │ ├── invalid_oq3p │ │ │ │ ├── declaration │ │ │ │ │ └── bit_array.qasm │ │ │ │ └── directives │ │ │ │ │ ├── pragma1.qasm │ │ │ │ │ ├── pragma2.qasm │ │ │ │ │ └── pragma3.qasm │ │ │ ├── valid_oq3p │ │ │ │ └── directives │ │ │ │ │ └── pragma.qasm │ │ │ └── invalid │ │ │ │ └── statements │ │ │ │ ├── calibration.qasm │ │ │ │ ├── headers.qasm │ │ │ │ ├── const.qasm │ │ │ │ ├── switch.qasm │ │ │ │ ├── io.qasm │ │ │ │ ├── tokens.qasm │ │ │ │ ├── branch.qasm │ │ │ │ ├── measure.qasm │ │ │ │ ├── gate_applications.qasm │ │ │ │ ├── loop.qasm │ │ │ │ └── declarations.qasm │ │ └── snapshots │ │ │ ├── runner__tests__snippets__reference__pulse__cal.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__scope__nop.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__pulse__cal2.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__pulse__cal2.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__pulse__defcal.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__assignment__slices.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__pulse__defcal.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__subroutine__array.qasm-sema.snap │ │ │ ├── runner__tests__snippets__invalid__statements__headers.qasm-parse.snap │ │ │ ├── runner__tests__snippets__invalid__statements__tokens.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__declaration__array.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__subroutine__extern.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__subroutine__subroutine.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__directives__defcalgrammar.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__scope__anonymous_block.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__control_flow__branching.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__directives__include.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__gate__quantum_gate.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__control_flow__branch_binop.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__directives__include.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__expression__built_in_call.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__expression__order_of_ops.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__control_flow__loop.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__declaration__declaration.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__expression__sub_and_extern_call.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__expression__unary_expr.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__directives__pragma.qasm-sema.snap │ │ │ ├── runner__tests__snippets__valid_oq3p__directives__pragma.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__expression__unary_expr.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__expression__unary_expr.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__header.qasm-sema.snap │ │ │ ├── runner__tests__snippets__invalid_oq3p__directives__pragma3.qasm-parse.snap │ │ │ ├── runner__tests__snippets__valid_oq3p__directives__pragma.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__directives__pragma.qasm-parse.snap │ │ │ ├── runner__tests__snippets__valid_oq3p__directives__pragma.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__directives__pragma.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid_oq3p__declaration__bit_array.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__scope__anonymous_block.qasm-parse.snap │ │ │ ├── runner__tests__snippets__invalid_oq3p__directives__pragma2.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__assignment__alias.qasm-sema.snap │ │ │ ├── runner__tests__snippets__invalid_oq3p__directives__pragma3.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__directives__defcalgrammar.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__scope__anonymous_block.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid_oq3p__directives__pragma.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid_oq3p__declaration__bit_array.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid_oq3p__directives__pragma2.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid_oq3p__directives__pragma1.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__expression__binary_expr.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__header.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__directives__include.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__directives__defcalgrammar.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid__statements__calibration.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__pulse__cal.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__declaration__complex2.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__declaration__complex2.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__subroutine__extern.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__control_flow__branch_binop.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__comments__comments.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__pulse__cal.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__comments__comments_cnot.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__control_flow__loop.qasm-parse.snap │ │ │ ├── runner__tests__snippets__invalid__statements__switch.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__gate__quantum_gate.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__expression__order_of_ops.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__expression__sub_and_extern_call.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__gate__gate_modifiers.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__control_flow__branching.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__comments__comments.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__control_flow__branch_binop.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__comments__comments_cnot.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__expression__binary_expr.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__scope__nop.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__header.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid__statements__const.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__pulse__cal2.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__gate__gate_modifiers.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__expression__binary_expr.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__subroutine__extern.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid__statements__calibration.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid__statements__headers.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__declaration__complex.qasm-sema.snap │ │ │ ├── runner__tests__snippets__invalid__statements__io.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__declaration__complex.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__expression__order_of_ops.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__scope__nop.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__directives__annotations2.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__gate__quantum_gate.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__directives__annotations.qasm-sema.snap │ │ │ ├── runner__tests__snippets__reference__pulse__defcal.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__declaration__complex2.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__expression__sub_and_extern_call.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__directives__annotations.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__directives__annotations2.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__gate__gate_modifiers.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__control_flow__loop.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid__statements__branch.qasm-parse.snap │ │ │ ├── runner__tests__snippets__reference__assignment__alias.qasm-parse.snap │ │ │ ├── runner__tests__snippets__invalid__statements__tokens.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__control_flow__branching.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid__statements__const.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__comments__comments.qasm-lex.snap │ │ │ ├── runner__tests__snippets__reference__comments__comments_cnot.qasm-lex.snap │ │ │ ├── runner__tests__snippets__invalid__statements__measure.qasm-parse.snap │ │ │ ├── runner__tests__snippets__invalid__statements__io.qasm-lex.snap │ │ │ └── runner__tests__snippets__reference__assignment__assignment.qasm-parse.snap │ ├── Cargo.toml │ ├── README.md │ └── tools │ │ └── expect_summary.py ├── oq3_syntax │ ├── src │ │ ├── ast │ │ │ ├── generated.rs │ │ │ ├── traits.rs │ │ │ └── type_ext.rs │ │ ├── validation │ │ │ └── block.rs │ │ ├── syntax_error.rs │ │ ├── token_text.rs │ │ └── syntax_node.rs │ └── Cargo.toml ├── oq3_lexer │ └── Cargo.toml ├── oq3_source_file │ ├── Cargo.toml │ └── src │ │ └── lib.rs └── oq3_parser │ ├── Cargo.toml │ └── src │ ├── syntax_kind.rs │ ├── token_set.rs │ ├── lib.rs │ └── input.rs ├── clippy.toml ├── dummy_triagebot.toml ├── .rustfmt.toml ├── CODE_OF_CONDUCT.md ├── .github └── workflows │ ├── release.yml │ └── main.yml ├── Cargo.toml ├── justfile └── NOTICE.txt /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /crates/oq3_semantics/.gitignore: -------------------------------------------------------------------------------- 1 | examples/qasm/ 2 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | # This does not work for some reason. 2 | # filter-map-identitiy = false 3 | 4 | msrv = "1.79.0" 5 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/expression/unary_expr.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | !my_var; 6 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid_oq3p/declaration/bit_array.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | array[bit[8], 2] x; 6 | -------------------------------------------------------------------------------- /dummy_triagebot.toml: -------------------------------------------------------------------------------- 1 | # Presence of this file is checked in sourcegen::project_root in ra_ap_sourcegen 2 | # If this file is not found, codegen is aborted. 3 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/scope/anonymous_block.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | { 6 | int ii = 32; 7 | } 8 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/valid_oq3p/directives/pragma.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: ok 4 | 5 | pragma (((9217#@%^^^*!@#$%^ 6 | #pragma ))!~==}{ 7 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid_oq3p/directives/pragma1.qasm: -------------------------------------------------------------------------------- 1 | // lex: diag 2 | // parse: skip 3 | // sema: skip 4 | 5 | // Invalid identifier token 6 | #pragmaa 1 2 3 7 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/directives/pragma.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: ok 4 | 5 | pragma IO_BIND[2:3] 6 | #pragma __directive_info__ 0 7 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/directives/include.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: panic 3 | // sema: skip 4 | 5 | include 'foo2'; 6 | include "foo"; 7 | include "001"; 8 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/expression/order_of_ops.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | a[1]+2|c*(sin(y)^!3.5*d[3]); 6 | b = bit[8](a)[2:4]; 7 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid_oq3p/directives/pragma2.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | // pragmaa is an ordinary identifier 6 | pragmaa 1 2 3 7 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid_oq3p/directives/pragma3.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | // "pragam" is an invalid identifier. 6 | int pragma = 1; 7 | -------------------------------------------------------------------------------- /crates/oq3_semantics/src/initialize_ast.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use crate::asg; 5 | use crate::symbols; 6 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/control_flow/branch_binop.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | if(spec[i] == 0 && spec[n+i] == 1) { 6 | x q[i]; 7 | } 8 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/expression/binary_expr.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: ok 4 | 5 | int x = 0; 6 | int y = 1; 7 | 8 | 2+2; 9 | 2**2; 10 | x << y; 11 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/pulse/cal.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: todo 3 | // sema: skip 4 | 5 | cal {} 6 | cal {One long, otherwise invalid token.} 7 | cal {Outer {nested} outer} 8 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/subroutine/extern.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: todo 4 | 5 | extern test_kern(bit[5], uint[10], float[16], complex[float[64]]) -> float[6]; 6 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/directives/defcalgrammar.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: todo 3 | // sema: skip 4 | 5 | defcalgrammar 'openpulse'; 6 | defcalgrammar "openpulse"; 7 | defcalgrammar "001"; 8 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/declaration/complex2.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: todo 4 | 5 | complex[float[32]] a = 2.0; 6 | complex[float[32]] b = 1.0; 7 | 8 | complex[float[32]] c = a ** b; 9 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/gate/gate_modifiers.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: ok 4 | 5 | qubit q; 6 | gate g q {} 7 | ctrl(2) @ g q; 8 | negctrl(3) @ g q; 9 | pow(-1./2.) @ g q; 10 | inv @ g q; 11 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/pulse/cal2.qasm: -------------------------------------------------------------------------------- 1 | // lex: todo 2 | // parse: todo 3 | // sema: skip 4 | 5 | cal {} 6 | cal {One long, otherwise invalid token.} 7 | cal {Outer {nested} outer} 8 | cal {£$&£*(")} 9 | 10 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/calibration.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | defcalgrammar "openpulse" defcalgrammar "openpulse"; 6 | defcalgrammar 3; 7 | defcal x $0 -> int[8] -> int[8] {} 8 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/expression/sub_and_extern_call.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | bit x = sub_call(10, "01", q1[0], q2); 6 | int[2] y = extern_call(0.5, 10dt); 7 | ambiguous_call(pi); 8 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/header.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: todo 4 | 5 | OPENQASM 3.0; 6 | include "stdgates.inc"; 7 | input angle[32] param1; 8 | input angle[32] param2; 9 | output bit result; 10 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/control_flow/loop.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | while (i < 10) { 6 | for uint j in {1, 4, 6} reset q[j]; 7 | if (i == 8) break; 8 | else continue; 9 | } 10 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/scope/nop.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: todo 3 | // sema: skip 4 | 5 | nop; 6 | nop $0; 7 | nop $1, $2; 8 | nop q, q[0],; 9 | box { 10 | nop $0; 11 | } 12 | gate x q { 13 | nop q; 14 | } 15 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/control_flow/branching.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | include "stdgates.inc"; 6 | if (x == a) { 7 | for uint i in [0:2:4] x[i] += 1; 8 | } 9 | else CX x[0], x[1]; 10 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/pulse/defcal.qasm: -------------------------------------------------------------------------------- 1 | // lex: todo 2 | // parse: todo 3 | // sema: skip 4 | 5 | defcal x $0 {} 6 | defcal measure $0 -> bit {Outer {nested} outer} 7 | defcal rz(angle[20] theta) q {£$&£*(")} 8 | defcal rz(pi / 2) q {Symbolic expression.} 9 | -------------------------------------------------------------------------------- /crates/oq3_syntax/src/ast/generated.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! This file is actually hand-written, but the submodules are indeed generated. 5 | 6 | pub(crate) mod nodes; 7 | pub(crate) mod tokens; 8 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/headers.qasm: -------------------------------------------------------------------------------- 1 | // lex: diag 2 | // parse: diag 3 | // sema: skip 4 | 5 | OPENQASM int; 6 | OPENQASM 'hello, world'; 7 | OPENQASM 3 3; 8 | OPENQASM 3.x; 9 | include 3; 10 | include include; 11 | include def; 12 | include "hello; 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/gate/quantum_gate.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | include "stdlib.qasm"; 6 | 7 | gate test_gate(theta) a, b { 8 | reset a; 9 | barrier b; 10 | gphase(-theta/2); 11 | CX a, b; 12 | barrier; 13 | } 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/const.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | const myvar; 6 | const myvar = ; 7 | const myvar = 8.0; 8 | input const myvar = 8; 9 | output const myvar = 8; 10 | const input myvar = 8; 11 | const output myvar = 8; 12 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/switch.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | switch () {} 6 | switch (i) { x $0 } 7 | switch (i) { case {} } 8 | switch (i) { case 1,, {} } 9 | switch (i) { default 0 {} } 10 | switch (i) { default, default {} } 11 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/io.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | input int[8]; 6 | output int[8]; 7 | input qreg myvar[4]; 8 | output qreg myvar[4]; 9 | input int[8] myvar = 32; 10 | output int[8] myvar = 32; 11 | input myvar; 12 | output myvar; 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/tokens.qasm: -------------------------------------------------------------------------------- 1 | // lex: diag 2 | // parse: diag 3 | // sema: skip 4 | 5 | #; 6 | 3x; 7 | x@x; 8 | 3.4.3; 9 | 3.4e3e3; 10 | // Bad integer literals. 11 | 3__4; 12 | 3_4_; 13 | 0b123; 14 | 0B123; 15 | 0o789; 16 | 0O789; 17 | 0x12g; 18 | 0X12g; 19 | 12af; 20 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/branch.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | if true x $0; 6 | if false { x $0; } 7 | if (myvar += 1) { x $0; } 8 | if (int[8] myvar = 1) { x $0; } 9 | if (true); 10 | if (true) else x $0; 11 | if (true) else (false) x $0; 12 | if (reset $0) { x $1; } 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/assignment/alias.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: todo 4 | 5 | bit[2] a; 6 | creg b[2]; 7 | qubit[5] q1; 8 | qreg q2[7]; 9 | let q = q1 ++ q2; 10 | let c = a[{0,1}] ++ b[1:2]; 11 | let qq = q1[{1,3,4}]; 12 | let qqq = qq ++ q2[1:2:6]; 13 | let d = c; 14 | let e = d[1]; 15 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/assignment/assignment.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: todo 3 | // sema: skip 4 | 5 | bit[2] a; 6 | bit[2] b; 7 | creg b[2]; 8 | qubit[3] q; 9 | int[10] x = 12; 10 | a[0] = b[1]; 11 | x += int[10](a[1]); 12 | measure q[1] -> a[0]; 13 | a = measure q[1:2]; 14 | measure q[0]; 15 | b = a == 0; 16 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__pulse__cal.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/pulse/cal.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | (no asg) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__scope__nop.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/scope/nop.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | (no asg) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__pulse__cal2.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/pulse/cal2.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | (no asg) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__pulse__cal2.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/pulse/cal2.qasm 6 | expect-parse: Todo 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- ast --- 12 | (no ast) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__pulse__defcal.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/pulse/defcal.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | (no asg) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__assignment__slices.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/assignment/slices.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- asg --- 12 | (no asg) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__pulse__defcal.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/pulse/defcal.qasm 6 | expect-parse: Todo 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- ast --- 12 | (no ast) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__subroutine__array.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/subroutine/array.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | (no asg) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/expression/built_in_call.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | int[32](10); 6 | sin(π); 7 | arcsin(π); 8 | cos(π); 9 | arccos(π); 10 | tan(π); 11 | arctan(π); 12 | exp(π); 13 | ln(π); 14 | sqrt(π); 15 | rotl(π); 16 | rotr(π); 17 | popcount(π); 18 | sizeof(x); 19 | sizeof(x, 0); 20 | sizeof(x, 1); 21 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__headers.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid/statements/headers.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 4 11 | --- ast --- 12 | (no ast) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__tokens.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid/statements/tokens.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- ast --- 12 | (no ast) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__declaration__array.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/declaration/array.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | (no asg) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__subroutine__extern.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/subroutine/extern.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | NullStmt 13 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | # See https://rust-lang.github.io/rustfmt/?version=v1.6.0&search= 2 | 3 | # Copyright contributors to the openqasm-parser project 4 | 5 | # Use this when it becomes stable 6 | # reorder_impl_items = true 7 | 8 | # When use_small_heuristics is set to Max, then each granular width setting is set to the same value as max_width. 9 | # use_small_heuristics = "Max" 10 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__subroutine__subroutine.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/subroutine/subroutine.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | (no asg) 13 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | All members of this project agree to adhere to the Qiskit Code of Conduct as found 3 | at [https://github.com/Qiskit/qiskit/blob/master/CODE_OF_CONDUCT.md](https://github.com/Qiskit/qiskit/blob/master/CODE_OF_CONDUCT.md) 4 | 5 | ---- 6 | 7 | License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), 8 | Copyright Contributors to Qiskit. 9 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__defcalgrammar.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/directives/defcalgrammar.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | (no asg) 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/measure.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | measure $0, $1; 6 | a[0:1] = measure $0, $1; 7 | a = measure $0 -> b; 8 | creg a[1] = measure $0; 9 | measure $0 -> creg a[1]; 10 | measure $0 -> bit[1] a; 11 | // Measure can't be used in sub-expressions. 12 | a = 2 * measure $0; 13 | a = (measure $0) + (measure $1); 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/declaration/complex.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: todo 4 | 5 | // beware the tab character in f = 1 im below 6 | complex[float] a; 7 | complex[float] b = 4 - 5.5im; 8 | complex[float[64]] d = a + 3 im; 9 | // complex[float[32]] c = a ** b; 10 | complex[float] e = 1im; 11 | complex[float] f = 1 im; 12 | complex z; 13 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/gate_applications.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | U (1)(2) $0; 6 | notmodifier @ x $0; 7 | pow @ x $0; 8 | pow(2, 3) @ x $0; 9 | ctrl(2, 3) @ x $0, $1; 10 | negctrl(2, 3) @ x $0, $1; 11 | inv(1) @ ctrl @ x $0, $1; 12 | 13 | // Global phase is defined in the grammar to be the last modifier. 14 | gphase(pi) @ ctrl @ x $0, $1; 15 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__scope__anonymous_block.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/scope/anonymous_block.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: BlockExpr not supported. 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__control_flow__branching.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/control_flow/branching.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: Unsupported binary operator 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__include.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/directives/include.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: called `Option::unwrap()` on a `None` value 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__gate__quantum_gate.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/gate/quantum_gate.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: called `Option::unwrap()` on a `None` value 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__control_flow__branch_binop.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/control_flow/branch_binop.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: Binary logic operators unsupported. 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__include.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/directives/include.qasm 6 | expect-parse: Panic 7 | --- parser --- 8 | ok: false 9 | panicked: true 10 | panic: called `Option::unwrap()` on a `None` value 11 | errors: 0 12 | --- ast --- 13 | (no ast) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__built_in_call.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/expression/built_in_call.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: programming error: expected Type::Def variant 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__order_of_ops.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/expression/order_of_ops.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: programming error: expected Type::Def variant 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__control_flow__loop.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/control_flow/loop.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: Comparision operators other than `=` and `!=` are not supported. 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__declaration__declaration.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/declaration/declaration.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: called `Result::unwrap()` on an `Err` value: AlreadyBound 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__sub_and_extern_call.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/expression/sub_and_extern_call.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: programming error: expected Type::Def variant 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__unary_expr.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/expression/unary_expr.qasm 6 | expect-sema: Panic 7 | --- sema --- 8 | ok: false 9 | panicked: true 10 | panic: Unary operators other than minus are not supported. Found 'LogicNot.' 11 | errors: 0 12 | --- asg --- 13 | (no asg) 14 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/comments/comments.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: todo 4 | 5 | OPENQASM 3.0; 6 | // Line comment before include 7 | include "stdgates.inc"; // Inline comment 8 | /* Block comment before declaration */ 9 | qubit[2] q; /* Inline block comment */ 10 | 11 | // Comment before gate 12 | h q[0]; // Gate with comment 13 | /* Multi-line block comment 14 | spanning multiple lines */ 15 | cx q[0], q[1]; 16 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/comments/comments_cnot.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: diag 4 | 5 | OPENQASM 3.0; 6 | // Line comment before include 7 | include "stdgates.inc"; // Inline comment 8 | /* Block comment before declaration */ 9 | qubit[2] q; /* Inline block comment */ 10 | 11 | // Comment before gate 12 | h q[0]; // Gate with comment 13 | /* Multi-line block comment 14 | spanning multiple lines */ 15 | cnot q[0], q[1]; 16 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/directives/annotations2.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: ok 4 | 5 | @bind [2:3] 6 | input uint[16] x; 7 | 8 | @rename other 9 | output float[64] var; 10 | 11 | @hello world 12 | int[8] y; 13 | 14 | @outer 15 | def fn() { 16 | @inner word1 17 | uint[16] x; 18 | @inner word2 19 | return; 20 | } 21 | 22 | @first 23 | @second @not_third 24 | uint[16] z; 25 | 26 | @binds tightly 27 | x = 1; x = 2; 28 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__pragma.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/directives/pragma.qasm 6 | expect-sema: Ok 7 | --- sema --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- asg --- 12 | Pragma(Pragma { pragma_text: " IO_BIND[2:3]" }) 13 | 14 | Pragma(Pragma { pragma_text: " __directive_info__ 0" }) 15 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__valid_oq3p__directives__pragma.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/valid_oq3p/directives/pragma.qasm 6 | expect-sema: Ok 7 | --- sema --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- asg --- 12 | Pragma(Pragma { pragma_text: " (((9217#@%^^^*!@#$%^" }) 13 | 14 | Pragma(Pragma { pragma_text: " ))!~==}{" }) 15 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/directives/annotations.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: diag 4 | 5 | @bind [2:3] 6 | input uint[16] x; 7 | 8 | @rename other 9 | output float[64] var; 10 | 11 | @hello world 12 | int[8] x; 13 | 14 | @outer 15 | def fn() { 16 | @inner word1 17 | uint[16] x; 18 | @inner word2 19 | return; 20 | } 21 | 22 | @first 23 | @second @not_third 24 | uint[16] x; 25 | 26 | @binds tightly 27 | x = 1; x = 2; 28 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/subroutine/subroutine.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: skip 4 | 5 | def test_sub1(int[5] i, qubit[2] q1, qreg q2[5]) -> int[10] { 6 | int[10] result; 7 | if (result == 2) return 1 + result; 8 | return result; 9 | } 10 | def test_sub2(int[5] i, bit[2] b, creg c[3]) { 11 | for int[5] j in {2, 3} 12 | i += j; 13 | return i+1; 14 | } 15 | def returns_a_measure(qubit q) { 16 | return measure q; 17 | } 18 | -------------------------------------------------------------------------------- /crates/pipeline-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pipeline-tests" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dev-dependencies] 7 | glob = "0.3" 8 | insta = "1" 9 | datatest-stable = "0.3.3" 10 | tempfile = "3" 11 | 12 | [dependencies] 13 | oq3_lexer.workspace = true 14 | oq3_parser.workspace = true 15 | oq3_syntax.workspace = true 16 | oq3_semantics.workspace = true 17 | oq3_source_file.workspace = true 18 | 19 | [[test]] 20 | name = "runner" 21 | harness = false 22 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__unary_expr.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/expression/unary_expr.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | !my_var; 10 | --- lexer --- 11 | ok: true 12 | errors: 0 13 | [0] Whitespace "\n" @0..1 14 | [1] Bang "!" @1..2 15 | [2] Ident "my_var" @2..8 16 | [3] Semi ";" @8..9 17 | [4] Whitespace "\n" @9..10 18 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__unary_expr.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/expression/unary_expr.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..10: 13 | !my_var; 14 | 15 | EXPR_STMT@1..9: !my_var; 16 | PREFIX_EXPR@1..8: !my_var 17 | IDENTIFIER@2..8: my_var 18 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/subroutine/array.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: skip 4 | 5 | def test_array_1(mutable array[uint[16], 4, 2] a) {} 6 | def test_array_2(readonly array[uint[16], 4, 2] a) {} 7 | def test_array_3(mutable array[uint[16], #dim=2] a) {} 8 | def test_array_4(readonly array[uint[16], #dim=2*n] a) {} 9 | def test_array_5(readonly array[int[8], #dim=1] a, mutable array[complex[float[64]], #dim=3] b, readonly array[complex[float[64]], 2, 2] c) -> int[8] {} 10 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/loop.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: diag 3 | // sema: skip 4 | 5 | for myvar in { 1, 2, 3 }; 6 | for myvar1, myvar2 in { 1, 2, 3 } { x $0; } 7 | for myvar in { x $0; } { x $0; } 8 | for myvar in for { x $0; } 9 | for myvar { x $0; } 10 | for (true) { x $0; } 11 | for { x $0; } 12 | for for in { 1, 2, 3 } { x $0; } 13 | for in { 1, 2, 3 } { x $0; } 14 | while true { x $0; } 15 | while (true) (true) { x $0; } 16 | while x in { 1, 2, 3 } { x $0; } 17 | while (true); 18 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/assignment/slices.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: skip 4 | 5 | array[uint[16], 2, 2] a = {{1, 2}, {3, 4}}; 6 | array[uint[16], 2, 4] b = {{1, 2, 3, 4}, {5, 6, 7, 8}}; 7 | // Various forms of testing that assignments can be made to indexed 8 | // identifiers, and from indexed identifiers. 9 | a = b[0:1][0:1]; 10 | a[0:1] = b[0:1][0:1]; 11 | a[0] = b[0][0:1]; 12 | a[0][0] = b[0][0]; 13 | a[0][0:1] = b[1][1:2:3]; 14 | a[0:1][0] = b[0:1][0]; 15 | a[0:1][0:1] = b[0:1][0:1]; 16 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__header.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/header.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | InputDeclaration(InputDeclaration { name: Ok(SymbolId(39)) }) 13 | 14 | InputDeclaration(InputDeclaration { name: Ok(SymbolId(40)) }) 15 | 16 | OutputDeclaration(OutputDeclaration { name: Ok(SymbolId(41)) }) 17 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid_oq3p__directives__pragma3.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid_oq3p/directives/pragma3.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 2 11 | --- ast --- 12 | SOURCE_FILE@0..55: 13 | // "pragam" is an invalid identifier. 14 | int pragma = 1; 15 | 16 | SCALAR_TYPE@39..42: int 17 | NAME@43..43: 18 | PRAGMA_STATEMENT@43..54: pragma = 1; 19 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__valid_oq3p__directives__pragma.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/valid_oq3p/directives/pragma.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..46: 13 | pragma (((9217#@%^^^*!@#$%^ 14 | #pragma ))!~==}{ 15 | 16 | PRAGMA_STATEMENT@1..28: pragma (((9217#@%^^^*!@#$%^ 17 | PRAGMA_STATEMENT@29..45: #pragma ))!~==}{ 18 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__pragma.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/directives/pragma.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..51: 13 | pragma IO_BIND[2:3] 14 | #pragma __directive_info__ 0 15 | 16 | PRAGMA_STATEMENT@1..20: pragma IO_BIND[2:3] 17 | PRAGMA_STATEMENT@21..50: #pragma __directive_info__ 0 18 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/declaration/array.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: skip 4 | 5 | array[uint[16], 1] x; 6 | array[int[8], 4] x; 7 | array[float[64], 4, 2] x; 8 | array[angle[32], 4, 3, 2] x; 9 | array[complex[float[32]], 4] x; 10 | array[bool, 3] x; 11 | array[int[8], 4] x = {1, 2, 3, 4}; 12 | array[int[8], 4] x = y; 13 | array[int[8], 2] x = {y, y+y}; 14 | array[uint[32], 2, 2] x = {{3, 4}, {2-3, 5*y}}; 15 | array[uint[32], 2, 2] x = {z, {2-3, 5*y}}; 16 | array[uint[32], 2, 2] x = {2*z, {1, 2}}; 17 | array[uint[32], 2, 2] x = y; 18 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__valid_oq3p__directives__pragma.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/valid_oq3p/directives/pragma.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | pragma (((9217#@%^^^*!@#$%^ 10 | #pragma ))!~==}{ 11 | --- lexer --- 12 | ok: true 13 | errors: 0 14 | [0] Whitespace "\n" @0..1 15 | [1] Pragma "pragma (((9217#@%^^^*!@#$%^" @1..28 16 | [2] Whitespace "\n" @28..29 17 | [3] Pragma "#pragma ))!~==}{" @29..45 18 | [4] Whitespace "\n" @45..46 19 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__pragma.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/directives/pragma.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | pragma IO_BIND[2:3] 10 | #pragma __directive_info__ 0 11 | --- lexer --- 12 | ok: true 13 | errors: 0 14 | [0] Whitespace "\n" @0..1 15 | [1] Pragma "pragma IO_BIND[2:3]" @1..20 16 | [2] Whitespace "\n" @20..21 17 | [3] Pragma "#pragma __directive_info__ 0" @21..50 18 | [4] Whitespace "\n" @50..51 19 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/control_flow/switch.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: ok 4 | 5 | include "stdgates.inc"; 6 | 7 | int i = 1; 8 | int j = 2; 9 | int k = 3; 10 | 11 | switch (i) { 12 | case 0 { 13 | x $0; 14 | } 15 | case 1, 2 { 16 | x $0; 17 | z $1; 18 | } 19 | case 3, { 20 | } 21 | default { 22 | cx $0, $1; 23 | } 24 | } 25 | 26 | switch (i + j) { 27 | default { 28 | switch (2 * k) { 29 | case 0 { 30 | x $0; 31 | } 32 | default { 33 | z $0; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/oq3_lexer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "oq3_lexer" 3 | description = "Lexer for OpenQASM 3 parser/analyzer" 4 | version.workspace = true 5 | edition.workspace = true 6 | rust-version.workspace = true 7 | license.workspace = true 8 | authors.workspace = true 9 | readme.workspace = true 10 | keywords.workspace = true 11 | categories.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | unicode-xid = "0.2.6" 16 | 17 | [dependencies.unicode-properties] 18 | version = "0.1.3" 19 | default-features = false 20 | features = ["emoji"] 21 | 22 | [dev-dependencies] 23 | expect-test = "1.5.1" 24 | -------------------------------------------------------------------------------- /crates/oq3_source_file/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "oq3_source_file" 3 | description = "Manage parsing source files, included files, and reporting diagnotics OpenQASM 3 parser/analyzer" 4 | version.workspace = true 5 | edition.workspace = true 6 | rust-version.workspace = true 7 | license.workspace = true 8 | authors.workspace = true 9 | readme.workspace = true 10 | keywords.workspace = true 11 | categories.workspace = true 12 | repository.workspace = true 13 | 14 | [lib] 15 | doctest = false 16 | 17 | [dependencies] 18 | ariadne = { version = "0.5.0", features = ["auto-color"] } 19 | oq3_syntax.workspace = true 20 | -------------------------------------------------------------------------------- /crates/oq3_parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "oq3_parser" 3 | description = "Parser for OpenQASM 3 parser/analyzer" 4 | version.workspace = true 5 | edition.workspace = true 6 | rust-version.workspace = true 7 | license.workspace = true 8 | authors.workspace = true 9 | readme.workspace = true 10 | keywords.workspace = true 11 | categories.workspace = true 12 | repository.workspace = true 13 | 14 | [lib] 15 | doctest = false 16 | 17 | [dependencies] 18 | oq3_lexer.workspace = true 19 | drop_bomb = "0.1.5" 20 | limit = { version = "0.0.229", package = "ra_ap_limit" } 21 | 22 | [dev-dependencies] 23 | expect-test = "1.5.1" 24 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid_oq3p__declaration__bit_array.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid_oq3p/declaration/bit_array.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- ast --- 12 | SOURCE_FILE@0..21: 13 | array[bit[8], 2] x; 14 | 15 | CLASSICAL_DECLARATION_STATEMENT@1..20: array[bit[8], 2] x; 16 | ARRAY_TYPE@1..17: array[bit[8], 2] 17 | SCALAR_TYPE@7..13: bit[8] 18 | DESIGNATOR@10..13: [8] 19 | LITERAL@11..12: 8 20 | LITERAL@15..16: 2 21 | NAME@18..19: x 22 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__scope__anonymous_block.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/scope/anonymous_block.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..20: 13 | { 14 | int ii = 32; 15 | } 16 | 17 | EXPR_STMT@1..19: { 18 | int ii = 32; 19 | } 20 | BLOCK_EXPR@1..19: { 21 | int ii = 32; 22 | } 23 | CLASSICAL_DECLARATION_STATEMENT@5..17: int ii = 32; 24 | SCALAR_TYPE@5..8: int 25 | NAME@9..11: ii 26 | LITERAL@14..16: 32 27 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid_oq3p__directives__pragma2.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid_oq3p/directives/pragma2.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 4 11 | --- ast --- 12 | SOURCE_FILE@0..52: 13 | // pragmaa is an ordinary identifier 14 | pragmaa 1 2 3 15 | 16 | EXPR_STMT@38..45: pragmaa 17 | IDENTIFIER@38..45: pragmaa 18 | EXPR_STMT@46..47: 1 19 | LITERAL@46..47: 1 20 | EXPR_STMT@48..49: 2 21 | LITERAL@48..49: 2 22 | EXPR_STMT@50..51: 3 23 | LITERAL@50..51: 3 24 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__assignment__alias.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/assignment/alias.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(7)), initializer: None }) 13 | 14 | NullStmt 15 | 16 | DeclareQuantum(DeclareQuantum { name: Ok(SymbolId(8)) }) 17 | 18 | NullStmt 19 | 20 | NullStmt 21 | 22 | NullStmt 23 | 24 | NullStmt 25 | 26 | NullStmt 27 | 28 | NullStmt 29 | 30 | NullStmt 31 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid_oq3p__directives__pragma3.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid_oq3p/directives/pragma3.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | // "pragam" is an invalid identifier. 10 | int pragma = 1; 11 | --- lexer --- 12 | ok: true 13 | errors: 0 14 | [0] Whitespace "\n" @0..1 15 | [1] LineComment "// "pragam" is an invalid identifier." @1..38 16 | [2] Whitespace "\n" @38..39 17 | [3] Ident "int" @39..42 18 | [4] Whitespace " " @42..43 19 | [5] Pragma "pragma = 1;" @43..54 20 | [6] Whitespace "\n" @54..55 21 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__defcalgrammar.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/directives/defcalgrammar.qasm 6 | expect-parse: Todo 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- ast --- 12 | SOURCE_FILE@0..76: 13 | defcalgrammar 'openpulse'; 14 | defcalgrammar "openpulse"; 15 | defcalgrammar "001"; 16 | 17 | DEF_CAL_GRAMMAR@1..27: defcalgrammar 'openpulse'; 18 | FILE_PATH@15..26: 'openpulse' 19 | DEF_CAL_GRAMMAR@28..54: defcalgrammar "openpulse"; 20 | FILE_PATH@42..53: "openpulse" 21 | DEF_CAL_GRAMMAR@55..75: defcalgrammar "001"; 22 | ERROR@69..74: "001" 23 | -------------------------------------------------------------------------------- /crates/oq3_semantics/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "oq3_semantics" 3 | description = "AST with semantic information for OpenQASM 3 parser/analyzer" 4 | version.workspace = true 5 | edition.workspace = true 6 | rust-version.workspace = true 7 | license.workspace = true 8 | authors.workspace = true 9 | readme.workspace = true 10 | keywords.workspace = true 11 | categories.workspace = true 12 | repository.workspace = true 13 | 14 | [lib] 15 | doctest = false 16 | 17 | [dependencies] 18 | oq3_source_file.workspace = true 19 | oq3_syntax.workspace = true 20 | hashbrown = { version = "0.15.2" } 21 | rowan = {version = "<=0.16.1"} 22 | boolenum = "0.1" 23 | 24 | [dev-dependencies] 25 | clap = { version = "~4.4", features = ["derive"] } 26 | oq3_lexer.workspace = true 27 | oq3_parser.workspace = true 28 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/reference/declaration/declaration.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // parse: ok 3 | // sema: panic 4 | 5 | // beware the tab character in dur4 = 8 ns below 6 | int[10] x; 7 | int[10] y; 8 | uint[32] z = 0xFa_1F; 9 | uint[32] z = 0XFa_1F; 10 | uint[16] z = 0o12_34; 11 | uint[16] z = 0b1001_1001; 12 | uint[16] z = 0B1001_1001; 13 | uint x; 14 | qubit[6] q1; 15 | qubit q2; 16 | bit[4] b1="0100"; 17 | bit[8] b2="1001_0100"; 18 | bit b2 = "1"; 19 | bool m=true; 20 | bool n=bool(b2); 21 | bool o=false; 22 | const float[64] c = 5.5e3; 23 | const float[64] d=5; 24 | float[32] f = .1e+3; 25 | duration dur = 1000dt; 26 | duration dur2 = dur + 200ns; 27 | duration dur3 = 10 ms; 28 | duration dur4 = 8 us; 29 | duration dur5 = 1s; 30 | stretch s; 31 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Release openqasm3_parser 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | publish_crates: 10 | name: Publish openqasm3_parser crates 11 | runs-on: ubuntu-latest 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | crate: [oq3_lexer, oq3_parser, oq3_syntax, oq3_source_file, oq3_semantics] 16 | max-parallel: 1 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: dtolnay/rust-toolchain@stable 21 | - name: Run cargo publish 22 | run: | 23 | cd crates/${{ matrix.crate }} 24 | cargo publish 25 | env: 26 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 27 | - run: date 28 | - run: sleep 60 29 | - run: date 30 | -------------------------------------------------------------------------------- /crates/oq3_semantics/src/display.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Unused at the moment. 5 | // This intent here is to print something like source code. 6 | // But this involves a ton of boiler plate. 7 | 8 | use std::fmt; 9 | use crate::asg::*; 10 | 11 | impl fmt::Display for Include { 12 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 13 | write!(f, "include \"{}\"", self.file_path()) 14 | } 15 | } 16 | 17 | impl fmt::Display for Stmt { 18 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 19 | match self { 20 | Stmt::Include(include) => { 21 | write!(f, "{}", include); 22 | } 23 | _ => () 24 | } 25 | write!(f, ";") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["crates/*"] 3 | resolver = "2" 4 | 5 | [workspace.package] 6 | version = "0.7.0" 7 | rust-version = "1.79" # Sync with ./rust-toolchain.toml 8 | edition = "2021" 9 | license = "Apache-2.0" 10 | authors = ["OpenQASM3 parser team"] 11 | readme = "README.md" 12 | keywords = ["QASM", "openqasm3", "parser"] 13 | categories = ["parser-implementations"] 14 | repository = "https://github.com/Qiskit/openqasm3_parser" 15 | 16 | [workspace.dependencies] 17 | # local crates 18 | oq3_lexer = { path = "crates/oq3_lexer", version = "0.7.0" } 19 | oq3_parser = { path = "crates/oq3_parser", version = "0.7.0" } 20 | oq3_syntax = { path = "crates/oq3_syntax", version = "0.7.0" } 21 | oq3_semantics = { path = "crates/oq3_semantics", version = "0.7.0" } 22 | oq3_source_file = { path = "crates/oq3_source_file", version = "0.7.0" } 23 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__scope__anonymous_block.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/scope/anonymous_block.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | { 10 | int ii = 32; 11 | } 12 | --- lexer --- 13 | ok: true 14 | errors: 0 15 | [0] Whitespace "\n" @0..1 16 | [1] OpenBrace "{" @1..2 17 | [2] Whitespace "\n " @2..5 18 | [3] Ident "int" @5..8 19 | [4] Whitespace " " @8..9 20 | [5] Ident "ii" @9..11 21 | [6] Whitespace " " @11..12 22 | [7] Eq "=" @12..13 23 | [8] Whitespace " " @13..14 24 | [9] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "32" @14..16 25 | [10] Semi ";" @16..17 26 | [11] Whitespace "\n" @17..18 27 | [12] CloseBrace "}" @18..19 28 | [13] Whitespace "\n" @19..20 29 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | # list recipes 2 | default: 3 | @just --list 4 | 5 | # One-stop CI-ish local run 6 | ci: 7 | cargo fmt --all -- --check 8 | cargo build --release --verbose 9 | cargo test --verbose --lib --tests 10 | cargo clippy --all-targets -- -D warnings -D clippy::dbg_macro 11 | 12 | # Regenerate source files from ungrammar and reformat 13 | sourcegen: 14 | cargo clean 15 | cargo build -p oq3_syntax --features sourcegen 16 | cargo fmt -p oq3_syntax -p oq3_parser 17 | 18 | _assert_empty_git_status: 19 | @if git status --porcelain | grep .; then \ 20 | echo "Uncommitted changes found"; \ 21 | git --no-pager diff; \ 22 | exit 1; \ 23 | fi 24 | 25 | # Check that source files are up to date (assumes a clean working tree) 26 | check_sourcegen: _assert_empty_git_status sourcegen _assert_empty_git_status 27 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid_oq3p__directives__pragma.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid_oq3p/directives/pragma.qasm 6 | expect-lex: Diag 7 | --- source --- 8 | 9 | #pragmaa 1 2 3 10 | --- lexer --- 11 | ok: false 12 | errors: 1 13 | [0] Whitespace "\n" @0..1 14 | [1] InvalidIdent "#pragma" @1..8 15 | [2] Ident "a" @8..9 16 | [3] Whitespace " " @9..10 17 | [4] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @10..11 18 | [5] Whitespace " " @11..12 19 | [6] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @12..13 20 | [7] Whitespace " " @13..14 21 | [8] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "3" @14..15 22 | [9] Whitespace "\n" @15..16 23 | -------------------------------------------------------------------------------- /crates/oq3_source_file/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Management of source files for OpenQASM 3 parsing and semantic analysis. The main `struct` here 5 | //! is `SourceFile` which contains the path to a source file and the AST produced by the parser. It 6 | //! also contains a `Vec` representing source files that are included via 7 | //! `include`. Nested includes are handled naturally this way. 8 | //! 9 | //! `report_error` formats error messages using the external crate `ariadne`. 10 | 11 | // mod error_report; 12 | mod api; 13 | mod source_file; 14 | 15 | pub use source_file::{ErrorTrait, SourceFile, SourceString, SourceTrait}; 16 | 17 | pub use api::{ 18 | inner_print_compiler_errors, parse_source_file, parse_source_file_with_search, 19 | parse_source_string, print_compiler_errors, report_error, 20 | }; 21 | -------------------------------------------------------------------------------- /crates/oq3_parser/src/syntax_kind.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Defines [`SyntaxKind`] -- a fieldless enum of all possible syntactic 5 | //! constructs of the OpenQASM 3 language. 6 | 7 | pub mod syntax_kind_enum; 8 | 9 | #[allow(unreachable_pub)] 10 | pub use self::syntax_kind_enum::{SyntaxKind, T}; 11 | 12 | impl From for SyntaxKind { 13 | #[inline] 14 | fn from(d: u16) -> SyntaxKind { 15 | assert!(d <= (SyntaxKind::__LAST as u16)); 16 | unsafe { std::mem::transmute::(d) } 17 | } 18 | } 19 | 20 | impl From for u16 { 21 | #[inline] 22 | fn from(k: SyntaxKind) -> u16 { 23 | k as u16 24 | } 25 | } 26 | 27 | impl SyntaxKind { 28 | #[inline] 29 | pub fn is_trivia(self) -> bool { 30 | matches!(self, SyntaxKind::WHITESPACE | SyntaxKind::COMMENT) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid_oq3p__declaration__bit_array.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid_oq3p/declaration/bit_array.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | array[bit[8], 2] x; 10 | --- lexer --- 11 | ok: true 12 | errors: 0 13 | [0] Whitespace "\n" @0..1 14 | [1] Ident "array" @1..6 15 | [2] OpenBracket "[" @6..7 16 | [3] Ident "bit" @7..10 17 | [4] OpenBracket "[" @10..11 18 | [5] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @11..12 19 | [6] CloseBracket "]" @12..13 20 | [7] Comma "," @13..14 21 | [8] Whitespace " " @14..15 22 | [9] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @15..16 23 | [10] CloseBracket "]" @16..17 24 | [11] Whitespace " " @17..18 25 | [12] Ident "x" @18..19 26 | [13] Semi ";" @19..20 27 | [14] Whitespace "\n" @20..21 28 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid_oq3p__directives__pragma2.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid_oq3p/directives/pragma2.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | // pragmaa is an ordinary identifier 10 | pragmaa 1 2 3 11 | --- lexer --- 12 | ok: true 13 | errors: 0 14 | [0] Whitespace "\n" @0..1 15 | [1] LineComment "// pragmaa is an ordinary identifier" @1..37 16 | [2] Whitespace "\n" @37..38 17 | [3] Ident "pragmaa" @38..45 18 | [4] Whitespace " " @45..46 19 | [5] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @46..47 20 | [6] Whitespace " " @47..48 21 | [7] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @48..49 22 | [8] Whitespace " " @49..50 23 | [9] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "3" @50..51 24 | [10] Whitespace "\n" @51..52 25 | -------------------------------------------------------------------------------- /crates/oq3_syntax/src/ast/traits.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Various traits that are implemented by ast nodes. 5 | //! 6 | //! The implementations are usually trivial, and live in generated.rs 7 | //! 8 | //! NOTE!!! This is not support for the rust traits! 9 | //! This cannot be removed for OQ3. 10 | 11 | use either::Either; 12 | 13 | use crate::ast::{self, support, AstNode}; 14 | 15 | pub trait HasName: AstNode { 16 | fn name(&self) -> Option { 17 | support::child(self.syntax()) 18 | } 19 | } 20 | 21 | pub trait HasLoopBody: AstNode { 22 | fn loop_body(&self) -> Option { 23 | support::child(self.syntax()) 24 | } 25 | } 26 | 27 | pub trait HasArgList: AstNode { 28 | fn arg_list(&self) -> Option { 29 | support::child(self.syntax()) 30 | } 31 | } 32 | 33 | impl HasName for Either {} 34 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid_oq3p__directives__pragma1.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid_oq3p/directives/pragma1.qasm 6 | expect-lex: Diag 7 | --- source --- 8 | 9 | // Invalid identifier token 10 | #pragmaa 1 2 3 11 | --- lexer --- 12 | ok: false 13 | errors: 1 14 | [0] Whitespace "\n" @0..1 15 | [1] LineComment "// Invalid identifier token" @1..28 16 | [2] Whitespace "\n" @28..29 17 | [3] InvalidIdent "#pragma" @29..36 18 | [4] Ident "a" @36..37 19 | [5] Whitespace " " @37..38 20 | [6] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @38..39 21 | [7] Whitespace " " @39..40 22 | [8] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @40..41 23 | [9] Whitespace " " @41..42 24 | [10] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "3" @42..43 25 | [11] Whitespace "\n" @43..44 26 | -------------------------------------------------------------------------------- /crates/pipeline-tests/README.md: -------------------------------------------------------------------------------- 1 | - List discovered tests: 2 | From workspace root 3 | 4 | ### OpenQASM snippets 5 | 6 | To see a list of tests 7 | ```sh 8 | cargo test -p pipeline-tests -- --list 9 | ``` 10 | 11 | These tags are at the top of each snippet. 12 | Set the tags according to what is expected. 13 | 14 | * ok - Stage must complete with no diagnostics. 15 | * diag - Stage must complete and produce diagnostics (≥1); snapshot verifies content. 16 | This is for testing invalid input 17 | * todo - Stage must complete and produce diagnostics (>=1); snapshot verifies content. 18 | Valid input that produces incorrect diagnostics. 19 | * panic - Stage is expected to panic; harness catches the unwind. 20 | * skip - Do not assert this stage (optionally skip running it). 21 | ``` 22 | // lex: ok|diag|todo|panic|skip 23 | // parse: ok|diag|todo|panic|skip 24 | // sema: ok|diag|todo|panic|skip 25 | ``` 26 | 27 | For summary status of tags on snippets 28 | ```sh 29 | ./tools/expect_summary.py 30 | ``` 31 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__binary_expr.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/expression/binary_expr.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..43: 13 | int x = 0; 14 | int y = 1; 15 | 16 | 2+2; 17 | 2**2; 18 | x << y; 19 | 20 | CLASSICAL_DECLARATION_STATEMENT@1..11: int x = 0; 21 | SCALAR_TYPE@1..4: int 22 | NAME@5..6: x 23 | LITERAL@9..10: 0 24 | CLASSICAL_DECLARATION_STATEMENT@12..22: int y = 1; 25 | SCALAR_TYPE@12..15: int 26 | NAME@16..17: y 27 | LITERAL@20..21: 1 28 | EXPR_STMT@24..28: 2+2; 29 | BIN_EXPR@24..27: 2+2 30 | LITERAL@24..25: 2 31 | LITERAL@26..27: 2 32 | EXPR_STMT@29..34: 2**2; 33 | BIN_EXPR@29..33: 2**2 34 | LITERAL@29..30: 2 35 | LITERAL@32..33: 2 36 | EXPR_STMT@35..42: x << y; 37 | BIN_EXPR@35..41: x << y 38 | IDENTIFIER@35..36: x 39 | IDENTIFIER@40..41: y 40 | -------------------------------------------------------------------------------- /crates/oq3_syntax/src/validation/block.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Logic for validating block expressions i.e. `ast::BlockExpr`. 5 | 6 | // use crate::{ 7 | // ast::{self, AstNode, HasAttrs}, 8 | // SyntaxError, 9 | // SyntaxKind::*, 10 | // }; 11 | 12 | // pub(crate) fn validate_block_expr(block: ast::BlockExpr, errors: &mut Vec) { 13 | // if let Some(parent) = block.syntax().parent() { 14 | // match parent.kind() { 15 | // FN | EXPR_STMT | STMT_LIST => return, 16 | // _ => {} 17 | // } 18 | // } 19 | // if let Some(stmt_list) = block.stmt_list() { 20 | // errors.extend(stmt_list.attrs().filter(|attr| attr.kind().is_inner()).map(|attr| { 21 | // SyntaxError::new( 22 | // "A block in this position cannot accept inner attributes", 23 | // attr.syntax().text_range(), 24 | // ) 25 | // })); 26 | // } 27 | // } 28 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__header.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/header.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..106: 13 | OPENQASM 3.0; 14 | include "stdgates.inc"; 15 | input angle[32] param1; 16 | input angle[32] param2; 17 | output bit result; 18 | 19 | VERSION_STRING@1..14: OPENQASM 3.0; 20 | INCLUDE@15..38: include "stdgates.inc"; 21 | FILE_PATH@23..37: "stdgates.inc" 22 | I_O_DECLARATION_STATEMENT@39..62: input angle[32] param1; 23 | SCALAR_TYPE@45..54: angle[32] 24 | DESIGNATOR@50..54: [32] 25 | LITERAL@51..53: 32 26 | NAME@55..61: param1 27 | I_O_DECLARATION_STATEMENT@63..86: input angle[32] param2; 28 | SCALAR_TYPE@69..78: angle[32] 29 | DESIGNATOR@74..78: [32] 30 | LITERAL@75..77: 32 31 | NAME@79..85: param2 32 | I_O_DECLARATION_STATEMENT@87..105: output bit result; 33 | SCALAR_TYPE@94..97: bit 34 | NAME@98..104: result 35 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__include.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/directives/include.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | include 'foo2'; 10 | include "foo"; 11 | include "001"; 12 | --- lexer --- 13 | ok: true 14 | errors: 0 15 | [0] Whitespace "\n" @0..1 16 | [1] Ident "include" @1..8 17 | [2] Whitespace " " @8..9 18 | [3] Literal { kind: Str { terminated: true }, suffix_start: 6 } "'foo2'" @9..15 19 | [4] Semi ";" @15..16 20 | [5] Whitespace "\n" @16..17 21 | [6] Ident "include" @17..24 22 | [7] Whitespace " " @24..25 23 | [8] Literal { kind: Str { terminated: true }, suffix_start: 5 } ""foo"" @25..30 24 | [9] Semi ";" @30..31 25 | [10] Whitespace "\n" @31..32 26 | [11] Ident "include" @32..39 27 | [12] Whitespace " " @39..40 28 | [13] Literal { kind: BitStr { terminated: true, consecutive_underscores: false }, suffix_start: 5 } ""001"" @40..45 29 | [14] Semi ";" @45..46 30 | [15] Whitespace "\n" @46..47 31 | -------------------------------------------------------------------------------- /crates/oq3_semantics/tests/symbol_tests.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use oq3_semantics::symbols; 5 | use oq3_semantics::types; 6 | 7 | const NUM_BUILTIN_CONSTS: usize = 7; 8 | 9 | // 10 | // Test API of symbols and symbol tables 11 | // 12 | 13 | #[test] 14 | fn test_symbol_table_create() { 15 | use symbols::SymbolTable; 16 | 17 | let table = SymbolTable::new(); 18 | assert_eq!(table.len_current_scope(), NUM_BUILTIN_CONSTS); 19 | let result = table.lookup("x"); 20 | assert!(result.is_err()); 21 | } 22 | 23 | #[test] 24 | fn test_symbol_table_bind() { 25 | use symbols::SymbolTable; 26 | use types::{IsConst, Type}; 27 | 28 | let mut table = SymbolTable::new(); 29 | let symbol_name = "x"; 30 | let x = table.new_binding(symbol_name, &Type::Bool(IsConst::False)); 31 | assert!(x.is_ok()); 32 | assert_eq!(table.len_current_scope(), 1 + NUM_BUILTIN_CONSTS); 33 | let result = table.lookup(symbol_name); 34 | assert!(result.is_ok()); 35 | assert_eq!(result.unwrap().symbol_id(), x.unwrap()); 36 | } 37 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__defcalgrammar.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/directives/defcalgrammar.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | defcalgrammar 'openpulse'; 10 | defcalgrammar "openpulse"; 11 | defcalgrammar "001"; 12 | --- lexer --- 13 | ok: true 14 | errors: 0 15 | [0] Whitespace "\n" @0..1 16 | [1] Ident "defcalgrammar" @1..14 17 | [2] Whitespace " " @14..15 18 | [3] Literal { kind: Str { terminated: true }, suffix_start: 11 } "'openpulse'" @15..26 19 | [4] Semi ";" @26..27 20 | [5] Whitespace "\n" @27..28 21 | [6] Ident "defcalgrammar" @28..41 22 | [7] Whitespace " " @41..42 23 | [8] Literal { kind: Str { terminated: true }, suffix_start: 11 } ""openpulse"" @42..53 24 | [9] Semi ";" @53..54 25 | [10] Whitespace "\n" @54..55 26 | [11] Ident "defcalgrammar" @55..68 27 | [12] Whitespace " " @68..69 28 | [13] Literal { kind: BitStr { terminated: true, consecutive_underscores: false }, suffix_start: 5 } ""001"" @69..74 29 | [14] Semi ";" @74..75 30 | [15] Whitespace "\n" @75..76 31 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__calibration.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid/statements/calibration.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 7 11 | --- ast --- 12 | SOURCE_FILE@0..106: 13 | defcalgrammar "openpulse" defcalgrammar "openpulse"; 14 | defcalgrammar 3; 15 | defcal x $0 -> int[8] -> int[8] {} 16 | 17 | DEF_CAL_GRAMMAR@1..26: defcalgrammar "openpulse" 18 | FILE_PATH@15..26: "openpulse" 19 | DEF_CAL_GRAMMAR@27..53: defcalgrammar "openpulse"; 20 | FILE_PATH@41..52: "openpulse" 21 | DEF_CAL_GRAMMAR@54..70: defcalgrammar 3; 22 | ERROR@68..69: 3 23 | DEF_CAL@71..92: defcal x $0 -> int[8] 24 | NAME@78..79: x 25 | QUBIT_LIST@80..82: $0 26 | HARDWARE_QUBIT@80..82: $0 27 | RETURN_SIGNATURE@83..92: -> int[8] 28 | SCALAR_TYPE@86..92: int[8] 29 | DESIGNATOR@89..92: [8] 30 | LITERAL@90..91: 8 31 | EXPR_STMT@93..95: -> 32 | PREFIX_EXPR@93..95: -> 33 | ERROR@94..95: > 34 | SCALAR_TYPE@96..102: int[8] 35 | DESIGNATOR@99..102: [8] 36 | LITERAL@100..101: 8 37 | NAME@103..103: 38 | EXPR_STMT@103..105: {} 39 | BLOCK_EXPR@103..105: {} 40 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__pulse__cal.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/pulse/cal.qasm 6 | expect-parse: Todo 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 7 11 | --- ast --- 12 | SOURCE_FILE@0..76: 13 | cal {} 14 | cal {One long, otherwise invalid token.} 15 | cal {Outer {nested} outer} 16 | 17 | CAL@1..7: cal {} 18 | BLOCK_EXPR@5..7: {} 19 | CAL@8..48: cal {One long, otherwise invalid token.} 20 | BLOCK_EXPR@12..48: {One long, otherwise invalid token.} 21 | EXPR_STMT@13..46: One long, otherwise invalid token 22 | GATE_CALL_EXPR@13..46: One long, otherwise invalid token 23 | IDENTIFIER@13..16: One 24 | QUBIT_LIST@17..46: long, otherwise invalid token 25 | IDENTIFIER@17..21: long 26 | IDENTIFIER@23..32: otherwise 27 | IDENTIFIER@33..40: invalid 28 | IDENTIFIER@41..46: token 29 | ERROR@46..47: . 30 | CAL@49..75: cal {Outer {nested} outer} 31 | BLOCK_EXPR@53..75: {Outer {nested} outer} 32 | EXPR_STMT@54..59: Outer 33 | IDENTIFIER@54..59: Outer 34 | EXPR_STMT@60..68: {nested} 35 | BLOCK_EXPR@60..68: {nested} 36 | IDENTIFIER@61..67: nested 37 | IDENTIFIER@69..74: outer 38 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__declaration__complex2.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/declaration/complex2.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(7)), initializer: Some(TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(Float(FloatLiteral { value: "2" })), ty: Float(Some(64), True) }, typ: Complex(Some(32), False) }), ty: Complex(Some(32), False) }) }) 13 | 14 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(8)), initializer: Some(TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(Float(FloatLiteral { value: "1" })), ty: Float(Some(64), True) }, typ: Complex(Some(32), False) }), ty: Complex(Some(32), False) }) }) 15 | 16 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(9)), initializer: Some(TExpr { expression: BinaryExpr(BinaryExpr { op: ConcatenationOp, left: TExpr { expression: Identifier(Ok(SymbolId(7))), ty: Complex(Some(32), False) }, right: TExpr { expression: Identifier(Ok(SymbolId(8))), ty: Complex(Some(32), False) } }), ty: ToDo }) }) 17 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__declaration__complex2.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/declaration/complex2.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..89: 13 | complex[float[32]] a = 2.0; 14 | complex[float[32]] b = 1.0; 15 | 16 | complex[float[32]] c = a ** b; 17 | 18 | CLASSICAL_DECLARATION_STATEMENT@1..28: complex[float[32]] a = 2.0; 19 | SCALAR_TYPE@1..19: complex[float[32]] 20 | SCALAR_TYPE@9..18: float[32] 21 | DESIGNATOR@14..18: [32] 22 | LITERAL@15..17: 32 23 | NAME@20..21: a 24 | LITERAL@24..27: 2.0 25 | CLASSICAL_DECLARATION_STATEMENT@29..56: complex[float[32]] b = 1.0; 26 | SCALAR_TYPE@29..47: complex[float[32]] 27 | SCALAR_TYPE@37..46: float[32] 28 | DESIGNATOR@42..46: [32] 29 | LITERAL@43..45: 32 30 | NAME@48..49: b 31 | LITERAL@52..55: 1.0 32 | CLASSICAL_DECLARATION_STATEMENT@58..88: complex[float[32]] c = a ** b; 33 | SCALAR_TYPE@58..76: complex[float[32]] 34 | SCALAR_TYPE@66..75: float[32] 35 | DESIGNATOR@71..75: [32] 36 | LITERAL@72..74: 32 37 | NAME@77..78: c 38 | BIN_EXPR@81..87: a ** b 39 | IDENTIFIER@81..82: a 40 | IDENTIFIER@86..87: b 41 | -------------------------------------------------------------------------------- /crates/oq3_parser/src/token_set.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! A bit-set of `SyntaxKind`s. 5 | 6 | use crate::SyntaxKind; 7 | 8 | /// A bit-set of `SyntaxKind`s 9 | #[derive(Clone, Copy)] 10 | pub(crate) struct TokenSet(u128); 11 | 12 | impl TokenSet { 13 | pub(crate) const EMPTY: TokenSet = TokenSet(0); 14 | 15 | pub(crate) const fn new(kinds: &[SyntaxKind]) -> TokenSet { 16 | let mut res = 0u128; 17 | let mut i = 0; 18 | while i < kinds.len() { 19 | res |= mask(kinds[i]); 20 | i += 1; 21 | } 22 | TokenSet(res) 23 | } 24 | 25 | pub(crate) const fn union(self, other: TokenSet) -> TokenSet { 26 | TokenSet(self.0 | other.0) 27 | } 28 | 29 | pub(crate) const fn contains(&self, kind: SyntaxKind) -> bool { 30 | self.0 & mask(kind) != 0 31 | } 32 | } 33 | 34 | const fn mask(kind: SyntaxKind) -> u128 { 35 | 1u128 << (kind as usize) 36 | } 37 | 38 | #[test] 39 | fn token_set_works_for_tokens() { 40 | use crate::SyntaxKind::*; 41 | let ts = TokenSet::new(&[EOF, COMMENT]); 42 | assert!(ts.contains(EOF)); 43 | assert!(ts.contains(COMMENT)); 44 | assert!(!ts.contains(PLUS)); 45 | } 46 | -------------------------------------------------------------------------------- /crates/oq3_semantics/src/utils.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /// Return the name of the type of a value. 5 | pub fn type_name_of(_: T) -> &'static str { 6 | std::any::type_name::() 7 | } 8 | 9 | /// Like dbg!, but print to stdout 10 | #[macro_export] 11 | macro_rules! dbg_stdout { 12 | // NOTE: We cannot use `concat!` to make a static string as a format argument 13 | // of `println!` because `file!` could contain a `{` or 14 | // `$val` expression could be a block (`{ .. }`), in which case the `println!` 15 | // will be malformed. 16 | () => { 17 | ::std::println!("[{}:{}]", ::std::file!(), ::std::line!()) 18 | }; 19 | ($val:expr $(,)?) => { 20 | // Use of `match` here is intentional because it affects the lifetimes 21 | // of temporaries - https://stackoverflow.com/a/48732525/1063961 22 | match $val { 23 | tmp => { 24 | ::std::println!("[{}:{}] {} = {:#?}", 25 | ::std::file!(), ::std::line!(), ::std::stringify!($val), &tmp); 26 | tmp 27 | } 28 | } 29 | }; 30 | ($($val:expr),+ $(,)?) => { 31 | ($(::std::dbg_stdout!($val)),+,) 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__subroutine__extern.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/subroutine/extern.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..80: 13 | extern test_kern(bit[5], uint[10], float[16], complex[float[64]]) -> float[6]; 14 | 15 | EXTERN_STMT@1..79: extern test_kern(bit[5], uint[10], float[16], complex[float[64]]) -> float[6]; 16 | NAME@8..17: test_kern 17 | TYPE_LIST@17..66: (bit[5], uint[10], float[16], complex[float[64]]) 18 | SCALAR_TYPE@18..24: bit[5] 19 | SCALAR_TYPE@18..24: bit[5] 20 | DESIGNATOR@21..24: [5] 21 | LITERAL@22..23: 5 22 | SCALAR_TYPE@26..34: uint[10] 23 | SCALAR_TYPE@26..34: uint[10] 24 | DESIGNATOR@30..34: [10] 25 | LITERAL@31..33: 10 26 | SCALAR_TYPE@36..45: float[16] 27 | SCALAR_TYPE@36..45: float[16] 28 | DESIGNATOR@41..45: [16] 29 | LITERAL@42..44: 16 30 | SCALAR_TYPE@47..65: complex[float[64]] 31 | SCALAR_TYPE@47..65: complex[float[64]] 32 | SCALAR_TYPE@55..64: float[64] 33 | DESIGNATOR@60..64: [64] 34 | LITERAL@61..63: 64 35 | RETURN_SIGNATURE@67..78: -> float[6] 36 | SCALAR_TYPE@70..78: float[6] 37 | DESIGNATOR@75..78: [6] 38 | LITERAL@76..77: 6 39 | -------------------------------------------------------------------------------- /crates/oq3_syntax/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "oq3_syntax" 3 | description = "Comment and whitespace preserving parser for the OpenQASM 3 parser/analyzer" 4 | version.workspace = true 5 | edition.workspace = true 6 | rust-version.workspace = true 7 | license.workspace = true 8 | authors.workspace = true 9 | readme.workspace = true 10 | keywords.workspace = true 11 | categories.workspace = true 12 | repository.workspace = true 13 | 14 | [lib] 15 | doctest = false 16 | 17 | [dependencies] 18 | # external crates 19 | cov-mark = "2.0.0" 20 | either = "1.15.0" 21 | indexmap = ">=2.8.0, <2.11.0" 22 | #indexmap = "2.8.0" 23 | once_cell = "1.21.0" 24 | rowan = {version = "<=0.16.1"} 25 | rustc-hash = "2.1.1" 26 | smol_str = ">=0.3.0, <0.3.4" 27 | #smol_str = "0.3.2" 28 | triomphe = { version = "<= 0.1.14", default-features = false, features = ["std"] } 29 | rustversion = "1.0" 30 | # local crates 31 | oq3_lexer.workspace = true 32 | oq3_parser.workspace = true 33 | 34 | [dev-dependencies] 35 | rayon = "=1.6.1" 36 | #rayon = "1.6.1" 37 | rayon-core = "=1.12.0" 38 | expect-test = "1.4.0" 39 | clap = { version = "~4.4", features = ["derive"] } 40 | 41 | [build-dependencies] 42 | itertools = "0.14.0" 43 | proc-macro2 = "1.0.47" 44 | quote = "1.0.20" 45 | ungrammar = "1.16.1" 46 | xshell = "0.2.2" 47 | 48 | [features] 49 | sourcegen = [] 50 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | The code in crates `oq3_lexer`, `oq3_parser`, and `oq3_syntax` are derived 2 | from crates in the rust-analyzer project, commit (d398a). 3 | The code in these crates is licensed in this OpenQASM 3 parser project under 4 | the following MIT license: 5 | 6 | Permission is hereby granted, free of charge, to any 7 | person obtaining a copy of this software and associated 8 | documentation files (the "Software"), to deal in the 9 | Software without restriction, including without 10 | limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of 12 | the Software, and to permit persons to whom the Software 13 | is furnished to do so, subject to the following 14 | conditions: 15 | 16 | The above copyright notice and this permission notice 17 | shall be included in all copies or substantial portions 18 | of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 21 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 22 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 23 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 24 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 27 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | DEALINGS IN THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__control_flow__branch_binop.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/control_flow/branch_binop.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..50: 13 | if(spec[i] == 0 && spec[n+i] == 1) { 14 | x q[i]; 15 | } 16 | 17 | IF_STMT@1..49: if(spec[i] == 0 && spec[n+i] == 1) { 18 | x q[i]; 19 | } 20 | BIN_EXPR@4..34: spec[i] == 0 && spec[n+i] == 1 21 | BIN_EXPR@4..16: spec[i] == 0 22 | INDEXED_IDENTIFIER@4..11: spec[i] 23 | IDENTIFIER@4..8: spec 24 | INDEX_OPERATOR@8..11: [i] 25 | EXPRESSION_LIST@9..10: i 26 | IDENTIFIER@9..10: i 27 | LITERAL@15..16: 0 28 | BIN_EXPR@20..34: spec[n+i] == 1 29 | INDEXED_IDENTIFIER@20..29: spec[n+i] 30 | IDENTIFIER@20..24: spec 31 | INDEX_OPERATOR@24..29: [n+i] 32 | EXPRESSION_LIST@25..28: n+i 33 | BIN_EXPR@25..28: n+i 34 | IDENTIFIER@25..26: n 35 | IDENTIFIER@27..28: i 36 | LITERAL@33..34: 1 37 | BLOCK_EXPR@36..49: { 38 | x q[i]; 39 | } 40 | EXPR_STMT@40..47: x q[i]; 41 | GATE_CALL_EXPR@40..46: x q[i] 42 | IDENTIFIER@40..41: x 43 | QUBIT_LIST@42..46: q[i] 44 | INDEXED_IDENTIFIER@42..46: q[i] 45 | IDENTIFIER@42..43: q 46 | INDEX_OPERATOR@43..46: [i] 47 | EXPRESSION_LIST@44..45: i 48 | IDENTIFIER@44..45: i 49 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__comments__comments.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/comments/comments.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | DeclareQuantum(DeclareQuantum { name: Ok(SymbolId(39)) }) 13 | 14 | GateCall(GateCall { name: Ok(SymbolId(10)), params: None, qubits: [TExpr { expression: GateOperand(IndexedIdentifier(IndexedIdentifier { identifier: Ok(SymbolId(39)), indexes: [ExpressionList(ExpressionList { expressions: [TExpr { expression: Literal(Int(IntLiteral { value: 0, sign: true })), ty: Int(Some(128), True) }] })] })), ty: QubitArray(D1(2)) }], modifiers: [] }) 15 | 16 | GateCall(GateCall { name: Ok(SymbolId(25)), params: None, qubits: [TExpr { expression: GateOperand(IndexedIdentifier(IndexedIdentifier { identifier: Ok(SymbolId(39)), indexes: [ExpressionList(ExpressionList { expressions: [TExpr { expression: Literal(Int(IntLiteral { value: 0, sign: true })), ty: Int(Some(128), True) }] })] })), ty: QubitArray(D1(2)) }, TExpr { expression: GateOperand(IndexedIdentifier(IndexedIdentifier { identifier: Ok(SymbolId(39)), indexes: [ExpressionList(ExpressionList { expressions: [TExpr { expression: Literal(Int(IntLiteral { value: 1, sign: true })), ty: Int(Some(128), True) }] })] })), ty: QubitArray(D1(2)) }], modifiers: [] }) 17 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__pulse__cal.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/pulse/cal.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | cal {} 10 | cal {One long, otherwise invalid token.} 11 | cal {Outer {nested} outer} 12 | --- lexer --- 13 | ok: true 14 | errors: 0 15 | [0] Whitespace "\n" @0..1 16 | [1] Ident "cal" @1..4 17 | [2] Whitespace " " @4..5 18 | [3] OpenBrace "{" @5..6 19 | [4] CloseBrace "}" @6..7 20 | [5] Whitespace "\n" @7..8 21 | [6] Ident "cal" @8..11 22 | [7] Whitespace " " @11..12 23 | [8] OpenBrace "{" @12..13 24 | [9] Ident "One" @13..16 25 | [10] Whitespace " " @16..17 26 | [11] Ident "long" @17..21 27 | [12] Comma "," @21..22 28 | [13] Whitespace " " @22..23 29 | [14] Ident "otherwise" @23..32 30 | [15] Whitespace " " @32..33 31 | [16] Ident "invalid" @33..40 32 | [17] Whitespace " " @40..41 33 | [18] Ident "token" @41..46 34 | [19] Dot "." @46..47 35 | [20] CloseBrace "}" @47..48 36 | [21] Whitespace "\n" @48..49 37 | [22] Ident "cal" @49..52 38 | [23] Whitespace " " @52..53 39 | [24] OpenBrace "{" @53..54 40 | [25] Ident "Outer" @54..59 41 | [26] Whitespace " " @59..60 42 | [27] OpenBrace "{" @60..61 43 | [28] Ident "nested" @61..67 44 | [29] CloseBrace "}" @67..68 45 | [30] Whitespace " " @68..69 46 | [31] Ident "outer" @69..74 47 | [32] CloseBrace "}" @74..75 48 | [33] Whitespace "\n" @75..76 49 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__comments__comments_cnot.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/comments/comments_cnot.qasm 6 | expect-sema: Diag 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | DeclareQuantum(DeclareQuantum { name: Ok(SymbolId(39)) }) 13 | 14 | GateCall(GateCall { name: Ok(SymbolId(10)), params: None, qubits: [TExpr { expression: GateOperand(IndexedIdentifier(IndexedIdentifier { identifier: Ok(SymbolId(39)), indexes: [ExpressionList(ExpressionList { expressions: [TExpr { expression: Literal(Int(IntLiteral { value: 0, sign: true })), ty: Int(Some(128), True) }] })] })), ty: QubitArray(D1(2)) }], modifiers: [] }) 15 | 16 | GateCall(GateCall { name: Err(MissingBinding), params: None, qubits: [TExpr { expression: GateOperand(IndexedIdentifier(IndexedIdentifier { identifier: Ok(SymbolId(39)), indexes: [ExpressionList(ExpressionList { expressions: [TExpr { expression: Literal(Int(IntLiteral { value: 0, sign: true })), ty: Int(Some(128), True) }] })] })), ty: QubitArray(D1(2)) }, TExpr { expression: GateOperand(IndexedIdentifier(IndexedIdentifier { identifier: Ok(SymbolId(39)), indexes: [ExpressionList(ExpressionList { expressions: [TExpr { expression: Literal(Int(IntLiteral { value: 1, sign: true })), ty: Int(Some(128), True) }] })] })), ty: QubitArray(D1(2)) }], modifiers: [] }) 17 | -------------------------------------------------------------------------------- /crates/oq3_syntax/src/ast/type_ext.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use crate::{ast, SyntaxToken, T}; 5 | 6 | // `ScalarTypeKind` includes Qubit because thus far, we only 7 | // use it for def can defcall, which allows mixing scalar and qubits 8 | // in a list of parameters. 9 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 10 | pub enum ScalarTypeKind { 11 | Angle, 12 | Bit, 13 | Bool, 14 | Complex, 15 | Duration, 16 | Float, 17 | Int, 18 | None, // Use this to record errors 19 | Stretch, 20 | UInt, 21 | Qubit, 22 | } 23 | 24 | impl ast::ScalarType { 25 | pub fn kind(&self) -> ScalarTypeKind { 26 | use ScalarTypeKind::*; 27 | match self.token().kind() { 28 | T![angle] => Angle, 29 | T![bit] => Bit, 30 | T![bool] => Bool, 31 | T![complex] => Complex, 32 | T![duration] => Duration, 33 | T![float] => Float, 34 | T![int] => Int, 35 | T![stretch] => Stretch, 36 | T![uint] => UInt, 37 | T![qubit] => Qubit, 38 | _ => None, 39 | } 40 | } 41 | 42 | pub fn token(&self) -> SyntaxToken { 43 | self.syntax 44 | .children_with_tokens() 45 | .find(|e| !e.kind().is_trivia()) 46 | .and_then(|e| e.into_token()) 47 | .unwrap() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__control_flow__loop.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/control_flow/loop.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..96: 13 | while (i < 10) { 14 | for uint j in {1, 4, 6} reset q[j]; 15 | if (i == 8) break; 16 | else continue; 17 | } 18 | 19 | WHILE_STMT@1..95: while (i < 10) { 20 | for uint j in {1, 4, 6} reset q[j]; 21 | if (i == 8) break; 22 | else continue; 23 | } 24 | BIN_EXPR@8..14: i < 10 25 | IDENTIFIER@8..9: i 26 | LITERAL@12..14: 10 27 | BLOCK_EXPR@16..95: { 28 | for uint j in {1, 4, 6} reset q[j]; 29 | if (i == 8) break; 30 | else continue; 31 | } 32 | FOR_STMT@20..55: for uint j in {1, 4, 6} reset q[j]; 33 | SCALAR_TYPE@24..28: uint 34 | NAME@29..30: j 35 | FOR_ITERABLE@34..43: {1, 4, 6} 36 | SET_EXPRESSION@34..43: {1, 4, 6} 37 | EXPRESSION_LIST@35..42: 1, 4, 6 38 | LITERAL@35..36: 1 39 | LITERAL@38..39: 4 40 | LITERAL@41..42: 6 41 | RESET@44..55: reset q[j]; 42 | INDEXED_IDENTIFIER@50..54: q[j] 43 | IDENTIFIER@50..51: q 44 | INDEX_OPERATOR@51..54: [j] 45 | EXPRESSION_LIST@52..53: j 46 | IDENTIFIER@52..53: j 47 | IF_STMT@58..93: if (i == 8) break; 48 | else continue; 49 | BIN_EXPR@62..68: i == 8 50 | IDENTIFIER@62..63: i 51 | LITERAL@67..68: 8 52 | BREAK_STMT@70..76: break; 53 | CONTINUE_STMT@84..93: continue; 54 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Rust 3 | 4 | on: 5 | push: 6 | branches: [ "main" ] 7 | pull_request: 8 | branches: [ "main" ] 9 | 10 | env: 11 | CARGO_TERM_COLOR: always 12 | 13 | jobs: 14 | build: 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | os: [ubuntu-latest, macos-13, windows-latest] 20 | steps: 21 | - uses: actions/checkout@v3 22 | - name: Install Just 23 | run: cargo install just 24 | - name: Rust Format 25 | run: just ci 26 | - name: Check source generation 27 | run: just check_sourcegen 28 | 29 | msrv: 30 | runs-on: ${{ matrix.os }} 31 | strategy: 32 | fail-fast: false 33 | matrix: 34 | os: [ubuntu-latest, macos-13, windows-latest] 35 | steps: 36 | - uses: actions/checkout@v3 37 | - name: Install Rust toolchain 38 | uses: dtolnay/rust-toolchain@1.80 39 | - name: Build 40 | run: cargo build --release --verbose 41 | - name: Run tests 42 | run: cargo test --verbose --lib --tests 43 | 44 | stable: 45 | runs-on: ${{ matrix.os }} 46 | strategy: 47 | fail-fast: false 48 | matrix: 49 | os: [ubuntu-latest, macos-13, windows-latest] 50 | steps: 51 | - uses: actions/checkout@v3 52 | - name: Install Rust toolchain 53 | uses: dtolnay/rust-toolchain@stable 54 | - name: Build 55 | run: cargo build --release --verbose 56 | - name: Run tests 57 | run: cargo test --verbose --lib --tests 58 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__switch.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid/statements/switch.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 20 11 | --- ast --- 12 | SOURCE_FILE@0..147: 13 | switch () {} 14 | switch (i) { x $0 } 15 | switch (i) { case {} } 16 | switch (i) { case 1,, {} } 17 | switch (i) { default 0 {} } 18 | switch (i) { default, default {} } 19 | 20 | SWITCH_CASE_STMT@1..13: switch () {} 21 | SWITCH_CASE_STMT@14..26: switch (i) { 22 | IDENTIFIER@22..23: i 23 | GATE_CALL_EXPR@27..31: x $0 24 | IDENTIFIER@27..28: x 25 | QUBIT_LIST@29..31: $0 26 | HARDWARE_QUBIT@29..31: $0 27 | ERROR@32..33: } 28 | SWITCH_CASE_STMT@34..56: switch (i) { case {} } 29 | IDENTIFIER@42..43: i 30 | CASE_EXPR@47..54: case {} 31 | EXPRESSION_LIST@52..52: 32 | BLOCK_EXPR@52..54: {} 33 | SWITCH_CASE_STMT@57..77: switch (i) { case 1, 34 | IDENTIFIER@65..66: i 35 | CASE_EXPR@70..77: case 1, 36 | EXPRESSION_LIST@75..77: 1, 37 | LITERAL@75..76: 1 38 | ERROR@77..78: , 39 | BLOCK_EXPR@79..81: {} 40 | ERROR@82..83: } 41 | SWITCH_CASE_STMT@84..104: switch (i) { default 42 | IDENTIFIER@92..93: i 43 | EXPR_STMT@105..106: 0 44 | LITERAL@105..106: 0 45 | BLOCK_EXPR@107..109: {} 46 | ERROR@110..111: } 47 | SWITCH_CASE_STMT@112..132: switch (i) { default 48 | IDENTIFIER@120..121: i 49 | ERROR@132..133: , 50 | ERROR@134..141: default 51 | BLOCK_EXPR@142..144: {} 52 | ERROR@145..146: } 53 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__gate__quantum_gate.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/gate/quantum_gate.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..122: 13 | include "stdlib.qasm"; 14 | 15 | gate test_gate(theta) a, b { 16 | reset a; 17 | barrier b; 18 | gphase(-theta/2); 19 | CX a, b; 20 | barrier; 21 | } 22 | 23 | INCLUDE@1..23: include "stdlib.qasm"; 24 | FILE_PATH@9..22: "stdlib.qasm" 25 | GATE@25..121: gate test_gate(theta) a, b { 26 | reset a; 27 | barrier b; 28 | gphase(-theta/2); 29 | CX a, b; 30 | barrier; 31 | } 32 | NAME@30..39: test_gate 33 | PARAM_LIST@39..46: (theta) 34 | PARAM@40..45: theta 35 | PARAM_LIST@47..51: a, b 36 | PARAM@47..48: a 37 | PARAM@50..51: b 38 | BLOCK_EXPR@52..121: { 39 | reset a; 40 | barrier b; 41 | gphase(-theta/2); 42 | CX a, b; 43 | barrier; 44 | } 45 | RESET@56..64: reset a; 46 | IDENTIFIER@62..63: a 47 | BARRIER@67..77: barrier b; 48 | QUBIT_LIST@75..76: b 49 | IDENTIFIER@75..76: b 50 | EXPR_STMT@80..97: gphase(-theta/2); 51 | G_PHASE_CALL_EXPR@80..96: gphase(-theta/2) 52 | PAREN_EXPR@86..96: (-theta/2) 53 | BIN_EXPR@87..95: -theta/2 54 | PREFIX_EXPR@87..93: -theta 55 | IDENTIFIER@88..93: theta 56 | LITERAL@94..95: 2 57 | EXPR_STMT@100..108: CX a, b; 58 | GATE_CALL_EXPR@100..107: CX a, b 59 | IDENTIFIER@100..102: CX 60 | QUBIT_LIST@103..107: a, b 61 | IDENTIFIER@103..104: a 62 | IDENTIFIER@106..107: b 63 | BARRIER@111..119: barrier; 64 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__order_of_ops.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/expression/order_of_ops.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..50: 13 | a[1]+2|c*(sin(y)^!3.5*d[3]); 14 | b = bit[8](a)[2:4]; 15 | 16 | EXPR_STMT@1..29: a[1]+2|c*(sin(y)^!3.5*d[3]); 17 | BIN_EXPR@1..28: a[1]+2|c*(sin(y)^!3.5*d[3]) 18 | BIN_EXPR@1..7: a[1]+2 19 | INDEXED_IDENTIFIER@1..5: a[1] 20 | IDENTIFIER@1..2: a 21 | INDEX_OPERATOR@2..5: [1] 22 | EXPRESSION_LIST@3..4: 1 23 | LITERAL@3..4: 1 24 | LITERAL@6..7: 2 25 | BIN_EXPR@8..28: c*(sin(y)^!3.5*d[3]) 26 | IDENTIFIER@8..9: c 27 | PAREN_EXPR@10..28: (sin(y)^!3.5*d[3]) 28 | BIN_EXPR@11..27: sin(y)^!3.5*d[3] 29 | CALL_EXPR@11..17: sin(y) 30 | IDENTIFIER@11..14: sin 31 | ARG_LIST@14..17: (y) 32 | EXPRESSION_LIST@14..17: (y) 33 | IDENTIFIER@15..16: y 34 | BIN_EXPR@18..27: !3.5*d[3] 35 | PREFIX_EXPR@18..22: !3.5 36 | LITERAL@19..22: 3.5 37 | INDEXED_IDENTIFIER@23..27: d[3] 38 | IDENTIFIER@23..24: d 39 | INDEX_OPERATOR@24..27: [3] 40 | EXPRESSION_LIST@25..26: 3 41 | LITERAL@25..26: 3 42 | ASSIGNMENT_STMT@30..49: b = bit[8](a)[2:4]; 43 | IDENTIFIER@30..31: b 44 | INDEX_EXPR@34..48: bit[8](a)[2:4] 45 | CAST_EXPRESSION@34..43: bit[8](a) 46 | SCALAR_TYPE@34..40: bit[8] 47 | DESIGNATOR@37..40: [8] 48 | LITERAL@38..39: 8 49 | IDENTIFIER@41..42: a 50 | INDEX_OPERATOR@43..48: [2:4] 51 | EXPRESSION_LIST@44..47: 2:4 52 | RANGE_EXPR@44..47: 2:4 53 | LITERAL@44..45: 2 54 | LITERAL@46..47: 4 55 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__sub_and_extern_call.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/expression/sub_and_extern_call.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..95: 13 | bit x = sub_call(10, "01", q1[0], q2); 14 | int[2] y = extern_call(0.5, 10dt); 15 | ambiguous_call(pi); 16 | 17 | CLASSICAL_DECLARATION_STATEMENT@1..39: bit x = sub_call(10, "01", q1[0], q2); 18 | SCALAR_TYPE@1..4: bit 19 | NAME@5..6: x 20 | CALL_EXPR@9..38: sub_call(10, "01", q1[0], q2) 21 | IDENTIFIER@9..17: sub_call 22 | ARG_LIST@17..38: (10, "01", q1[0], q2) 23 | EXPRESSION_LIST@17..38: (10, "01", q1[0], q2) 24 | LITERAL@18..20: 10 25 | LITERAL@22..26: "01" 26 | INDEXED_IDENTIFIER@28..33: q1[0] 27 | IDENTIFIER@28..30: q1 28 | INDEX_OPERATOR@30..33: [0] 29 | EXPRESSION_LIST@31..32: 0 30 | LITERAL@31..32: 0 31 | IDENTIFIER@35..37: q2 32 | CLASSICAL_DECLARATION_STATEMENT@40..74: int[2] y = extern_call(0.5, 10dt); 33 | SCALAR_TYPE@40..46: int[2] 34 | DESIGNATOR@43..46: [2] 35 | LITERAL@44..45: 2 36 | NAME@47..48: y 37 | CALL_EXPR@51..73: extern_call(0.5, 10dt) 38 | IDENTIFIER@51..62: extern_call 39 | ARG_LIST@62..73: (0.5, 10dt) 40 | EXPRESSION_LIST@62..73: (0.5, 10dt) 41 | LITERAL@63..66: 0.5 42 | TIMING_LITERAL@68..72: 10dt 43 | LITERAL@68..70: 10 44 | IDENTIFIER@70..72: dt 45 | EXPR_STMT@75..94: ambiguous_call(pi); 46 | CALL_EXPR@75..93: ambiguous_call(pi) 47 | IDENTIFIER@75..89: ambiguous_call 48 | ARG_LIST@89..93: (pi) 49 | EXPRESSION_LIST@89..93: (pi) 50 | IDENTIFIER@90..92: pi 51 | -------------------------------------------------------------------------------- /crates/oq3_semantics/tests/specification_example_tests.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use oq3_semantics::asg; 5 | use oq3_semantics::semantic_error::SemanticErrorList; 6 | use oq3_semantics::symbols::SymbolTable; 7 | use oq3_semantics::syntax_to_semantics::parse_source_string; 8 | //use oq3_semantics::types::{ArrayDims, IsConst, Type}; 9 | 10 | fn parse_string(code: &str) -> (asg::Program, SemanticErrorList, SymbolTable) { 11 | parse_source_string(code, None).take_context().as_tuple() 12 | } 13 | 14 | #[test] 15 | fn test_subroutines_1() { 16 | let code = r#" 17 | include "stdgates.inc"; 18 | def xmeasure(qubit q) -> bit { h q; return measure q; } 19 | "#; 20 | let (program, errors, _symbol_table) = parse_string(code); 21 | assert_eq!(errors.len(), 0); 22 | assert_eq!(program.len(), 1); 23 | } 24 | 25 | #[test] 26 | fn test_subroutines_2() { 27 | let code = r#" 28 | include "stdgates.inc"; 29 | def pmeasure(angle[32] theta, qubit q) -> bit { 30 | rz(theta) q; 31 | h q; 32 | return measure q; 33 | } 34 | "#; 35 | let (program, errors, _symbol_table) = parse_string(code); 36 | assert_eq!(errors.len(), 0); 37 | assert_eq!(program.len(), 1); 38 | } 39 | 40 | #[test] 41 | fn test_subroutines_3() { 42 | let code = r#" 43 | include "stdgates.inc"; 44 | def xcheck(qubit[4] d, qubit a) -> bit { 45 | reset a; 46 | for int i in [0: 3] cx d[i], a; 47 | return measure a; 48 | } 49 | "#; 50 | let (program, errors, _symbol_table) = parse_string(code); 51 | assert_eq!(errors.len(), 0); 52 | assert_eq!(program.len(), 1); 53 | } 54 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__gate__gate_modifiers.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/gate/gate_modifiers.qasm 6 | expect-sema: Ok 7 | --- sema --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- asg --- 12 | DeclareQuantum(DeclareQuantum { name: Ok(SymbolId(7)) }) 13 | 14 | GateDefinition(GateDefinition { name: Ok(SymbolId(9)), params: None, qubits: [Ok(SymbolId(8))], block: Block { statements: [] } }) 15 | 16 | GateCall(GateCall { name: Ok(SymbolId(9)), params: None, qubits: [TExpr { expression: GateOperand(Identifier(Ok(SymbolId(7)))), ty: Qubit }], modifiers: [Ctrl(Some(TExpr { expression: Literal(Int(IntLiteral { value: 2, sign: true })), ty: Int(Some(128), True) }))] }) 17 | 18 | GateCall(GateCall { name: Ok(SymbolId(9)), params: None, qubits: [TExpr { expression: GateOperand(Identifier(Ok(SymbolId(7)))), ty: Qubit }], modifiers: [NegCtrl(Some(TExpr { expression: Literal(Int(IntLiteral { value: 3, sign: true })), ty: Int(Some(128), True) }))] }) 19 | 20 | GateCall(GateCall { name: Ok(SymbolId(9)), params: None, qubits: [TExpr { expression: GateOperand(Identifier(Ok(SymbolId(7)))), ty: Qubit }], modifiers: [Pow(TExpr { expression: BinaryExpr(BinaryExpr { op: ArithOp(Div), left: TExpr { expression: Literal(Float(FloatLiteral { value: "-1" })), ty: Float(Some(64), True) }, right: TExpr { expression: Literal(Float(FloatLiteral { value: "2" })), ty: Float(Some(64), True) } }), ty: Float(Some(64), True) })] }) 21 | 22 | GateCall(GateCall { name: Ok(SymbolId(9)), params: None, qubits: [TExpr { expression: GateOperand(Identifier(Ok(SymbolId(7)))), ty: Qubit }], modifiers: [Inv] }) 23 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__control_flow__branching.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/control_flow/branching.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..96: 13 | include "stdgates.inc"; 14 | if (x == a) { 15 | for uint i in [0:2:4] x[i] += 1; 16 | } 17 | else CX x[0], x[1]; 18 | 19 | INCLUDE@1..24: include "stdgates.inc"; 20 | FILE_PATH@9..23: "stdgates.inc" 21 | IF_STMT@25..95: if (x == a) { 22 | for uint i in [0:2:4] x[i] += 1; 23 | } 24 | else CX x[0], x[1]; 25 | BIN_EXPR@29..35: x == a 26 | IDENTIFIER@29..30: x 27 | IDENTIFIER@34..35: a 28 | BLOCK_EXPR@37..75: { 29 | for uint i in [0:2:4] x[i] += 1; 30 | } 31 | FOR_STMT@41..73: for uint i in [0:2:4] x[i] += 1; 32 | SCALAR_TYPE@45..49: uint 33 | NAME@50..51: i 34 | FOR_ITERABLE@55..62: [0:2:4] 35 | RANGE_EXPR@55..62: [0:2:4] 36 | LITERAL@56..57: 0 37 | LITERAL@58..59: 2 38 | LITERAL@60..61: 4 39 | EXPR_STMT@63..73: x[i] += 1; 40 | BIN_EXPR@63..72: x[i] += 1 41 | INDEXED_IDENTIFIER@63..67: x[i] 42 | IDENTIFIER@63..64: x 43 | INDEX_OPERATOR@64..67: [i] 44 | EXPRESSION_LIST@65..66: i 45 | IDENTIFIER@65..66: i 46 | LITERAL@71..72: 1 47 | EXPR_STMT@81..95: CX x[0], x[1]; 48 | GATE_CALL_EXPR@81..94: CX x[0], x[1] 49 | IDENTIFIER@81..83: CX 50 | QUBIT_LIST@84..94: x[0], x[1] 51 | INDEXED_IDENTIFIER@84..88: x[0] 52 | IDENTIFIER@84..85: x 53 | INDEX_OPERATOR@85..88: [0] 54 | EXPRESSION_LIST@86..87: 0 55 | LITERAL@86..87: 0 56 | INDEXED_IDENTIFIER@90..94: x[1] 57 | IDENTIFIER@90..91: x 58 | INDEX_OPERATOR@91..94: [1] 59 | EXPRESSION_LIST@92..93: 1 60 | LITERAL@92..93: 1 61 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__comments__comments.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/comments/comments.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..292: 13 | OPENQASM 3.0; 14 | // Line comment before include 15 | include "stdgates.inc"; // Inline comment 16 | /* Block comment before declaration */ 17 | qubit[2] q; /* Inline block comment */ 18 | 19 | // Comment before gate 20 | h q[0]; // Gate with comment 21 | /* Multi-line block comment 22 | spanning multiple lines */ 23 | cx q[0], q[1]; 24 | 25 | VERSION_STRING@1..14: OPENQASM 3.0; 26 | INCLUDE@46..69: include "stdgates.inc"; 27 | FILE_PATH@54..68: "stdgates.inc" 28 | QUANTUM_DECLARATION_STATEMENT@127..138: qubit[2] q; 29 | QUBIT_TYPE@127..135: qubit[2] 30 | DESIGNATOR@132..135: [2] 31 | LITERAL@133..134: 2 32 | NAME@136..137: q 33 | EXPR_STMT@190..197: h q[0]; 34 | GATE_CALL_EXPR@190..196: h q[0] 35 | IDENTIFIER@190..191: h 36 | QUBIT_LIST@192..196: q[0] 37 | INDEXED_IDENTIFIER@192..196: q[0] 38 | IDENTIFIER@192..193: q 39 | INDEX_OPERATOR@193..196: [0] 40 | EXPRESSION_LIST@194..195: 0 41 | LITERAL@194..195: 0 42 | EXPR_STMT@277..291: cx q[0], q[1]; 43 | GATE_CALL_EXPR@277..290: cx q[0], q[1] 44 | IDENTIFIER@277..279: cx 45 | QUBIT_LIST@280..290: q[0], q[1] 46 | INDEXED_IDENTIFIER@280..284: q[0] 47 | IDENTIFIER@280..281: q 48 | INDEX_OPERATOR@281..284: [0] 49 | EXPRESSION_LIST@282..283: 0 50 | LITERAL@282..283: 0 51 | INDEXED_IDENTIFIER@286..290: q[1] 52 | IDENTIFIER@286..287: q 53 | INDEX_OPERATOR@287..290: [1] 54 | EXPRESSION_LIST@288..289: 1 55 | LITERAL@288..289: 1 56 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__control_flow__branch_binop.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/control_flow/branch_binop.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | if(spec[i] == 0 && spec[n+i] == 1) { 10 | x q[i]; 11 | } 12 | --- lexer --- 13 | ok: true 14 | errors: 0 15 | [0] Whitespace "\n" @0..1 16 | [1] Ident "if" @1..3 17 | [2] OpenParen "(" @3..4 18 | [3] Ident "spec" @4..8 19 | [4] OpenBracket "[" @8..9 20 | [5] Ident "i" @9..10 21 | [6] CloseBracket "]" @10..11 22 | [7] Whitespace " " @11..12 23 | [8] Eq "=" @12..13 24 | [9] Eq "=" @13..14 25 | [10] Whitespace " " @14..15 26 | [11] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @15..16 27 | [12] Whitespace " " @16..17 28 | [13] And "&" @17..18 29 | [14] And "&" @18..19 30 | [15] Whitespace " " @19..20 31 | [16] Ident "spec" @20..24 32 | [17] OpenBracket "[" @24..25 33 | [18] Ident "n" @25..26 34 | [19] Plus "+" @26..27 35 | [20] Ident "i" @27..28 36 | [21] CloseBracket "]" @28..29 37 | [22] Whitespace " " @29..30 38 | [23] Eq "=" @30..31 39 | [24] Eq "=" @31..32 40 | [25] Whitespace " " @32..33 41 | [26] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @33..34 42 | [27] CloseParen ")" @34..35 43 | [28] Whitespace " " @35..36 44 | [29] OpenBrace "{" @36..37 45 | [30] Whitespace "\n " @37..40 46 | [31] Ident "x" @40..41 47 | [32] Whitespace " " @41..42 48 | [33] Ident "q" @42..43 49 | [34] OpenBracket "[" @43..44 50 | [35] Ident "i" @44..45 51 | [36] CloseBracket "]" @45..46 52 | [37] Semi ";" @46..47 53 | [38] Whitespace "\n" @47..48 54 | [39] CloseBrace "}" @48..49 55 | [40] Whitespace "\n" @49..50 56 | -------------------------------------------------------------------------------- /crates/oq3_semantics/tests/types_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use oq3_semantics::types; 5 | 6 | // 7 | // Types 8 | // 9 | 10 | #[test] 11 | fn test_int_type_const() { 12 | use types::{IsConst, Type}; 13 | 14 | let typ = Type::Int(Some(32), IsConst::True); 15 | assert_eq!(typ.width(), Some(32)); 16 | assert!(typ.is_scalar()); 17 | assert!(typ.is_const()); 18 | assert!(!typ.is_quantum()); 19 | } 20 | 21 | #[test] 22 | fn test_int_type_not_const() { 23 | use types::{IsConst, Type}; 24 | 25 | let typ = Type::Int(Some(32), IsConst::False); 26 | assert_eq!(typ.width(), Some(32)); 27 | assert!(typ.is_scalar()); 28 | assert!(!typ.is_const()); 29 | assert!(!typ.is_quantum()); 30 | } 31 | 32 | #[test] 33 | fn test_int_type_no_width() { 34 | use types::{IsConst, Type}; 35 | 36 | let typ = Type::Int(None, IsConst::False); // No width 37 | assert!(typ.width().is_none()); 38 | assert!(typ.is_scalar()); 39 | assert!(!typ.is_const()); 40 | assert!(!typ.is_quantum()); 41 | } 42 | 43 | #[test] 44 | fn test_qubit_type_single_qubit() { 45 | use types::Type; 46 | 47 | let typ = Type::Qubit; 48 | assert!(typ.width().is_none()); 49 | assert!(!typ.is_scalar()); 50 | assert!(typ.is_const()); 51 | assert!(typ.is_quantum()); 52 | } 53 | 54 | // #[test] 55 | // fn test_qubit_type_qubit_register() { 56 | // use types::{Type}; 57 | 58 | // let width = 100; 59 | // let typ = Type::Qubit(Some(width)); 60 | // assert_eq!(typ.width(), Some(width)); 61 | // assert_eq!(typ.is_scalar(), false); 62 | // assert_eq!(typ.is_const(), false); 63 | // assert_eq!(typ.is_quantum(), true); 64 | // } 65 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__comments__comments_cnot.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/comments/comments_cnot.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..294: 13 | OPENQASM 3.0; 14 | // Line comment before include 15 | include "stdgates.inc"; // Inline comment 16 | /* Block comment before declaration */ 17 | qubit[2] q; /* Inline block comment */ 18 | 19 | // Comment before gate 20 | h q[0]; // Gate with comment 21 | /* Multi-line block comment 22 | spanning multiple lines */ 23 | cnot q[0], q[1]; 24 | 25 | VERSION_STRING@1..14: OPENQASM 3.0; 26 | INCLUDE@46..69: include "stdgates.inc"; 27 | FILE_PATH@54..68: "stdgates.inc" 28 | QUANTUM_DECLARATION_STATEMENT@127..138: qubit[2] q; 29 | QUBIT_TYPE@127..135: qubit[2] 30 | DESIGNATOR@132..135: [2] 31 | LITERAL@133..134: 2 32 | NAME@136..137: q 33 | EXPR_STMT@190..197: h q[0]; 34 | GATE_CALL_EXPR@190..196: h q[0] 35 | IDENTIFIER@190..191: h 36 | QUBIT_LIST@192..196: q[0] 37 | INDEXED_IDENTIFIER@192..196: q[0] 38 | IDENTIFIER@192..193: q 39 | INDEX_OPERATOR@193..196: [0] 40 | EXPRESSION_LIST@194..195: 0 41 | LITERAL@194..195: 0 42 | EXPR_STMT@277..293: cnot q[0], q[1]; 43 | GATE_CALL_EXPR@277..292: cnot q[0], q[1] 44 | IDENTIFIER@277..281: cnot 45 | QUBIT_LIST@282..292: q[0], q[1] 46 | INDEXED_IDENTIFIER@282..286: q[0] 47 | IDENTIFIER@282..283: q 48 | INDEX_OPERATOR@283..286: [0] 49 | EXPRESSION_LIST@284..285: 0 50 | LITERAL@284..285: 0 51 | INDEXED_IDENTIFIER@288..292: q[1] 52 | IDENTIFIER@288..289: q 53 | INDEX_OPERATOR@289..292: [1] 54 | EXPRESSION_LIST@290..291: 1 55 | LITERAL@290..291: 1 56 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snippets/invalid/statements/declarations.qasm: -------------------------------------------------------------------------------- 1 | // lex: ok 2 | // WARNING. SKIP PARSING. PARSER HANGS 3 | // Bug in runner.rs. parsing will run even if tagged "skip" 4 | // parse: skip 5 | // sema: skip 6 | 7 | // Not specifying the variable. 8 | float; 9 | uint[8]; 10 | qreg[4]; 11 | creg[4]; 12 | complex[float[32]]; 13 | 14 | // Incorrect designators. 15 | int[8, 8] myvar; 16 | uint[8, 8] myvar; 17 | float[8, 8] myvar; 18 | angle[8, 8] myvar; 19 | bool[4] myvar; 20 | bool[4, 4] myvar; 21 | bit[4, 4] myvar; 22 | creg[2] myvar; 23 | creg[2, 2] myvar; 24 | qreg[2] myvar; 25 | qreg[2, 2] myvar; 26 | complex[32] myvar; 27 | complex[mytype] myvar; 28 | complex[float[32], float[32]] myvar; 29 | complex[qreg] myvar; 30 | complex[creg] myvar; 31 | complex[qreg[8]] myvar; 32 | complex[creg[8]] myvar; 33 | 34 | // Bad array specifiers. 35 | array myvar; 36 | array[8] myvar; 37 | array[not_a_type, 4] myvar; 38 | array[int[8], int[8], 2] myvar; 39 | 40 | // Invalid identifiers. 41 | int[8] int; 42 | int[8] def; 43 | int[8] 0; 44 | int[8] input; 45 | 46 | // Bad assignments. 47 | int[8] myvar = end; 48 | int[8] myvar =; 49 | float[32] myvar_f = int[32] myvar_i = 2; 50 | // array initialiser uses {} 51 | array[uint[8], 4] myvar = [4, 5, 6, 7]; 52 | // can't use arithmetic on the entire initialiser 53 | array[uint[8], 4] myvar = 2 * {1, 2, 3, 4}; 54 | // backed arrays can't use #dim 55 | array[uint[8], #dim=2] myvar; 56 | // can't have more than one type specification 57 | array[int[8], int[8]] myvar; 58 | 59 | // Incorrect orders. 60 | myvar: int[8]; 61 | myvar int[8]; 62 | int myvar[8]; 63 | uint myvar[8]; 64 | float myvar[32]; 65 | 66 | // Compound assignments. 67 | int[8] myvar1, myvar2; 68 | int[8] myvari, float[32] myvarf; 69 | int[8] myvari float[32] myvarf; 70 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__binary_expr.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/expression/binary_expr.qasm 6 | expect-sema: Ok 7 | --- sema --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- asg --- 12 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(7)), initializer: Some(TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(Int(IntLiteral { value: 0, sign: true })), ty: Int(Some(128), True) }, typ: Int(None, False) }), ty: Int(None, False) }) }) 13 | 14 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(8)), initializer: Some(TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(Int(IntLiteral { value: 1, sign: true })), ty: Int(Some(128), True) }, typ: Int(None, False) }), ty: Int(None, False) }) }) 15 | 16 | ExprStmt(TExpr { expression: BinaryExpr(BinaryExpr { op: ArithOp(Add), left: TExpr { expression: Literal(Int(IntLiteral { value: 2, sign: true })), ty: Int(Some(128), True) }, right: TExpr { expression: Literal(Int(IntLiteral { value: 2, sign: true })), ty: Int(Some(128), True) } }), ty: Int(Some(128), True) }) 17 | 18 | ExprStmt(TExpr { expression: BinaryExpr(BinaryExpr { op: ConcatenationOp, left: TExpr { expression: Literal(Int(IntLiteral { value: 2, sign: true })), ty: Int(Some(128), True) }, right: TExpr { expression: Literal(Int(IntLiteral { value: 2, sign: true })), ty: Int(Some(128), True) } }), ty: ToDo }) 19 | 20 | ExprStmt(TExpr { expression: BinaryExpr(BinaryExpr { op: ArithOp(Shl), left: TExpr { expression: Identifier(Ok(SymbolId(7))), ty: Int(None, False) }, right: TExpr { expression: Identifier(Ok(SymbolId(8))), ty: Int(None, False) } }), ty: Int(None, False) }) 21 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__scope__nop.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/scope/nop.qasm 6 | expect-parse: Todo 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- ast --- 12 | SOURCE_FILE@0..80: 13 | nop; 14 | nop $0; 15 | nop $1, $2; 16 | nop q, q[0],; 17 | box { 18 | nop $0; 19 | } 20 | gate x q { 21 | nop q; 22 | } 23 | 24 | EXPR_STMT@1..5: nop; 25 | IDENTIFIER@1..4: nop 26 | EXPR_STMT@6..13: nop $0; 27 | GATE_CALL_EXPR@6..12: nop $0 28 | IDENTIFIER@6..9: nop 29 | QUBIT_LIST@10..12: $0 30 | HARDWARE_QUBIT@10..12: $0 31 | EXPR_STMT@14..25: nop $1, $2; 32 | GATE_CALL_EXPR@14..24: nop $1, $2 33 | IDENTIFIER@14..17: nop 34 | QUBIT_LIST@18..24: $1, $2 35 | HARDWARE_QUBIT@18..20: $1 36 | HARDWARE_QUBIT@22..24: $2 37 | EXPR_STMT@26..39: nop q, q[0],; 38 | GATE_CALL_EXPR@26..38: nop q, q[0], 39 | IDENTIFIER@26..29: nop 40 | QUBIT_LIST@30..38: q, q[0], 41 | IDENTIFIER@30..31: q 42 | INDEXED_IDENTIFIER@33..37: q[0] 43 | IDENTIFIER@33..34: q 44 | INDEX_OPERATOR@34..37: [0] 45 | EXPRESSION_LIST@35..36: 0 46 | LITERAL@35..36: 0 47 | EXPR_STMT@40..57: box { 48 | nop $0; 49 | } 50 | BOX_EXPR@40..57: box { 51 | nop $0; 52 | } 53 | BLOCK_EXPR@44..57: { 54 | nop $0; 55 | } 56 | EXPR_STMT@48..55: nop $0; 57 | GATE_CALL_EXPR@48..54: nop $0 58 | IDENTIFIER@48..51: nop 59 | QUBIT_LIST@52..54: $0 60 | HARDWARE_QUBIT@52..54: $0 61 | GATE@58..79: gate x q { 62 | nop q; 63 | } 64 | NAME@63..64: x 65 | PARAM_LIST@65..66: q 66 | PARAM@65..66: q 67 | BLOCK_EXPR@67..79: { 68 | nop q; 69 | } 70 | EXPR_STMT@71..77: nop q; 71 | GATE_CALL_EXPR@71..76: nop q 72 | IDENTIFIER@71..74: nop 73 | QUBIT_LIST@75..76: q 74 | IDENTIFIER@75..76: q 75 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__header.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/header.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | OPENQASM 3.0; 10 | include "stdgates.inc"; 11 | input angle[32] param1; 12 | input angle[32] param2; 13 | output bit result; 14 | --- lexer --- 15 | ok: true 16 | errors: 0 17 | [0] Whitespace "\n" @0..1 18 | [1] OpenQasmVersionStmt { major: true, minor: true } "OPENQASM 3.0" @1..13 19 | [2] Semi ";" @13..14 20 | [3] Whitespace "\n" @14..15 21 | [4] Ident "include" @15..22 22 | [5] Whitespace " " @22..23 23 | [6] Literal { kind: Str { terminated: true }, suffix_start: 14 } ""stdgates.inc"" @23..37 24 | [7] Semi ";" @37..38 25 | [8] Whitespace "\n" @38..39 26 | [9] Ident "input" @39..44 27 | [10] Whitespace " " @44..45 28 | [11] Ident "angle" @45..50 29 | [12] OpenBracket "[" @50..51 30 | [13] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "32" @51..53 31 | [14] CloseBracket "]" @53..54 32 | [15] Whitespace " " @54..55 33 | [16] Ident "param1" @55..61 34 | [17] Semi ";" @61..62 35 | [18] Whitespace "\n" @62..63 36 | [19] Ident "input" @63..68 37 | [20] Whitespace " " @68..69 38 | [21] Ident "angle" @69..74 39 | [22] OpenBracket "[" @74..75 40 | [23] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "32" @75..77 41 | [24] CloseBracket "]" @77..78 42 | [25] Whitespace " " @78..79 43 | [26] Ident "param2" @79..85 44 | [27] Semi ";" @85..86 45 | [28] Whitespace "\n" @86..87 46 | [29] Ident "output" @87..93 47 | [30] Whitespace " " @93..94 48 | [31] Ident "bit" @94..97 49 | [32] Whitespace " " @97..98 50 | [33] Ident "result" @98..104 51 | [34] Semi ";" @104..105 52 | [35] Whitespace "\n" @105..106 53 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__const.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid/statements/const.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 29 11 | --- ast --- 12 | SOURCE_FILE@0..143: 13 | const myvar; 14 | const myvar = ; 15 | const myvar = 8.0; 16 | input const myvar = 8; 17 | output const myvar = 8; 18 | const input myvar = 8; 19 | const output myvar = 8; 20 | 21 | CLASSICAL_DECLARATION_STATEMENT@1..13: const myvar; 22 | SCALAR_TYPE@7..7: 23 | NAME@7..12: myvar 24 | CLASSICAL_DECLARATION_STATEMENT@14..29: const myvar = ; 25 | SCALAR_TYPE@20..20: 26 | NAME@20..25: myvar 27 | ERROR@28..29: ; 28 | CLASSICAL_DECLARATION_STATEMENT@30..48: const myvar = 8.0; 29 | SCALAR_TYPE@36..36: 30 | NAME@36..41: myvar 31 | LITERAL@44..47: 8.0 32 | I_O_DECLARATION_STATEMENT@49..55: input 33 | SCALAR_TYPE@55..55: 34 | NAME@55..55: 35 | CLASSICAL_DECLARATION_STATEMENT@55..71: const myvar = 8; 36 | SCALAR_TYPE@61..61: 37 | NAME@61..66: myvar 38 | LITERAL@69..70: 8 39 | I_O_DECLARATION_STATEMENT@72..79: output 40 | SCALAR_TYPE@79..79: 41 | NAME@79..79: 42 | CLASSICAL_DECLARATION_STATEMENT@79..95: const myvar = 8; 43 | SCALAR_TYPE@85..85: 44 | NAME@85..90: myvar 45 | LITERAL@93..94: 8 46 | SCALAR_TYPE@102..102: 47 | NAME@102..102: 48 | I_O_DECLARATION_STATEMENT@102..113: input myvar 49 | SCALAR_TYPE@108..108: 50 | NAME@108..113: myvar 51 | ERROR@114..115: = 52 | EXPR_STMT@116..118: 8; 53 | LITERAL@116..117: 8 54 | SCALAR_TYPE@125..125: 55 | NAME@125..125: 56 | I_O_DECLARATION_STATEMENT@125..137: output myvar 57 | SCALAR_TYPE@132..132: 58 | NAME@132..137: myvar 59 | ERROR@138..139: = 60 | EXPR_STMT@140..142: 8; 61 | LITERAL@140..141: 8 62 | -------------------------------------------------------------------------------- /crates/oq3_semantics/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Abstract Semantic Graph (ASG) 5 | //! This crate implements an abstract semantic graph (ASG) for the OpenQASM 3 language. 6 | //! Currently the semantic information encoded in this ASG includes: 7 | //! All identifiers are resolved to (scoped) symbols. 8 | //! All expressions are annotated with a type. 9 | //! 10 | //! This kind of structure is often refered to as something like an AST decorated with semantic 11 | //! information, even though it's not really a tree, but rather a directed acyclic graph. We use the 12 | //! acronym ASG here not to be pedantic but rather to have an easy and succinct way to distinguish 13 | //! the output of syntactic analysis from output of semantic analysis. 14 | 15 | // This code is littered with FIXME. This doesn't always mean something needs to be FIXED. 16 | // All FIXME's should be turned into external Issues (ie on GH) or just removed if obsolete. 17 | 18 | // Organization of API 19 | // We opt for adding one level of hierarchy to the API by using file structure. 20 | // This is useful for example because one might want to manipulate the ASG (in asg.rs), 21 | // but not need to construct the ASG from the output of the parser (in syntax_to_semantics.rs) 22 | // Whether types and symbols should be separate is a bit less clear. 23 | // An alternative is to make these modules private and introduce new modules here in lib.rs 24 | // that only `use` things from the file-level modules. 25 | 26 | pub mod asg; 27 | pub mod context; 28 | pub mod semantic_error; 29 | pub mod symbols; 30 | pub mod syntax_to_semantics; 31 | pub mod types; 32 | pub mod validate; 33 | 34 | pub use rowan::{TextRange, TextSize}; 35 | 36 | // mod display; 37 | 38 | mod utils; 39 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__pulse__cal2.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/pulse/cal2.qasm 6 | expect-lex: Todo 7 | --- source --- 8 | 9 | cal {} 10 | cal {One long, otherwise invalid token.} 11 | cal {Outer {nested} outer} 12 | cal {£$&£*(")} 13 | 14 | --- lexer --- 15 | ok: false 16 | errors: 1 17 | [0] Whitespace "\n" @0..1 18 | [1] Ident "cal" @1..4 19 | [2] Whitespace " " @4..5 20 | [3] OpenBrace "{" @5..6 21 | [4] CloseBrace "}" @6..7 22 | [5] Whitespace "\n" @7..8 23 | [6] Ident "cal" @8..11 24 | [7] Whitespace " " @11..12 25 | [8] OpenBrace "{" @12..13 26 | [9] Ident "One" @13..16 27 | [10] Whitespace " " @16..17 28 | [11] Ident "long" @17..21 29 | [12] Comma "," @21..22 30 | [13] Whitespace " " @22..23 31 | [14] Ident "otherwise" @23..32 32 | [15] Whitespace " " @32..33 33 | [16] Ident "invalid" @33..40 34 | [17] Whitespace " " @40..41 35 | [18] Ident "token" @41..46 36 | [19] Dot "." @46..47 37 | [20] CloseBrace "}" @47..48 38 | [21] Whitespace "\n" @48..49 39 | [22] Ident "cal" @49..52 40 | [23] Whitespace " " @52..53 41 | [24] OpenBrace "{" @53..54 42 | [25] Ident "Outer" @54..59 43 | [26] Whitespace " " @59..60 44 | [27] OpenBrace "{" @60..61 45 | [28] Ident "nested" @61..67 46 | [29] CloseBrace "}" @67..68 47 | [30] Whitespace " " @68..69 48 | [31] Ident "outer" @69..74 49 | [32] CloseBrace "}" @74..75 50 | [33] Whitespace "\n" @75..76 51 | [34] Ident "cal" @76..79 52 | [35] Whitespace " " @79..80 53 | [36] OpenBrace "{" @80..81 54 | [37] Unknown "£" @81..83 55 | [38] Dollar "$" @83..84 56 | [39] And "&" @84..85 57 | [40] Unknown "£" @85..87 58 | [41] Star "*" @87..88 59 | [42] OpenParen "(" @88..89 60 | [43] Literal { kind: Str { terminated: false }, suffix_start: 5 } "")}\n\n" @89..94 61 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__gate__gate_modifiers.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/gate/gate_modifiers.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..85: 13 | qubit q; 14 | gate g q {} 15 | ctrl(2) @ g q; 16 | negctrl(3) @ g q; 17 | pow(-1./2.) @ g q; 18 | inv @ g q; 19 | 20 | QUANTUM_DECLARATION_STATEMENT@1..9: qubit q; 21 | QUBIT_TYPE@1..6: qubit 22 | NAME@7..8: q 23 | GATE@10..21: gate g q {} 24 | NAME@15..16: g 25 | PARAM_LIST@17..18: q 26 | PARAM@17..18: q 27 | BLOCK_EXPR@19..21: {} 28 | EXPR_STMT@22..36: ctrl(2) @ g q; 29 | MODIFIED_GATE_CALL_EXPR@22..35: ctrl(2) @ g q 30 | CTRL_MODIFIER@22..31: ctrl(2) @ 31 | PAREN_EXPR@26..29: (2) 32 | LITERAL@27..28: 2 33 | GATE_CALL_EXPR@32..35: g q 34 | IDENTIFIER@32..33: g 35 | QUBIT_LIST@34..35: q 36 | IDENTIFIER@34..35: q 37 | EXPR_STMT@37..54: negctrl(3) @ g q; 38 | MODIFIED_GATE_CALL_EXPR@37..53: negctrl(3) @ g q 39 | NEG_CTRL_MODIFIER@37..49: negctrl(3) @ 40 | PAREN_EXPR@44..47: (3) 41 | LITERAL@45..46: 3 42 | GATE_CALL_EXPR@50..53: g q 43 | IDENTIFIER@50..51: g 44 | QUBIT_LIST@52..53: q 45 | IDENTIFIER@52..53: q 46 | EXPR_STMT@55..73: pow(-1./2.) @ g q; 47 | MODIFIED_GATE_CALL_EXPR@55..72: pow(-1./2.) @ g q 48 | POW_MODIFIER@55..68: pow(-1./2.) @ 49 | PAREN_EXPR@58..66: (-1./2.) 50 | BIN_EXPR@59..65: -1./2. 51 | PREFIX_EXPR@59..62: -1. 52 | LITERAL@60..62: 1. 53 | LITERAL@63..65: 2. 54 | GATE_CALL_EXPR@69..72: g q 55 | IDENTIFIER@69..70: g 56 | QUBIT_LIST@71..72: q 57 | IDENTIFIER@71..72: q 58 | EXPR_STMT@74..84: inv @ g q; 59 | MODIFIED_GATE_CALL_EXPR@74..83: inv @ g q 60 | INV_MODIFIER@74..79: inv @ 61 | GATE_CALL_EXPR@80..83: g q 62 | IDENTIFIER@80..81: g 63 | QUBIT_LIST@82..83: q 64 | IDENTIFIER@82..83: q 65 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__binary_expr.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/expression/binary_expr.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | int x = 0; 10 | int y = 1; 11 | 12 | 2+2; 13 | 2**2; 14 | x << y; 15 | --- lexer --- 16 | ok: true 17 | errors: 0 18 | [0] Whitespace "\n" @0..1 19 | [1] Ident "int" @1..4 20 | [2] Whitespace " " @4..5 21 | [3] Ident "x" @5..6 22 | [4] Whitespace " " @6..7 23 | [5] Eq "=" @7..8 24 | [6] Whitespace " " @8..9 25 | [7] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @9..10 26 | [8] Semi ";" @10..11 27 | [9] Whitespace "\n" @11..12 28 | [10] Ident "int" @12..15 29 | [11] Whitespace " " @15..16 30 | [12] Ident "y" @16..17 31 | [13] Whitespace " " @17..18 32 | [14] Eq "=" @18..19 33 | [15] Whitespace " " @19..20 34 | [16] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @20..21 35 | [17] Semi ";" @21..22 36 | [18] Whitespace "\n\n" @22..24 37 | [19] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @24..25 38 | [20] Plus "+" @25..26 39 | [21] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @26..27 40 | [22] Semi ";" @27..28 41 | [23] Whitespace "\n" @28..29 42 | [24] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @29..30 43 | [25] Star "*" @30..31 44 | [26] Star "*" @31..32 45 | [27] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @32..33 46 | [28] Semi ";" @33..34 47 | [29] Whitespace "\n" @34..35 48 | [30] Ident "x" @35..36 49 | [31] Whitespace " " @36..37 50 | [32] Lt "<" @37..38 51 | [33] Lt "<" @38..39 52 | [34] Whitespace " " @39..40 53 | [35] Ident "y" @40..41 54 | [36] Semi ";" @41..42 55 | [37] Whitespace "\n" @42..43 56 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__subroutine__extern.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/subroutine/extern.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | extern test_kern(bit[5], uint[10], float[16], complex[float[64]]) -> float[6]; 10 | --- lexer --- 11 | ok: true 12 | errors: 0 13 | [0] Whitespace "\n" @0..1 14 | [1] Ident "extern" @1..7 15 | [2] Whitespace " " @7..8 16 | [3] Ident "test_kern" @8..17 17 | [4] OpenParen "(" @17..18 18 | [5] Ident "bit" @18..21 19 | [6] OpenBracket "[" @21..22 20 | [7] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "5" @22..23 21 | [8] CloseBracket "]" @23..24 22 | [9] Comma "," @24..25 23 | [10] Whitespace " " @25..26 24 | [11] Ident "uint" @26..30 25 | [12] OpenBracket "[" @30..31 26 | [13] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "10" @31..33 27 | [14] CloseBracket "]" @33..34 28 | [15] Comma "," @34..35 29 | [16] Whitespace " " @35..36 30 | [17] Ident "float" @36..41 31 | [18] OpenBracket "[" @41..42 32 | [19] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "16" @42..44 33 | [20] CloseBracket "]" @44..45 34 | [21] Comma "," @45..46 35 | [22] Whitespace " " @46..47 36 | [23] Ident "complex" @47..54 37 | [24] OpenBracket "[" @54..55 38 | [25] Ident "float" @55..60 39 | [26] OpenBracket "[" @60..61 40 | [27] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "64" @61..63 41 | [28] CloseBracket "]" @63..64 42 | [29] CloseBracket "]" @64..65 43 | [30] CloseParen ")" @65..66 44 | [31] Whitespace " " @66..67 45 | [32] Minus "-" @67..68 46 | [33] Gt ">" @68..69 47 | [34] Whitespace " " @69..70 48 | [35] Ident "float" @70..75 49 | [36] OpenBracket "[" @75..76 50 | [37] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "6" @76..77 51 | [38] CloseBracket "]" @77..78 52 | [39] Semi ";" @78..79 53 | [40] Whitespace "\n" @79..80 54 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__calibration.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid/statements/calibration.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | defcalgrammar "openpulse" defcalgrammar "openpulse"; 10 | defcalgrammar 3; 11 | defcal x $0 -> int[8] -> int[8] {} 12 | --- lexer --- 13 | ok: true 14 | errors: 0 15 | [0] Whitespace "\n" @0..1 16 | [1] Ident "defcalgrammar" @1..14 17 | [2] Whitespace " " @14..15 18 | [3] Literal { kind: Str { terminated: true }, suffix_start: 11 } ""openpulse"" @15..26 19 | [4] Whitespace " " @26..27 20 | [5] Ident "defcalgrammar" @27..40 21 | [6] Whitespace " " @40..41 22 | [7] Literal { kind: Str { terminated: true }, suffix_start: 11 } ""openpulse"" @41..52 23 | [8] Semi ";" @52..53 24 | [9] Whitespace "\n" @53..54 25 | [10] Ident "defcalgrammar" @54..67 26 | [11] Whitespace " " @67..68 27 | [12] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "3" @68..69 28 | [13] Semi ";" @69..70 29 | [14] Whitespace "\n" @70..71 30 | [15] Ident "defcal" @71..77 31 | [16] Whitespace " " @77..78 32 | [17] Ident "x" @78..79 33 | [18] Whitespace " " @79..80 34 | [19] HardwareIdent "$0" @80..82 35 | [20] Whitespace " " @82..83 36 | [21] Minus "-" @83..84 37 | [22] Gt ">" @84..85 38 | [23] Whitespace " " @85..86 39 | [24] Ident "int" @86..89 40 | [25] OpenBracket "[" @89..90 41 | [26] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @90..91 42 | [27] CloseBracket "]" @91..92 43 | [28] Whitespace " " @92..93 44 | [29] Minus "-" @93..94 45 | [30] Gt ">" @94..95 46 | [31] Whitespace " " @95..96 47 | [32] Ident "int" @96..99 48 | [33] OpenBracket "[" @99..100 49 | [34] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @100..101 50 | [35] CloseBracket "]" @101..102 51 | [36] Whitespace " " @102..103 52 | [37] OpenBrace "{" @103..104 53 | [38] CloseBrace "}" @104..105 54 | [39] Whitespace "\n" @105..106 55 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__headers.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid/statements/headers.qasm 6 | expect-lex: Diag 7 | --- source --- 8 | 9 | OPENQASM int; 10 | OPENQASM 'hello, world'; 11 | OPENQASM 3 3; 12 | OPENQASM 3.x; 13 | include 3; 14 | include include; 15 | include def; 16 | include "hello; 17 | --- lexer --- 18 | ok: false 19 | errors: 1 20 | [0] Whitespace "\n" @0..1 21 | [1] OpenQasmVersionStmt { major: false, minor: false } "OPENQASM " @1..10 22 | [2] Ident "int" @10..13 23 | [3] Semi ";" @13..14 24 | [4] Whitespace "\n" @14..15 25 | [5] OpenQasmVersionStmt { major: false, minor: false } "OPENQASM " @15..24 26 | [6] Literal { kind: Str { terminated: true }, suffix_start: 14 } "'hello, world'" @24..38 27 | [7] Semi ";" @38..39 28 | [8] Whitespace "\n" @39..40 29 | [9] OpenQasmVersionStmt { major: true, minor: true } "OPENQASM 3" @40..50 30 | [10] Whitespace " " @50..51 31 | [11] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "3" @51..52 32 | [12] Semi ";" @52..53 33 | [13] Whitespace "\n" @53..54 34 | [14] OpenQasmVersionStmt { major: true, minor: false } "OPENQASM 3." @54..65 35 | [15] Ident "x" @65..66 36 | [16] Semi ";" @66..67 37 | [17] Whitespace "\n" @67..68 38 | [18] Ident "include" @68..75 39 | [19] Whitespace " " @75..76 40 | [20] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "3" @76..77 41 | [21] Semi ";" @77..78 42 | [22] Whitespace "\n" @78..79 43 | [23] Ident "include" @79..86 44 | [24] Whitespace " " @86..87 45 | [25] Ident "include" @87..94 46 | [26] Semi ";" @94..95 47 | [27] Whitespace "\n" @95..96 48 | [28] Ident "include" @96..103 49 | [29] Whitespace " " @103..104 50 | [30] Ident "def" @104..107 51 | [31] Semi ";" @107..108 52 | [32] Whitespace "\n" @108..109 53 | [33] Ident "include" @109..116 54 | [34] Whitespace " " @116..117 55 | [35] Literal { kind: Str { terminated: false }, suffix_start: 8 } ""hello;\n" @117..125 56 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__declaration__complex.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/declaration/complex.qasm 6 | expect-sema: Todo 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(7)), initializer: None }) 13 | 14 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(8)), initializer: Some(TExpr { expression: BinaryExpr(BinaryExpr { op: ArithOp(Sub), left: TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(Int(IntLiteral { value: 4, sign: true })), ty: Int(Some(128), True) }, typ: Complex(Some(64), True) }), ty: Complex(Some(64), True) }, right: TExpr { expression: Literal(ImaginaryFloat(FloatLiteral { value: "5.5" })), ty: Complex(Some(64), True) } }), ty: Complex(Some(64), True) }) }) 15 | 16 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(9)), initializer: Some(TExpr { expression: BinaryExpr(BinaryExpr { op: ArithOp(Add), left: TExpr { expression: Identifier(Ok(SymbolId(7))), ty: Complex(None, False) }, right: TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(ImaginaryInt(IntLiteral { value: 3, sign: true })), ty: Int(Some(64), True) }, typ: Complex(None, False) }), ty: Complex(None, False) } }), ty: Complex(None, False) }) }) 17 | 18 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(10)), initializer: Some(TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(ImaginaryInt(IntLiteral { value: 1, sign: true })), ty: Int(Some(64), True) }, typ: Complex(None, False) }), ty: Complex(None, False) }) }) 19 | 20 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(11)), initializer: Some(TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(ImaginaryInt(IntLiteral { value: 1, sign: true })), ty: Int(Some(64), True) }, typ: Complex(None, False) }), ty: Complex(None, False) }) }) 21 | 22 | DeclareClassical(DeclareClassical { name: Ok(SymbolId(12)), initializer: None }) 23 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__io.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid/statements/io.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 18 11 | --- ast --- 12 | SOURCE_FILE@0..151: 13 | input int[8]; 14 | output int[8]; 15 | input qreg myvar[4]; 16 | output qreg myvar[4]; 17 | input int[8] myvar = 32; 18 | output int[8] myvar = 32; 19 | input myvar; 20 | output myvar; 21 | 22 | I_O_DECLARATION_STATEMENT@1..14: input int[8]; 23 | SCALAR_TYPE@7..13: int[8] 24 | DESIGNATOR@10..13: [8] 25 | LITERAL@11..12: 8 26 | NAME@13..13: 27 | I_O_DECLARATION_STATEMENT@15..29: output int[8]; 28 | SCALAR_TYPE@22..28: int[8] 29 | DESIGNATOR@25..28: [8] 30 | LITERAL@26..27: 8 31 | NAME@28..28: 32 | I_O_DECLARATION_STATEMENT@30..36: input 33 | SCALAR_TYPE@36..36: 34 | NAME@36..36: 35 | OLD_STYLE_DECLARATION_STATEMENT@36..50: qreg myvar[4]; 36 | OLD_TYPED_PARAM@36..49: qreg myvar[4] 37 | INDEX_OPERATOR@46..49: [4] 38 | EXPRESSION_LIST@47..48: 4 39 | LITERAL@47..48: 4 40 | I_O_DECLARATION_STATEMENT@51..58: output 41 | SCALAR_TYPE@58..58: 42 | NAME@58..58: 43 | OLD_STYLE_DECLARATION_STATEMENT@58..72: qreg myvar[4]; 44 | OLD_TYPED_PARAM@58..71: qreg myvar[4] 45 | INDEX_OPERATOR@68..71: [4] 46 | EXPRESSION_LIST@69..70: 4 47 | LITERAL@69..70: 4 48 | I_O_DECLARATION_STATEMENT@73..91: input int[8] myvar 49 | SCALAR_TYPE@79..85: int[8] 50 | DESIGNATOR@82..85: [8] 51 | LITERAL@83..84: 8 52 | NAME@86..91: myvar 53 | ERROR@92..93: = 54 | EXPR_STMT@94..97: 32; 55 | LITERAL@94..96: 32 56 | I_O_DECLARATION_STATEMENT@98..117: output int[8] myvar 57 | SCALAR_TYPE@105..111: int[8] 58 | DESIGNATOR@108..111: [8] 59 | LITERAL@109..110: 8 60 | NAME@112..117: myvar 61 | ERROR@118..119: = 62 | EXPR_STMT@120..123: 32; 63 | LITERAL@120..122: 32 64 | I_O_DECLARATION_STATEMENT@124..136: input myvar; 65 | SCALAR_TYPE@130..130: 66 | NAME@130..135: myvar 67 | I_O_DECLARATION_STATEMENT@137..150: output myvar; 68 | SCALAR_TYPE@144..144: 69 | NAME@144..149: myvar 70 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__declaration__complex.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/declaration/complex.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..235: 13 | // beware the tab character in f = 1 im below 14 | complex[float] a; 15 | complex[float] b = 4 - 5.5im; 16 | complex[float[64]] d = a + 3 im; 17 | // complex[float[32]] c = a ** b; 18 | complex[float] e = 1im; 19 | complex[float] f = 1 im; 20 | complex z; 21 | 22 | CLASSICAL_DECLARATION_STATEMENT@49..66: complex[float] a; 23 | SCALAR_TYPE@49..63: complex[float] 24 | SCALAR_TYPE@57..62: float 25 | NAME@64..65: a 26 | CLASSICAL_DECLARATION_STATEMENT@69..98: complex[float] b = 4 - 5.5im; 27 | SCALAR_TYPE@69..83: complex[float] 28 | SCALAR_TYPE@77..82: float 29 | NAME@84..85: b 30 | BIN_EXPR@88..97: 4 - 5.5im 31 | LITERAL@88..89: 4 32 | TIMING_LITERAL@92..97: 5.5im 33 | LITERAL@92..95: 5.5 34 | IDENTIFIER@95..97: im 35 | CLASSICAL_DECLARATION_STATEMENT@101..133: complex[float[64]] d = a + 3 im; 36 | SCALAR_TYPE@101..119: complex[float[64]] 37 | SCALAR_TYPE@109..118: float[64] 38 | DESIGNATOR@114..118: [64] 39 | LITERAL@115..117: 64 40 | NAME@120..121: d 41 | BIN_EXPR@124..132: a + 3 im 42 | IDENTIFIER@124..125: a 43 | TIMING_LITERAL@128..132: 3 im 44 | LITERAL@128..129: 3 45 | IDENTIFIER@130..132: im 46 | CLASSICAL_DECLARATION_STATEMENT@171..194: complex[float] e = 1im; 47 | SCALAR_TYPE@171..185: complex[float] 48 | SCALAR_TYPE@179..184: float 49 | NAME@186..187: e 50 | TIMING_LITERAL@190..193: 1im 51 | LITERAL@190..191: 1 52 | IDENTIFIER@191..193: im 53 | CLASSICAL_DECLARATION_STATEMENT@197..221: complex[float] f = 1 im; 54 | SCALAR_TYPE@197..211: complex[float] 55 | SCALAR_TYPE@205..210: float 56 | NAME@212..213: f 57 | TIMING_LITERAL@216..220: 1 im 58 | LITERAL@216..217: 1 59 | IDENTIFIER@218..220: im 60 | CLASSICAL_DECLARATION_STATEMENT@224..234: complex z; 61 | SCALAR_TYPE@224..231: complex 62 | NAME@232..233: z 63 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__order_of_ops.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/expression/order_of_ops.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | a[1]+2|c*(sin(y)^!3.5*d[3]); 10 | b = bit[8](a)[2:4]; 11 | --- lexer --- 12 | ok: true 13 | errors: 0 14 | [0] Whitespace "\n" @0..1 15 | [1] Ident "a" @1..2 16 | [2] OpenBracket "[" @2..3 17 | [3] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @3..4 18 | [4] CloseBracket "]" @4..5 19 | [5] Plus "+" @5..6 20 | [6] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @6..7 21 | [7] Or "|" @7..8 22 | [8] Ident "c" @8..9 23 | [9] Star "*" @9..10 24 | [10] OpenParen "(" @10..11 25 | [11] Ident "sin" @11..14 26 | [12] OpenParen "(" @14..15 27 | [13] Ident "y" @15..16 28 | [14] CloseParen ")" @16..17 29 | [15] Caret "^" @17..18 30 | [16] Bang "!" @18..19 31 | [17] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 3 } "3.5" @19..22 32 | [18] Star "*" @22..23 33 | [19] Ident "d" @23..24 34 | [20] OpenBracket "[" @24..25 35 | [21] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "3" @25..26 36 | [22] CloseBracket "]" @26..27 37 | [23] CloseParen ")" @27..28 38 | [24] Semi ";" @28..29 39 | [25] Whitespace "\n" @29..30 40 | [26] Ident "b" @30..31 41 | [27] Whitespace " " @31..32 42 | [28] Eq "=" @32..33 43 | [29] Whitespace " " @33..34 44 | [30] Ident "bit" @34..37 45 | [31] OpenBracket "[" @37..38 46 | [32] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @38..39 47 | [33] CloseBracket "]" @39..40 48 | [34] OpenParen "(" @40..41 49 | [35] Ident "a" @41..42 50 | [36] CloseParen ")" @42..43 51 | [37] OpenBracket "[" @43..44 52 | [38] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @44..45 53 | [39] Colon ":" @45..46 54 | [40] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "4" @46..47 55 | [41] CloseBracket "]" @47..48 56 | [42] Semi ";" @48..49 57 | [43] Whitespace "\n" @49..50 58 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__scope__nop.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/scope/nop.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | nop; 10 | nop $0; 11 | nop $1, $2; 12 | nop q, q[0],; 13 | box { 14 | nop $0; 15 | } 16 | gate x q { 17 | nop q; 18 | } 19 | --- lexer --- 20 | ok: true 21 | errors: 0 22 | [0] Whitespace "\n" @0..1 23 | [1] Ident "nop" @1..4 24 | [2] Semi ";" @4..5 25 | [3] Whitespace "\n" @5..6 26 | [4] Ident "nop" @6..9 27 | [5] Whitespace " " @9..10 28 | [6] HardwareIdent "$0" @10..12 29 | [7] Semi ";" @12..13 30 | [8] Whitespace "\n" @13..14 31 | [9] Ident "nop" @14..17 32 | [10] Whitespace " " @17..18 33 | [11] HardwareIdent "$1" @18..20 34 | [12] Comma "," @20..21 35 | [13] Whitespace " " @21..22 36 | [14] HardwareIdent "$2" @22..24 37 | [15] Semi ";" @24..25 38 | [16] Whitespace "\n" @25..26 39 | [17] Ident "nop" @26..29 40 | [18] Whitespace " " @29..30 41 | [19] Ident "q" @30..31 42 | [20] Comma "," @31..32 43 | [21] Whitespace " " @32..33 44 | [22] Ident "q" @33..34 45 | [23] OpenBracket "[" @34..35 46 | [24] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @35..36 47 | [25] CloseBracket "]" @36..37 48 | [26] Comma "," @37..38 49 | [27] Semi ";" @38..39 50 | [28] Whitespace "\n" @39..40 51 | [29] Ident "box" @40..43 52 | [30] Whitespace " " @43..44 53 | [31] OpenBrace "{" @44..45 54 | [32] Whitespace "\n " @45..48 55 | [33] Ident "nop" @48..51 56 | [34] Whitespace " " @51..52 57 | [35] HardwareIdent "$0" @52..54 58 | [36] Semi ";" @54..55 59 | [37] Whitespace "\n" @55..56 60 | [38] CloseBrace "}" @56..57 61 | [39] Whitespace "\n" @57..58 62 | [40] Ident "gate" @58..62 63 | [41] Whitespace " " @62..63 64 | [42] Ident "x" @63..64 65 | [43] Whitespace " " @64..65 66 | [44] Ident "q" @65..66 67 | [45] Whitespace " " @66..67 68 | [46] OpenBrace "{" @67..68 69 | [47] Whitespace "\n " @68..71 70 | [48] Ident "nop" @71..74 71 | [49] Whitespace " " @74..75 72 | [50] Ident "q" @75..76 73 | [51] Semi ";" @76..77 74 | [52] Whitespace "\n" @77..78 75 | [53] CloseBrace "}" @78..79 76 | [54] Whitespace "\n" @79..80 77 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__annotations2.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/directives/annotations2.qasm 6 | expect-sema: Ok 7 | --- sema --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- asg --- 12 | AnnotatedStmt(AnnotatedStmt { stmt: InputDeclaration(InputDeclaration { name: Ok(SymbolId(7)) }), annotations: [Annotation { annotation_text: "@bind [2:3]" }] }) 13 | 14 | AnnotatedStmt(AnnotatedStmt { stmt: OutputDeclaration(OutputDeclaration { name: Ok(SymbolId(8)) }), annotations: [Annotation { annotation_text: "@rename other" }] }) 15 | 16 | AnnotatedStmt(AnnotatedStmt { stmt: DeclareClassical(DeclareClassical { name: Ok(SymbolId(9)), initializer: None }), annotations: [Annotation { annotation_text: "@hello world" }] }) 17 | 18 | AnnotatedStmt(AnnotatedStmt { stmt: DefStmt(DefStmt { name: Ok(SymbolId(11)), params: [], block: Block { statements: [DeclareClassical(DeclareClassical { name: Ok(SymbolId(10)), initializer: None }), ExprStmt(TExpr { expression: Return(ReturnExpression { value: None }), ty: Void })] }, return_type: Void }), annotations: [Annotation { annotation_text: "@outer" }, Annotation { annotation_text: "@inner word1" }, Annotation { annotation_text: "@inner word2" }] }) 19 | 20 | AnnotatedStmt(AnnotatedStmt { stmt: DeclareClassical(DeclareClassical { name: Ok(SymbolId(12)), initializer: None }), annotations: [Annotation { annotation_text: "@first" }, Annotation { annotation_text: "@second @not_third" }] }) 21 | 22 | AnnotatedStmt(AnnotatedStmt { stmt: Assignment(Assignment { lvalue: Identifier(Ok(SymbolId(7))), rvalue: TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(Int(IntLiteral { value: 1, sign: true })), ty: Int(Some(128), True) }, typ: UInt(Some(16), False) }), ty: UInt(Some(16), False) } }), annotations: [Annotation { annotation_text: "@binds tightly" }] }) 23 | 24 | Assignment(Assignment { lvalue: Identifier(Ok(SymbolId(7))), rvalue: TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(Int(IntLiteral { value: 2, sign: true })), ty: Int(Some(128), True) }, typ: UInt(Some(16), False) }), ty: UInt(Some(16), False) } }) 25 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__gate__quantum_gate.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/gate/quantum_gate.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | include "stdlib.qasm"; 10 | 11 | gate test_gate(theta) a, b { 12 | reset a; 13 | barrier b; 14 | gphase(-theta/2); 15 | CX a, b; 16 | barrier; 17 | } 18 | --- lexer --- 19 | ok: true 20 | errors: 0 21 | [0] Whitespace "\n" @0..1 22 | [1] Ident "include" @1..8 23 | [2] Whitespace " " @8..9 24 | [3] Literal { kind: Str { terminated: true }, suffix_start: 13 } ""stdlib.qasm"" @9..22 25 | [4] Semi ";" @22..23 26 | [5] Whitespace "\n\n" @23..25 27 | [6] Ident "gate" @25..29 28 | [7] Whitespace " " @29..30 29 | [8] Ident "test_gate" @30..39 30 | [9] OpenParen "(" @39..40 31 | [10] Ident "theta" @40..45 32 | [11] CloseParen ")" @45..46 33 | [12] Whitespace " " @46..47 34 | [13] Ident "a" @47..48 35 | [14] Comma "," @48..49 36 | [15] Whitespace " " @49..50 37 | [16] Ident "b" @50..51 38 | [17] Whitespace " " @51..52 39 | [18] OpenBrace "{" @52..53 40 | [19] Whitespace "\n " @53..56 41 | [20] Ident "reset" @56..61 42 | [21] Whitespace " " @61..62 43 | [22] Ident "a" @62..63 44 | [23] Semi ";" @63..64 45 | [24] Whitespace "\n " @64..67 46 | [25] Ident "barrier" @67..74 47 | [26] Whitespace " " @74..75 48 | [27] Ident "b" @75..76 49 | [28] Semi ";" @76..77 50 | [29] Whitespace "\n " @77..80 51 | [30] Ident "gphase" @80..86 52 | [31] OpenParen "(" @86..87 53 | [32] Minus "-" @87..88 54 | [33] Ident "theta" @88..93 55 | [34] Slash "/" @93..94 56 | [35] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @94..95 57 | [36] CloseParen ")" @95..96 58 | [37] Semi ";" @96..97 59 | [38] Whitespace "\n " @97..100 60 | [39] Ident "CX" @100..102 61 | [40] Whitespace " " @102..103 62 | [41] Ident "a" @103..104 63 | [42] Comma "," @104..105 64 | [43] Whitespace " " @105..106 65 | [44] Ident "b" @106..107 66 | [45] Semi ";" @107..108 67 | [46] Whitespace "\n " @108..111 68 | [47] Ident "barrier" @111..118 69 | [48] Semi ";" @118..119 70 | [49] Whitespace "\n" @119..120 71 | [50] CloseBrace "}" @120..121 72 | [51] Whitespace "\n" @121..122 73 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__annotations.qasm-sema.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: sema_snap 4 | --- 5 | id: tests/snippets/reference/directives/annotations.qasm 6 | expect-sema: Diag 7 | --- sema --- 8 | ok: false 9 | panicked: false 10 | errors: 1 11 | --- asg --- 12 | AnnotatedStmt(AnnotatedStmt { stmt: InputDeclaration(InputDeclaration { name: Ok(SymbolId(7)) }), annotations: [Annotation { annotation_text: "@bind [2:3]" }] }) 13 | 14 | AnnotatedStmt(AnnotatedStmt { stmt: OutputDeclaration(OutputDeclaration { name: Ok(SymbolId(8)) }), annotations: [Annotation { annotation_text: "@rename other" }] }) 15 | 16 | AnnotatedStmt(AnnotatedStmt { stmt: DeclareClassical(DeclareClassical { name: Err(AlreadyBound), initializer: None }), annotations: [Annotation { annotation_text: "@hello world" }] }) 17 | 18 | AnnotatedStmt(AnnotatedStmt { stmt: DefStmt(DefStmt { name: Ok(SymbolId(10)), params: [], block: Block { statements: [DeclareClassical(DeclareClassical { name: Ok(SymbolId(9)), initializer: None }), ExprStmt(TExpr { expression: Return(ReturnExpression { value: None }), ty: Void })] }, return_type: Void }), annotations: [Annotation { annotation_text: "@outer" }, Annotation { annotation_text: "@inner word1" }, Annotation { annotation_text: "@inner word2" }] }) 19 | 20 | AnnotatedStmt(AnnotatedStmt { stmt: DeclareClassical(DeclareClassical { name: Err(AlreadyBound), initializer: None }), annotations: [Annotation { annotation_text: "@first" }, Annotation { annotation_text: "@second @not_third" }] }) 21 | 22 | AnnotatedStmt(AnnotatedStmt { stmt: Assignment(Assignment { lvalue: Identifier(Ok(SymbolId(7))), rvalue: TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(Int(IntLiteral { value: 1, sign: true })), ty: Int(Some(128), True) }, typ: UInt(Some(16), False) }), ty: UInt(Some(16), False) } }), annotations: [Annotation { annotation_text: "@binds tightly" }] }) 23 | 24 | Assignment(Assignment { lvalue: Identifier(Ok(SymbolId(7))), rvalue: TExpr { expression: Cast(Cast { operand: TExpr { expression: Literal(Int(IntLiteral { value: 2, sign: true })), ty: Int(Some(128), True) }, typ: UInt(Some(16), False) }), ty: UInt(Some(16), False) } }) 25 | -------------------------------------------------------------------------------- /crates/oq3_syntax/src/syntax_error.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! See docs for `SyntaxError`. 5 | 6 | use std::fmt; 7 | 8 | use crate::{TextRange, TextSize}; 9 | 10 | /// Represents the result of unsuccessful tokenization, parsing 11 | /// or tree validation. 12 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] 13 | pub struct SyntaxError(String, TextRange); 14 | 15 | // FIXME: The fixme comment below is retained from the original r-a code. 16 | // FIXME: there was an unused SyntaxErrorKind previously (before this enum was removed) 17 | // It was introduced in this PR: https://github.com/rust-lang/rust-analyzer/pull/846/files#diff-827da9b03b8f9faa1bade5cdd44d5dafR95 18 | // but it was not removed by a mistake. 19 | // 20 | // So, we need to find a place where to stick validation for attributes in match clauses. 21 | // Code before refactor: 22 | // InvalidMatchInnerAttr => { 23 | // write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression") 24 | // } 25 | 26 | impl SyntaxError { 27 | /// Create a new syntax error with message `message`. 28 | /// The text range into the source file given by `range`. 29 | pub fn new(message: impl Into, range: TextRange) -> Self { 30 | Self(message.into(), range) 31 | } 32 | 33 | // Note that this is meant to convert from `TextSize` to `TextRange`, whatever these mean. 34 | /// This method of creating a SynatxError is used in `shortcuts.rs`. (elsewhere ?) 35 | pub fn new_at_offset(message: impl Into, offset: TextSize) -> Self { 36 | Self(message.into(), TextRange::empty(offset)) 37 | } 38 | 39 | pub fn with_range(mut self, range: TextRange) -> Self { 40 | self.1 = range; 41 | self 42 | } 43 | 44 | /// Return the text range for this SyntaxError. 45 | pub fn range(&self) -> TextRange { 46 | self.1 47 | } 48 | 49 | /// Return the message for this SyntaxError. 50 | pub fn message(&self) -> &str { 51 | self.0.as_ref() 52 | } 53 | } 54 | 55 | impl fmt::Display for SyntaxError { 56 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 57 | self.0.fmt(f) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__pulse__defcal.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/pulse/defcal.qasm 6 | expect-lex: Todo 7 | --- source --- 8 | 9 | defcal x $0 {} 10 | defcal measure $0 -> bit {Outer {nested} outer} 11 | defcal rz(angle[20] theta) q {£$&£*(")} 12 | defcal rz(pi / 2) q {Symbolic expression.} 13 | --- lexer --- 14 | ok: false 15 | errors: 1 16 | [0] Whitespace "\n" @0..1 17 | [1] Ident "defcal" @1..7 18 | [2] Whitespace " " @7..8 19 | [3] Ident "x" @8..9 20 | [4] Whitespace " " @9..10 21 | [5] HardwareIdent "$0" @10..12 22 | [6] Whitespace " " @12..13 23 | [7] OpenBrace "{" @13..14 24 | [8] CloseBrace "}" @14..15 25 | [9] Whitespace "\n" @15..16 26 | [10] Ident "defcal" @16..22 27 | [11] Whitespace " " @22..23 28 | [12] Ident "measure" @23..30 29 | [13] Whitespace " " @30..31 30 | [14] HardwareIdent "$0" @31..33 31 | [15] Whitespace " " @33..34 32 | [16] Minus "-" @34..35 33 | [17] Gt ">" @35..36 34 | [18] Whitespace " " @36..37 35 | [19] Ident "bit" @37..40 36 | [20] Whitespace " " @40..41 37 | [21] OpenBrace "{" @41..42 38 | [22] Ident "Outer" @42..47 39 | [23] Whitespace " " @47..48 40 | [24] OpenBrace "{" @48..49 41 | [25] Ident "nested" @49..55 42 | [26] CloseBrace "}" @55..56 43 | [27] Whitespace " " @56..57 44 | [28] Ident "outer" @57..62 45 | [29] CloseBrace "}" @62..63 46 | [30] Whitespace "\n" @63..64 47 | [31] Ident "defcal" @64..70 48 | [32] Whitespace " " @70..71 49 | [33] Ident "rz" @71..73 50 | [34] OpenParen "(" @73..74 51 | [35] Ident "angle" @74..79 52 | [36] OpenBracket "[" @79..80 53 | [37] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "20" @80..82 54 | [38] CloseBracket "]" @82..83 55 | [39] Whitespace " " @83..84 56 | [40] Ident "theta" @84..89 57 | [41] CloseParen ")" @89..90 58 | [42] Whitespace " " @90..91 59 | [43] Ident "q" @91..92 60 | [44] Whitespace " " @92..93 61 | [45] OpenBrace "{" @93..94 62 | [46] Unknown "£" @94..96 63 | [47] Dollar "$" @96..97 64 | [48] And "&" @97..98 65 | [49] Unknown "£" @98..100 66 | [50] Star "*" @100..101 67 | [51] OpenParen "(" @101..102 68 | [52] Literal { kind: Str { terminated: false }, suffix_start: 47 } "")}\ndefcal rz(pi / 2) q {Symbolic expression.}\n" @102..149 69 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__declaration__complex2.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/declaration/complex2.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | complex[float[32]] a = 2.0; 10 | complex[float[32]] b = 1.0; 11 | 12 | complex[float[32]] c = a ** b; 13 | --- lexer --- 14 | ok: true 15 | errors: 0 16 | [0] Whitespace "\n" @0..1 17 | [1] Ident "complex" @1..8 18 | [2] OpenBracket "[" @8..9 19 | [3] Ident "float" @9..14 20 | [4] OpenBracket "[" @14..15 21 | [5] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "32" @15..17 22 | [6] CloseBracket "]" @17..18 23 | [7] CloseBracket "]" @18..19 24 | [8] Whitespace " " @19..20 25 | [9] Ident "a" @20..21 26 | [10] Whitespace " " @21..22 27 | [11] Eq "=" @22..23 28 | [12] Whitespace " " @23..24 29 | [13] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 3 } "2.0" @24..27 30 | [14] Semi ";" @27..28 31 | [15] Whitespace "\n" @28..29 32 | [16] Ident "complex" @29..36 33 | [17] OpenBracket "[" @36..37 34 | [18] Ident "float" @37..42 35 | [19] OpenBracket "[" @42..43 36 | [20] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "32" @43..45 37 | [21] CloseBracket "]" @45..46 38 | [22] CloseBracket "]" @46..47 39 | [23] Whitespace " " @47..48 40 | [24] Ident "b" @48..49 41 | [25] Whitespace " " @49..50 42 | [26] Eq "=" @50..51 43 | [27] Whitespace " " @51..52 44 | [28] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 3 } "1.0" @52..55 45 | [29] Semi ";" @55..56 46 | [30] Whitespace "\n\n" @56..58 47 | [31] Ident "complex" @58..65 48 | [32] OpenBracket "[" @65..66 49 | [33] Ident "float" @66..71 50 | [34] OpenBracket "[" @71..72 51 | [35] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "32" @72..74 52 | [36] CloseBracket "]" @74..75 53 | [37] CloseBracket "]" @75..76 54 | [38] Whitespace " " @76..77 55 | [39] Ident "c" @77..78 56 | [40] Whitespace " " @78..79 57 | [41] Eq "=" @79..80 58 | [42] Whitespace " " @80..81 59 | [43] Ident "a" @81..82 60 | [44] Whitespace " " @82..83 61 | [45] Star "*" @83..84 62 | [46] Star "*" @84..85 63 | [47] Whitespace " " @85..86 64 | [48] Ident "b" @86..87 65 | [49] Semi ";" @87..88 66 | [50] Whitespace "\n" @88..89 67 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__expression__sub_and_extern_call.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/expression/sub_and_extern_call.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | bit x = sub_call(10, "01", q1[0], q2); 10 | int[2] y = extern_call(0.5, 10dt); 11 | ambiguous_call(pi); 12 | --- lexer --- 13 | ok: true 14 | errors: 0 15 | [0] Whitespace "\n" @0..1 16 | [1] Ident "bit" @1..4 17 | [2] Whitespace " " @4..5 18 | [3] Ident "x" @5..6 19 | [4] Whitespace " " @6..7 20 | [5] Eq "=" @7..8 21 | [6] Whitespace " " @8..9 22 | [7] Ident "sub_call" @9..17 23 | [8] OpenParen "(" @17..18 24 | [9] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "10" @18..20 25 | [10] Comma "," @20..21 26 | [11] Whitespace " " @21..22 27 | [12] Literal { kind: BitStr { terminated: true, consecutive_underscores: false }, suffix_start: 4 } ""01"" @22..26 28 | [13] Comma "," @26..27 29 | [14] Whitespace " " @27..28 30 | [15] Ident "q1" @28..30 31 | [16] OpenBracket "[" @30..31 32 | [17] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @31..32 33 | [18] CloseBracket "]" @32..33 34 | [19] Comma "," @33..34 35 | [20] Whitespace " " @34..35 36 | [21] Ident "q2" @35..37 37 | [22] CloseParen ")" @37..38 38 | [23] Semi ";" @38..39 39 | [24] Whitespace "\n" @39..40 40 | [25] Ident "int" @40..43 41 | [26] OpenBracket "[" @43..44 42 | [27] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @44..45 43 | [28] CloseBracket "]" @45..46 44 | [29] Whitespace " " @46..47 45 | [30] Ident "y" @47..48 46 | [31] Whitespace " " @48..49 47 | [32] Eq "=" @49..50 48 | [33] Whitespace " " @50..51 49 | [34] Ident "extern_call" @51..62 50 | [35] OpenParen "(" @62..63 51 | [36] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 3 } "0.5" @63..66 52 | [37] Comma "," @66..67 53 | [38] Whitespace " " @67..68 54 | [39] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "10" @68..70 55 | [40] Ident "dt" @70..72 56 | [41] CloseParen ")" @72..73 57 | [42] Semi ";" @73..74 58 | [43] Whitespace "\n" @74..75 59 | [44] Ident "ambiguous_call" @75..89 60 | [45] OpenParen "(" @89..90 61 | [46] Ident "pi" @90..92 62 | [47] CloseParen ")" @92..93 63 | [48] Semi ";" @93..94 64 | [49] Whitespace "\n" @94..95 65 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__annotations.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/directives/annotations.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..236: 13 | @bind [2:3] 14 | input uint[16] x; 15 | 16 | @rename other 17 | output float[64] var; 18 | 19 | @hello world 20 | int[8] x; 21 | 22 | @outer 23 | def fn() { 24 | @inner word1 25 | uint[16] x; 26 | @inner word2 27 | return; 28 | } 29 | 30 | @first 31 | @second @not_third 32 | uint[16] x; 33 | 34 | @binds tightly 35 | x = 1; x = 2; 36 | 37 | ANNOTATION_STATEMENT@1..12: @bind [2:3] 38 | I_O_DECLARATION_STATEMENT@13..30: input uint[16] x; 39 | SCALAR_TYPE@19..27: uint[16] 40 | DESIGNATOR@23..27: [16] 41 | LITERAL@24..26: 16 42 | NAME@28..29: x 43 | ANNOTATION_STATEMENT@32..45: @rename other 44 | I_O_DECLARATION_STATEMENT@46..67: output float[64] var; 45 | SCALAR_TYPE@53..62: float[64] 46 | DESIGNATOR@58..62: [64] 47 | LITERAL@59..61: 64 48 | NAME@63..66: var 49 | ANNOTATION_STATEMENT@69..81: @hello world 50 | CLASSICAL_DECLARATION_STATEMENT@82..91: int[8] x; 51 | SCALAR_TYPE@82..88: int[8] 52 | DESIGNATOR@85..88: [8] 53 | LITERAL@86..87: 8 54 | NAME@89..90: x 55 | ANNOTATION_STATEMENT@93..99: @outer 56 | DEF@100..166: def fn() { 57 | @inner word1 58 | uint[16] x; 59 | @inner word2 60 | return; 61 | } 62 | NAME@104..106: fn 63 | TYPED_PARAM_LIST@106..108: () 64 | BLOCK_EXPR@109..166: { 65 | @inner word1 66 | uint[16] x; 67 | @inner word2 68 | return; 69 | } 70 | ANNOTATION_STATEMENT@113..125: @inner word1 71 | CLASSICAL_DECLARATION_STATEMENT@128..139: uint[16] x; 72 | SCALAR_TYPE@128..136: uint[16] 73 | DESIGNATOR@132..136: [16] 74 | LITERAL@133..135: 16 75 | NAME@137..138: x 76 | ANNOTATION_STATEMENT@142..154: @inner word2 77 | EXPR_STMT@157..164: return; 78 | RETURN_EXPR@157..163: return 79 | ANNOTATION_STATEMENT@168..174: @first 80 | ANNOTATION_STATEMENT@175..193: @second @not_third 81 | CLASSICAL_DECLARATION_STATEMENT@194..205: uint[16] x; 82 | SCALAR_TYPE@194..202: uint[16] 83 | DESIGNATOR@198..202: [16] 84 | LITERAL@199..201: 16 85 | NAME@203..204: x 86 | ANNOTATION_STATEMENT@207..221: @binds tightly 87 | ASSIGNMENT_STMT@222..228: x = 1; 88 | IDENTIFIER@222..223: x 89 | LITERAL@226..227: 1 90 | ASSIGNMENT_STMT@229..235: x = 2; 91 | IDENTIFIER@229..230: x 92 | LITERAL@233..234: 2 93 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__directives__annotations2.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/directives/annotations2.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..236: 13 | @bind [2:3] 14 | input uint[16] x; 15 | 16 | @rename other 17 | output float[64] var; 18 | 19 | @hello world 20 | int[8] y; 21 | 22 | @outer 23 | def fn() { 24 | @inner word1 25 | uint[16] x; 26 | @inner word2 27 | return; 28 | } 29 | 30 | @first 31 | @second @not_third 32 | uint[16] z; 33 | 34 | @binds tightly 35 | x = 1; x = 2; 36 | 37 | ANNOTATION_STATEMENT@1..12: @bind [2:3] 38 | I_O_DECLARATION_STATEMENT@13..30: input uint[16] x; 39 | SCALAR_TYPE@19..27: uint[16] 40 | DESIGNATOR@23..27: [16] 41 | LITERAL@24..26: 16 42 | NAME@28..29: x 43 | ANNOTATION_STATEMENT@32..45: @rename other 44 | I_O_DECLARATION_STATEMENT@46..67: output float[64] var; 45 | SCALAR_TYPE@53..62: float[64] 46 | DESIGNATOR@58..62: [64] 47 | LITERAL@59..61: 64 48 | NAME@63..66: var 49 | ANNOTATION_STATEMENT@69..81: @hello world 50 | CLASSICAL_DECLARATION_STATEMENT@82..91: int[8] y; 51 | SCALAR_TYPE@82..88: int[8] 52 | DESIGNATOR@85..88: [8] 53 | LITERAL@86..87: 8 54 | NAME@89..90: y 55 | ANNOTATION_STATEMENT@93..99: @outer 56 | DEF@100..166: def fn() { 57 | @inner word1 58 | uint[16] x; 59 | @inner word2 60 | return; 61 | } 62 | NAME@104..106: fn 63 | TYPED_PARAM_LIST@106..108: () 64 | BLOCK_EXPR@109..166: { 65 | @inner word1 66 | uint[16] x; 67 | @inner word2 68 | return; 69 | } 70 | ANNOTATION_STATEMENT@113..125: @inner word1 71 | CLASSICAL_DECLARATION_STATEMENT@128..139: uint[16] x; 72 | SCALAR_TYPE@128..136: uint[16] 73 | DESIGNATOR@132..136: [16] 74 | LITERAL@133..135: 16 75 | NAME@137..138: x 76 | ANNOTATION_STATEMENT@142..154: @inner word2 77 | EXPR_STMT@157..164: return; 78 | RETURN_EXPR@157..163: return 79 | ANNOTATION_STATEMENT@168..174: @first 80 | ANNOTATION_STATEMENT@175..193: @second @not_third 81 | CLASSICAL_DECLARATION_STATEMENT@194..205: uint[16] z; 82 | SCALAR_TYPE@194..202: uint[16] 83 | DESIGNATOR@198..202: [16] 84 | LITERAL@199..201: 16 85 | NAME@203..204: z 86 | ANNOTATION_STATEMENT@207..221: @binds tightly 87 | ASSIGNMENT_STMT@222..228: x = 1; 88 | IDENTIFIER@222..223: x 89 | LITERAL@226..227: 1 90 | ASSIGNMENT_STMT@229..235: x = 2; 91 | IDENTIFIER@229..230: x 92 | LITERAL@233..234: 2 93 | -------------------------------------------------------------------------------- /crates/oq3_parser/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Parser for OpenQASM 3 5 | 6 | mod lexed_str; 7 | mod token_set; 8 | 9 | // Temp make pub for debugging 10 | mod event; 11 | mod grammar; 12 | mod input; 13 | mod output; 14 | mod parser; 15 | mod shortcuts; 16 | pub mod syntax_kind; 17 | 18 | // FIXME 19 | // #[cfg(test)] 20 | // mod tests; 21 | 22 | pub(crate) use token_set::TokenSet; 23 | 24 | pub use crate::{ 25 | input::Input, 26 | lexed_str::LexedStr, 27 | output::{Output, Step}, 28 | shortcuts::StrStep, 29 | syntax_kind::SyntaxKind, 30 | }; 31 | 32 | /// GJL FIXME comments 33 | /// Parse the whole of the input as a given syntactic construct. 34 | /// [`TopEntryPoint::parse`] makes a guarantee that 35 | /// * all input is consumed 36 | /// * the result is a valid tree (there's one root node) 37 | #[derive(Debug)] 38 | pub enum TopEntryPoint { 39 | SourceFile, 40 | // Type, 41 | Expr, 42 | } 43 | 44 | impl TopEntryPoint { 45 | pub fn parse(&self, input: &Input) -> Output { 46 | let entry_point: fn(&'_ mut parser::Parser<'_>) = match self { 47 | TopEntryPoint::SourceFile => grammar::entry::top::source_file, 48 | // TopEntryPoint::Type => grammar::entry::top::type_, 49 | // This entry point is unused. 50 | TopEntryPoint::Expr => grammar::entry::top::expr, 51 | }; 52 | let mut p = parser::Parser::new(input); 53 | entry_point(&mut p); 54 | // move `events` out of the parser `p`. 55 | let events = p.finish(); 56 | let res = event::process(events); 57 | 58 | if cfg!(debug_assertions) { 59 | let mut depth = 0; 60 | let mut first = true; 61 | for step in res.iter() { 62 | assert!(depth > 0 || first); 63 | first = false; 64 | match step { 65 | Step::Enter { .. } => depth += 1, 66 | Step::Exit => depth -= 1, 67 | Step::FloatSplit { 68 | ends_in_dot: has_pseudo_dot, 69 | } => depth -= 1 + !has_pseudo_dot as usize, 70 | Step::Token { .. } | Step::Error { .. } => (), 71 | } 72 | } 73 | assert!(!first, "no tree at all"); 74 | assert_eq!(depth, 0, "unbalanced tree"); 75 | } 76 | 77 | res 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__gate__gate_modifiers.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/gate/gate_modifiers.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | qubit q; 10 | gate g q {} 11 | ctrl(2) @ g q; 12 | negctrl(3) @ g q; 13 | pow(-1./2.) @ g q; 14 | inv @ g q; 15 | --- lexer --- 16 | ok: true 17 | errors: 0 18 | [0] Whitespace "\n" @0..1 19 | [1] Ident "qubit" @1..6 20 | [2] Whitespace " " @6..7 21 | [3] Ident "q" @7..8 22 | [4] Semi ";" @8..9 23 | [5] Whitespace "\n" @9..10 24 | [6] Ident "gate" @10..14 25 | [7] Whitespace " " @14..15 26 | [8] Ident "g" @15..16 27 | [9] Whitespace " " @16..17 28 | [10] Ident "q" @17..18 29 | [11] Whitespace " " @18..19 30 | [12] OpenBrace "{" @19..20 31 | [13] CloseBrace "}" @20..21 32 | [14] Whitespace "\n" @21..22 33 | [15] Ident "ctrl" @22..26 34 | [16] OpenParen "(" @26..27 35 | [17] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @27..28 36 | [18] CloseParen ")" @28..29 37 | [19] Whitespace " " @29..30 38 | [20] At "@" @30..31 39 | [21] Whitespace " " @31..32 40 | [22] Ident "g" @32..33 41 | [23] Whitespace " " @33..34 42 | [24] Ident "q" @34..35 43 | [25] Semi ";" @35..36 44 | [26] Whitespace "\n" @36..37 45 | [27] Ident "negctrl" @37..44 46 | [28] OpenParen "(" @44..45 47 | [29] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "3" @45..46 48 | [30] CloseParen ")" @46..47 49 | [31] Whitespace " " @47..48 50 | [32] At "@" @48..49 51 | [33] Whitespace " " @49..50 52 | [34] Ident "g" @50..51 53 | [35] Whitespace " " @51..52 54 | [36] Ident "q" @52..53 55 | [37] Semi ";" @53..54 56 | [38] Whitespace "\n" @54..55 57 | [39] Ident "pow" @55..58 58 | [40] OpenParen "(" @58..59 59 | [41] Minus "-" @59..60 60 | [42] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 2 } "1." @60..62 61 | [43] Slash "/" @62..63 62 | [44] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 2 } "2." @63..65 63 | [45] CloseParen ")" @65..66 64 | [46] Whitespace " " @66..67 65 | [47] At "@" @67..68 66 | [48] Whitespace " " @68..69 67 | [49] Ident "g" @69..70 68 | [50] Whitespace " " @70..71 69 | [51] Ident "q" @71..72 70 | [52] Semi ";" @72..73 71 | [53] Whitespace "\n" @73..74 72 | [54] Ident "inv" @74..77 73 | [55] Whitespace " " @77..78 74 | [56] At "@" @78..79 75 | [57] Whitespace " " @79..80 76 | [58] Ident "g" @80..81 77 | [59] Whitespace " " @81..82 78 | [60] Ident "q" @82..83 79 | [61] Semi ";" @83..84 80 | [62] Whitespace "\n" @84..85 81 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__control_flow__loop.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/control_flow/loop.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | while (i < 10) { 10 | for uint j in {1, 4, 6} reset q[j]; 11 | if (i == 8) break; 12 | else continue; 13 | } 14 | --- lexer --- 15 | ok: true 16 | errors: 0 17 | [0] Whitespace "\n" @0..1 18 | [1] Ident "while" @1..6 19 | [2] Whitespace " " @6..7 20 | [3] OpenParen "(" @7..8 21 | [4] Ident "i" @8..9 22 | [5] Whitespace " " @9..10 23 | [6] Lt "<" @10..11 24 | [7] Whitespace " " @11..12 25 | [8] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "10" @12..14 26 | [9] CloseParen ")" @14..15 27 | [10] Whitespace " " @15..16 28 | [11] OpenBrace "{" @16..17 29 | [12] Whitespace "\n " @17..20 30 | [13] Ident "for" @20..23 31 | [14] Whitespace " " @23..24 32 | [15] Ident "uint" @24..28 33 | [16] Whitespace " " @28..29 34 | [17] Ident "j" @29..30 35 | [18] Whitespace " " @30..31 36 | [19] Ident "in" @31..33 37 | [20] Whitespace " " @33..34 38 | [21] OpenBrace "{" @34..35 39 | [22] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @35..36 40 | [23] Comma "," @36..37 41 | [24] Whitespace " " @37..38 42 | [25] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "4" @38..39 43 | [26] Comma "," @39..40 44 | [27] Whitespace " " @40..41 45 | [28] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "6" @41..42 46 | [29] CloseBrace "}" @42..43 47 | [30] Whitespace " " @43..44 48 | [31] Ident "reset" @44..49 49 | [32] Whitespace " " @49..50 50 | [33] Ident "q" @50..51 51 | [34] OpenBracket "[" @51..52 52 | [35] Ident "j" @52..53 53 | [36] CloseBracket "]" @53..54 54 | [37] Semi ";" @54..55 55 | [38] Whitespace "\n " @55..58 56 | [39] Ident "if" @58..60 57 | [40] Whitespace " " @60..61 58 | [41] OpenParen "(" @61..62 59 | [42] Ident "i" @62..63 60 | [43] Whitespace " " @63..64 61 | [44] Eq "=" @64..65 62 | [45] Eq "=" @65..66 63 | [46] Whitespace " " @66..67 64 | [47] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @67..68 65 | [48] CloseParen ")" @68..69 66 | [49] Whitespace " " @69..70 67 | [50] Ident "break" @70..75 68 | [51] Semi ";" @75..76 69 | [52] Whitespace "\n " @76..79 70 | [53] Ident "else" @79..83 71 | [54] Whitespace " " @83..84 72 | [55] Ident "continue" @84..92 73 | [56] Semi ";" @92..93 74 | [57] Whitespace "\n" @93..94 75 | [58] CloseBrace "}" @94..95 76 | [59] Whitespace "\n" @95..96 77 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__branch.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid/statements/branch.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 16 11 | --- ast --- 12 | SOURCE_FILE@0..177: 13 | if true x $0; 14 | if false { x $0; } 15 | if (myvar += 1) { x $0; } 16 | if (int[8] myvar = 1) { x $0; } 17 | if (true); 18 | if (true) else x $0; 19 | if (true) else (false) x $0; 20 | if (reset $0) { x $1; } 21 | 22 | IF_STMT@1..14: if true x $0; 23 | TIMING_LITERAL@4..10: true x 24 | LITERAL@4..8: true 25 | IDENTIFIER@9..10: x 26 | EXPR_STMT@11..14: $0; 27 | HARDWARE_QUBIT@11..13: $0 28 | IF_STMT@15..33: if false { x $0; } 29 | LITERAL@18..23: false 30 | BLOCK_EXPR@24..33: { x $0; } 31 | EXPR_STMT@26..31: x $0; 32 | GATE_CALL_EXPR@26..30: x $0 33 | IDENTIFIER@26..27: x 34 | QUBIT_LIST@28..30: $0 35 | HARDWARE_QUBIT@28..30: $0 36 | IF_STMT@34..59: if (myvar += 1) { x $0; } 37 | BIN_EXPR@38..48: myvar += 1 38 | IDENTIFIER@38..43: myvar 39 | LITERAL@47..48: 1 40 | BLOCK_EXPR@50..59: { x $0; } 41 | EXPR_STMT@52..57: x $0; 42 | GATE_CALL_EXPR@52..56: x $0 43 | IDENTIFIER@52..53: x 44 | QUBIT_LIST@54..56: $0 45 | HARDWARE_QUBIT@54..56: $0 46 | IF_STMT@60..91: if (int[8] myvar = 1) { x $0; } 47 | CAST_EXPRESSION@64..81: int[8] myvar = 1) 48 | SCALAR_TYPE@64..70: int[8] 49 | DESIGNATOR@67..70: [8] 50 | LITERAL@68..69: 8 51 | ASSIGNMENT_STMT@71..80: myvar = 1 52 | IDENTIFIER@71..76: myvar 53 | LITERAL@79..80: 1 54 | BLOCK_EXPR@82..91: { x $0; } 55 | EXPR_STMT@84..89: x $0; 56 | GATE_CALL_EXPR@84..88: x $0 57 | IDENTIFIER@84..85: x 58 | QUBIT_LIST@86..88: $0 59 | HARDWARE_QUBIT@86..88: $0 60 | IF_STMT@92..102: if (true); 61 | LITERAL@96..100: true 62 | IF_STMT@103..117: if (true) else 63 | LITERAL@107..111: true 64 | ERROR@113..117: else 65 | EXPR_STMT@118..123: x $0; 66 | GATE_CALL_EXPR@118..122: x $0 67 | IDENTIFIER@118..119: x 68 | QUBIT_LIST@120..122: $0 69 | HARDWARE_QUBIT@120..122: $0 70 | IF_STMT@124..138: if (true) else 71 | LITERAL@128..132: true 72 | ERROR@134..138: else 73 | EXPR_STMT@139..146: (false) 74 | PAREN_EXPR@139..146: (false) 75 | LITERAL@140..145: false 76 | EXPR_STMT@147..152: x $0; 77 | GATE_CALL_EXPR@147..151: x $0 78 | IDENTIFIER@147..148: x 79 | QUBIT_LIST@149..151: $0 80 | HARDWARE_QUBIT@149..151: $0 81 | IF_STMT@153..165: if (reset $0 82 | ERROR@157..162: reset 83 | EXPR_STMT@163..165: $0 84 | HARDWARE_QUBIT@163..165: $0 85 | ERROR@165..166: ) 86 | EXPR_STMT@167..176: { x $1; } 87 | BLOCK_EXPR@167..176: { x $1; } 88 | EXPR_STMT@169..174: x $1; 89 | GATE_CALL_EXPR@169..173: x $1 90 | IDENTIFIER@169..170: x 91 | QUBIT_LIST@171..173: $1 92 | HARDWARE_QUBIT@171..173: $1 93 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__assignment__alias.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/assignment/alias.qasm 6 | expect-parse: Ok 7 | --- parser --- 8 | ok: true 9 | panicked: false 10 | errors: 0 11 | --- ast --- 12 | SOURCE_FILE@0..167: 13 | bit[2] a; 14 | creg b[2]; 15 | qubit[5] q1; 16 | qreg q2[7]; 17 | let q = q1 ++ q2; 18 | let c = a[{0,1}] ++ b[1:2]; 19 | let qq = q1[{1,3,4}]; 20 | let qqq = qq ++ q2[1:2:6]; 21 | let d = c; 22 | let e = d[1]; 23 | 24 | CLASSICAL_DECLARATION_STATEMENT@1..10: bit[2] a; 25 | SCALAR_TYPE@1..7: bit[2] 26 | DESIGNATOR@4..7: [2] 27 | LITERAL@5..6: 2 28 | NAME@8..9: a 29 | OLD_STYLE_DECLARATION_STATEMENT@11..21: creg b[2]; 30 | OLD_TYPED_PARAM@11..20: creg b[2] 31 | INDEX_OPERATOR@17..20: [2] 32 | EXPRESSION_LIST@18..19: 2 33 | LITERAL@18..19: 2 34 | QUANTUM_DECLARATION_STATEMENT@22..34: qubit[5] q1; 35 | QUBIT_TYPE@22..30: qubit[5] 36 | DESIGNATOR@27..30: [5] 37 | LITERAL@28..29: 5 38 | NAME@31..33: q1 39 | OLD_STYLE_DECLARATION_STATEMENT@35..46: qreg q2[7]; 40 | OLD_TYPED_PARAM@35..45: qreg q2[7] 41 | INDEX_OPERATOR@42..45: [7] 42 | EXPRESSION_LIST@43..44: 7 43 | LITERAL@43..44: 7 44 | LET_STMT@47..64: let q = q1 ++ q2; 45 | BIN_EXPR@55..63: q1 ++ q2 46 | IDENTIFIER@55..57: q1 47 | IDENTIFIER@61..63: q2 48 | LET_STMT@65..92: let c = a[{0,1}] ++ b[1:2]; 49 | BIN_EXPR@73..91: a[{0,1}] ++ b[1:2] 50 | INDEXED_IDENTIFIER@73..81: a[{0,1}] 51 | IDENTIFIER@73..74: a 52 | INDEX_OPERATOR@74..81: [{0,1}] 53 | SET_EXPRESSION@75..80: {0,1} 54 | EXPRESSION_LIST@76..79: 0,1 55 | LITERAL@76..77: 0 56 | LITERAL@78..79: 1 57 | INDEXED_IDENTIFIER@85..91: b[1:2] 58 | IDENTIFIER@85..86: b 59 | INDEX_OPERATOR@86..91: [1:2] 60 | EXPRESSION_LIST@87..90: 1:2 61 | RANGE_EXPR@87..90: 1:2 62 | LITERAL@87..88: 1 63 | LITERAL@89..90: 2 64 | LET_STMT@93..114: let qq = q1[{1,3,4}]; 65 | INDEXED_IDENTIFIER@102..113: q1[{1,3,4}] 66 | IDENTIFIER@102..104: q1 67 | INDEX_OPERATOR@104..113: [{1,3,4}] 68 | SET_EXPRESSION@105..112: {1,3,4} 69 | EXPRESSION_LIST@106..111: 1,3,4 70 | LITERAL@106..107: 1 71 | LITERAL@108..109: 3 72 | LITERAL@110..111: 4 73 | LET_STMT@115..141: let qqq = qq ++ q2[1:2:6]; 74 | BIN_EXPR@125..140: qq ++ q2[1:2:6] 75 | IDENTIFIER@125..127: qq 76 | INDEXED_IDENTIFIER@131..140: q2[1:2:6] 77 | IDENTIFIER@131..133: q2 78 | INDEX_OPERATOR@133..140: [1:2:6] 79 | EXPRESSION_LIST@134..139: 1:2:6 80 | RANGE_EXPR@134..139: 1:2:6 81 | LITERAL@134..135: 1 82 | LITERAL@136..137: 2 83 | LITERAL@138..139: 6 84 | LET_STMT@142..152: let d = c; 85 | IDENTIFIER@150..151: c 86 | LET_STMT@153..166: let e = d[1]; 87 | INDEXED_IDENTIFIER@161..165: d[1] 88 | IDENTIFIER@161..162: d 89 | INDEX_OPERATOR@162..165: [1] 90 | EXPRESSION_LIST@163..164: 1 91 | LITERAL@163..164: 1 92 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__tokens.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid/statements/tokens.qasm 6 | expect-lex: Diag 7 | --- source --- 8 | 9 | #; 10 | 3x; 11 | x@x; 12 | 3.4.3; 13 | 3.4e3e3; 14 | // Bad integer literals. 15 | 3__4; 16 | 3_4_; 17 | 0b123; 18 | 0B123; 19 | 0o789; 20 | 0O789; 21 | 0x12g; 22 | 0X12g; 23 | 12af; 24 | --- lexer --- 25 | ok: false 26 | errors: 1 27 | [0] Whitespace "\n" @0..1 28 | [1] InvalidIdent "#" @1..2 29 | [2] Semi ";" @2..3 30 | [3] Whitespace "\n" @3..4 31 | [4] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "3x" @4..6 32 | [5] Semi ";" @6..7 33 | [6] Whitespace "\n" @7..8 34 | [7] Ident "x" @8..9 35 | [8] Annotation "@x;" @9..12 36 | [9] Whitespace "\n" @12..13 37 | [10] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 3 } "3.4" @13..16 38 | [11] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 2 } ".3" @16..18 39 | [12] Semi ";" @18..19 40 | [13] Whitespace "\n" @19..20 41 | [14] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 5 } "3.4e3e3" @20..27 42 | [15] Semi ";" @27..28 43 | [16] Whitespace "\n" @28..29 44 | [17] LineComment "// Bad integer literals." @29..53 45 | [18] Whitespace "\n" @53..54 46 | [19] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 4 } "3__4" @54..58 47 | [20] Semi ";" @58..59 48 | [21] Whitespace "\n" @59..60 49 | [22] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 4 } "3_4_" @60..64 50 | [23] Semi ";" @64..65 51 | [24] Whitespace "\n" @65..66 52 | [25] Literal { kind: Int { base: Binary, empty_int: false }, suffix_start: 5 } "0b123" @66..71 53 | [26] Semi ";" @71..72 54 | [27] Whitespace "\n" @72..73 55 | [28] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0B123" @73..78 56 | [29] Semi ";" @78..79 57 | [30] Whitespace "\n" @79..80 58 | [31] Literal { kind: Int { base: Octal, empty_int: false }, suffix_start: 5 } "0o789" @80..85 59 | [32] Semi ";" @85..86 60 | [33] Whitespace "\n" @86..87 61 | [34] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0O789" @87..92 62 | [35] Semi ";" @92..93 63 | [36] Whitespace "\n" @93..94 64 | [37] Literal { kind: Int { base: Hexadecimal, empty_int: false }, suffix_start: 4 } "0x12g" @94..99 65 | [38] Semi ";" @99..100 66 | [39] Whitespace "\n" @100..101 67 | [40] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0X12g" @101..106 68 | [41] Semi ";" @106..107 69 | [42] Whitespace "\n" @107..108 70 | [43] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "12af" @108..112 71 | [44] Semi ";" @112..113 72 | [45] Whitespace "\n" @113..114 73 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__control_flow__branching.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/control_flow/branching.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | include "stdgates.inc"; 10 | if (x == a) { 11 | for uint i in [0:2:4] x[i] += 1; 12 | } 13 | else CX x[0], x[1]; 14 | --- lexer --- 15 | ok: true 16 | errors: 0 17 | [0] Whitespace "\n" @0..1 18 | [1] Ident "include" @1..8 19 | [2] Whitespace " " @8..9 20 | [3] Literal { kind: Str { terminated: true }, suffix_start: 14 } ""stdgates.inc"" @9..23 21 | [4] Semi ";" @23..24 22 | [5] Whitespace "\n" @24..25 23 | [6] Ident "if" @25..27 24 | [7] Whitespace " " @27..28 25 | [8] OpenParen "(" @28..29 26 | [9] Ident "x" @29..30 27 | [10] Whitespace " " @30..31 28 | [11] Eq "=" @31..32 29 | [12] Eq "=" @32..33 30 | [13] Whitespace " " @33..34 31 | [14] Ident "a" @34..35 32 | [15] CloseParen ")" @35..36 33 | [16] Whitespace " " @36..37 34 | [17] OpenBrace "{" @37..38 35 | [18] Whitespace "\n " @38..41 36 | [19] Ident "for" @41..44 37 | [20] Whitespace " " @44..45 38 | [21] Ident "uint" @45..49 39 | [22] Whitespace " " @49..50 40 | [23] Ident "i" @50..51 41 | [24] Whitespace " " @51..52 42 | [25] Ident "in" @52..54 43 | [26] Whitespace " " @54..55 44 | [27] OpenBracket "[" @55..56 45 | [28] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @56..57 46 | [29] Colon ":" @57..58 47 | [30] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @58..59 48 | [31] Colon ":" @59..60 49 | [32] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "4" @60..61 50 | [33] CloseBracket "]" @61..62 51 | [34] Whitespace " " @62..63 52 | [35] Ident "x" @63..64 53 | [36] OpenBracket "[" @64..65 54 | [37] Ident "i" @65..66 55 | [38] CloseBracket "]" @66..67 56 | [39] Whitespace " " @67..68 57 | [40] Plus "+" @68..69 58 | [41] Eq "=" @69..70 59 | [42] Whitespace " " @70..71 60 | [43] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @71..72 61 | [44] Semi ";" @72..73 62 | [45] Whitespace "\n" @73..74 63 | [46] CloseBrace "}" @74..75 64 | [47] Whitespace "\n" @75..76 65 | [48] Ident "else" @76..80 66 | [49] Whitespace " " @80..81 67 | [50] Ident "CX" @81..83 68 | [51] Whitespace " " @83..84 69 | [52] Ident "x" @84..85 70 | [53] OpenBracket "[" @85..86 71 | [54] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @86..87 72 | [55] CloseBracket "]" @87..88 73 | [56] Comma "," @88..89 74 | [57] Whitespace " " @89..90 75 | [58] Ident "x" @90..91 76 | [59] OpenBracket "[" @91..92 77 | [60] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @92..93 78 | [61] CloseBracket "]" @93..94 79 | [62] Semi ";" @94..95 80 | [63] Whitespace "\n" @95..96 81 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__const.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid/statements/const.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | const myvar; 10 | const myvar = ; 11 | const myvar = 8.0; 12 | input const myvar = 8; 13 | output const myvar = 8; 14 | const input myvar = 8; 15 | const output myvar = 8; 16 | --- lexer --- 17 | ok: true 18 | errors: 0 19 | [0] Whitespace "\n" @0..1 20 | [1] Ident "const" @1..6 21 | [2] Whitespace " " @6..7 22 | [3] Ident "myvar" @7..12 23 | [4] Semi ";" @12..13 24 | [5] Whitespace "\n" @13..14 25 | [6] Ident "const" @14..19 26 | [7] Whitespace " " @19..20 27 | [8] Ident "myvar" @20..25 28 | [9] Whitespace " " @25..26 29 | [10] Eq "=" @26..27 30 | [11] Whitespace " " @27..28 31 | [12] Semi ";" @28..29 32 | [13] Whitespace "\n" @29..30 33 | [14] Ident "const" @30..35 34 | [15] Whitespace " " @35..36 35 | [16] Ident "myvar" @36..41 36 | [17] Whitespace " " @41..42 37 | [18] Eq "=" @42..43 38 | [19] Whitespace " " @43..44 39 | [20] Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 3 } "8.0" @44..47 40 | [21] Semi ";" @47..48 41 | [22] Whitespace "\n" @48..49 42 | [23] Ident "input" @49..54 43 | [24] Whitespace " " @54..55 44 | [25] Ident "const" @55..60 45 | [26] Whitespace " " @60..61 46 | [27] Ident "myvar" @61..66 47 | [28] Whitespace " " @66..67 48 | [29] Eq "=" @67..68 49 | [30] Whitespace " " @68..69 50 | [31] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @69..70 51 | [32] Semi ";" @70..71 52 | [33] Whitespace "\n" @71..72 53 | [34] Ident "output" @72..78 54 | [35] Whitespace " " @78..79 55 | [36] Ident "const" @79..84 56 | [37] Whitespace " " @84..85 57 | [38] Ident "myvar" @85..90 58 | [39] Whitespace " " @90..91 59 | [40] Eq "=" @91..92 60 | [41] Whitespace " " @92..93 61 | [42] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @93..94 62 | [43] Semi ";" @94..95 63 | [44] Whitespace "\n" @95..96 64 | [45] Ident "const" @96..101 65 | [46] Whitespace " " @101..102 66 | [47] Ident "input" @102..107 67 | [48] Whitespace " " @107..108 68 | [49] Ident "myvar" @108..113 69 | [50] Whitespace " " @113..114 70 | [51] Eq "=" @114..115 71 | [52] Whitespace " " @115..116 72 | [53] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @116..117 73 | [54] Semi ";" @117..118 74 | [55] Whitespace "\n" @118..119 75 | [56] Ident "const" @119..124 76 | [57] Whitespace " " @124..125 77 | [58] Ident "output" @125..131 78 | [59] Whitespace " " @131..132 79 | [60] Ident "myvar" @132..137 80 | [61] Whitespace " " @137..138 81 | [62] Eq "=" @138..139 82 | [63] Whitespace " " @139..140 83 | [64] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @140..141 84 | [65] Semi ";" @141..142 85 | [66] Whitespace "\n" @142..143 86 | -------------------------------------------------------------------------------- /crates/oq3_parser/src/input.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! See [`Input`]. 5 | 6 | use crate::SyntaxKind; 7 | 8 | #[allow(non_camel_case_types)] 9 | type bits = u64; 10 | 11 | // FIXME GJL `LexerToken` does not appear anywhere in the r-a project. 12 | // `LexerToken` seems to refer to output of `oq3_lexer::tokenize` and `LexedStr` 13 | // (also present in r-a). These *do* preserve whitespace and comments. 14 | /// Input for the parser -- a sequence of tokens. 15 | /// 16 | /// As of now, parser doesn't have access to the *text* of the tokens, and makes 17 | /// decisions based solely on their classification. Unlike `LexerToken`, the 18 | /// `Token` doesn't include whitespace and comments. Main input to the parser. 19 | /// 20 | /// Struct of arrays internally, but this shouldn't really matter. 21 | #[derive(Default)] 22 | pub struct Input { 23 | /// SyntaxKind has u16 variants 24 | kind: Vec, 25 | 26 | /// Account for whitespace/comments dropped on construction 27 | joint: Vec, 28 | } 29 | 30 | /// `pub` impl used by callers to create `Tokens`. 31 | impl Input { 32 | /// Sets jointness for the last token we've pushed. 33 | /// 34 | /// This is a separate API rather than an argument to the `push` to make it 35 | /// convenient both for textual and mbe tokens. With text, you know whether 36 | /// the *previous* token was joint, with mbe, you know whether the *current* 37 | /// one is joint. This API allows for styles of usage: 38 | /// 39 | /// ``` 40 | /// // In text: 41 | /// tokens.was_joint(prev_joint); 42 | /// tokens.push(curr); 43 | /// 44 | /// // In MBE: 45 | /// token.push(curr); 46 | /// tokens.push(curr_joint) 47 | /// ``` 48 | #[inline] 49 | pub fn was_joint(&mut self) { 50 | let n = self.len() - 1; 51 | let (idx, b_idx) = self.bit_index(n); 52 | self.joint[idx] |= 1 << b_idx; 53 | } 54 | #[inline] 55 | pub fn push(&mut self, kind: SyntaxKind) { 56 | let idx = self.len(); 57 | if idx % (bits::BITS as usize) == 0 { 58 | self.joint.push(0); 59 | } 60 | self.kind.push(kind); 61 | } 62 | } 63 | 64 | /// pub(crate) impl used by the parser to consume `Tokens`. 65 | impl Input { 66 | pub(crate) fn kind(&self, idx: usize) -> SyntaxKind { 67 | self.kind.get(idx).copied().unwrap_or(SyntaxKind::EOF) 68 | } 69 | 70 | pub(crate) fn is_joint(&self, n: usize) -> bool { 71 | let (idx, b_idx) = self.bit_index(n); 72 | self.joint[idx] & (1 << b_idx) != 0 73 | } 74 | } 75 | 76 | impl Input { 77 | fn bit_index(&self, n: usize) -> (usize, usize) { 78 | let idx = n / (bits::BITS as usize); 79 | let b_idx = n % (bits::BITS as usize); 80 | (idx, b_idx) 81 | } 82 | // Number of tokens 83 | fn len(&self) -> usize { 84 | self.kind.len() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__comments__comments.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/comments/comments.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | OPENQASM 3.0; 10 | // Line comment before include 11 | include "stdgates.inc"; // Inline comment 12 | /* Block comment before declaration */ 13 | qubit[2] q; /* Inline block comment */ 14 | 15 | // Comment before gate 16 | h q[0]; // Gate with comment 17 | /* Multi-line block comment 18 | spanning multiple lines */ 19 | cx q[0], q[1]; 20 | --- lexer --- 21 | ok: true 22 | errors: 0 23 | [0] Whitespace "\n" @0..1 24 | [1] OpenQasmVersionStmt { major: true, minor: true } "OPENQASM 3.0" @1..13 25 | [2] Semi ";" @13..14 26 | [3] Whitespace "\n" @14..15 27 | [4] LineComment "// Line comment before include" @15..45 28 | [5] Whitespace "\n" @45..46 29 | [6] Ident "include" @46..53 30 | [7] Whitespace " " @53..54 31 | [8] Literal { kind: Str { terminated: true }, suffix_start: 14 } ""stdgates.inc"" @54..68 32 | [9] Semi ";" @68..69 33 | [10] Whitespace " " @69..70 34 | [11] LineComment "// Inline comment" @70..87 35 | [12] Whitespace "\n" @87..88 36 | [13] BlockComment { terminated: true } "/* Block comment before declaration */" @88..126 37 | [14] Whitespace "\n" @126..127 38 | [15] Ident "qubit" @127..132 39 | [16] OpenBracket "[" @132..133 40 | [17] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @133..134 41 | [18] CloseBracket "]" @134..135 42 | [19] Whitespace " " @135..136 43 | [20] Ident "q" @136..137 44 | [21] Semi ";" @137..138 45 | [22] Whitespace " " @138..139 46 | [23] BlockComment { terminated: true } "/* Inline block comment */" @139..165 47 | [24] Whitespace "\n\n" @165..167 48 | [25] LineComment "// Comment before gate" @167..189 49 | [26] Whitespace "\n" @189..190 50 | [27] Ident "h" @190..191 51 | [28] Whitespace " " @191..192 52 | [29] Ident "q" @192..193 53 | [30] OpenBracket "[" @193..194 54 | [31] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @194..195 55 | [32] CloseBracket "]" @195..196 56 | [33] Semi ";" @196..197 57 | [34] Whitespace " " @197..198 58 | [35] LineComment "// Gate with comment" @198..218 59 | [36] Whitespace "\n" @218..219 60 | [37] BlockComment { terminated: true } "/* Multi-line block comment\n spanning multiple lines */" @219..276 61 | [38] Whitespace "\n" @276..277 62 | [39] Ident "cx" @277..279 63 | [40] Whitespace " " @279..280 64 | [41] Ident "q" @280..281 65 | [42] OpenBracket "[" @281..282 66 | [43] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @282..283 67 | [44] CloseBracket "]" @283..284 68 | [45] Comma "," @284..285 69 | [46] Whitespace " " @285..286 70 | [47] Ident "q" @286..287 71 | [48] OpenBracket "[" @287..288 72 | [49] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @288..289 73 | [50] CloseBracket "]" @289..290 74 | [51] Semi ";" @290..291 75 | [52] Whitespace "\n" @291..292 76 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__comments__comments_cnot.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/reference/comments/comments_cnot.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | OPENQASM 3.0; 10 | // Line comment before include 11 | include "stdgates.inc"; // Inline comment 12 | /* Block comment before declaration */ 13 | qubit[2] q; /* Inline block comment */ 14 | 15 | // Comment before gate 16 | h q[0]; // Gate with comment 17 | /* Multi-line block comment 18 | spanning multiple lines */ 19 | cnot q[0], q[1]; 20 | --- lexer --- 21 | ok: true 22 | errors: 0 23 | [0] Whitespace "\n" @0..1 24 | [1] OpenQasmVersionStmt { major: true, minor: true } "OPENQASM 3.0" @1..13 25 | [2] Semi ";" @13..14 26 | [3] Whitespace "\n" @14..15 27 | [4] LineComment "// Line comment before include" @15..45 28 | [5] Whitespace "\n" @45..46 29 | [6] Ident "include" @46..53 30 | [7] Whitespace " " @53..54 31 | [8] Literal { kind: Str { terminated: true }, suffix_start: 14 } ""stdgates.inc"" @54..68 32 | [9] Semi ";" @68..69 33 | [10] Whitespace " " @69..70 34 | [11] LineComment "// Inline comment" @70..87 35 | [12] Whitespace "\n" @87..88 36 | [13] BlockComment { terminated: true } "/* Block comment before declaration */" @88..126 37 | [14] Whitespace "\n" @126..127 38 | [15] Ident "qubit" @127..132 39 | [16] OpenBracket "[" @132..133 40 | [17] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "2" @133..134 41 | [18] CloseBracket "]" @134..135 42 | [19] Whitespace " " @135..136 43 | [20] Ident "q" @136..137 44 | [21] Semi ";" @137..138 45 | [22] Whitespace " " @138..139 46 | [23] BlockComment { terminated: true } "/* Inline block comment */" @139..165 47 | [24] Whitespace "\n\n" @165..167 48 | [25] LineComment "// Comment before gate" @167..189 49 | [26] Whitespace "\n" @189..190 50 | [27] Ident "h" @190..191 51 | [28] Whitespace " " @191..192 52 | [29] Ident "q" @192..193 53 | [30] OpenBracket "[" @193..194 54 | [31] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @194..195 55 | [32] CloseBracket "]" @195..196 56 | [33] Semi ";" @196..197 57 | [34] Whitespace " " @197..198 58 | [35] LineComment "// Gate with comment" @198..218 59 | [36] Whitespace "\n" @218..219 60 | [37] BlockComment { terminated: true } "/* Multi-line block comment\n spanning multiple lines */" @219..276 61 | [38] Whitespace "\n" @276..277 62 | [39] Ident "cnot" @277..281 63 | [40] Whitespace " " @281..282 64 | [41] Ident "q" @282..283 65 | [42] OpenBracket "[" @283..284 66 | [43] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "0" @284..285 67 | [44] CloseBracket "]" @285..286 68 | [45] Comma "," @286..287 69 | [46] Whitespace " " @287..288 70 | [47] Ident "q" @288..289 71 | [48] OpenBracket "[" @289..290 72 | [49] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "1" @290..291 73 | [50] CloseBracket "]" @291..292 74 | [51] Semi ";" @292..293 75 | [52] Whitespace "\n" @293..294 76 | -------------------------------------------------------------------------------- /crates/oq3_syntax/src/token_text.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Yet another version of owned string, backed by a syntax tree token. 5 | 6 | use std::{cmp::Ordering, fmt, ops}; 7 | 8 | use rowan::GreenToken; 9 | use smol_str::SmolStr; 10 | 11 | pub struct TokenText<'a>(pub(crate) Repr<'a>); 12 | 13 | pub(crate) enum Repr<'a> { 14 | Borrowed(&'a str), 15 | Owned(GreenToken), 16 | } 17 | 18 | impl<'a> TokenText<'a> { 19 | pub(crate) fn borrowed(text: &'a str) -> Self { 20 | TokenText(Repr::Borrowed(text)) 21 | } 22 | 23 | pub(crate) fn owned(green: GreenToken) -> Self { 24 | TokenText(Repr::Owned(green)) 25 | } 26 | 27 | pub fn as_str(&self) -> &str { 28 | match &self.0 { 29 | &Repr::Borrowed(it) => it, 30 | Repr::Owned(green) => green.text(), 31 | } 32 | } 33 | } 34 | 35 | impl ops::Deref for TokenText<'_> { 36 | type Target = str; 37 | 38 | fn deref(&self) -> &str { 39 | self.as_str() 40 | } 41 | } 42 | impl AsRef for TokenText<'_> { 43 | fn as_ref(&self) -> &str { 44 | self.as_str() 45 | } 46 | } 47 | 48 | impl From> for String { 49 | fn from(token_text: TokenText<'_>) -> Self { 50 | token_text.as_str().into() 51 | } 52 | } 53 | 54 | impl From> for SmolStr { 55 | fn from(token_text: TokenText<'_>) -> Self { 56 | SmolStr::new(token_text.as_str()) 57 | } 58 | } 59 | 60 | impl PartialEq<&'_ str> for TokenText<'_> { 61 | fn eq(&self, other: &&str) -> bool { 62 | self.as_str() == *other 63 | } 64 | } 65 | impl PartialEq> for &'_ str { 66 | fn eq(&self, other: &TokenText<'_>) -> bool { 67 | other == self 68 | } 69 | } 70 | impl PartialEq for TokenText<'_> { 71 | fn eq(&self, other: &String) -> bool { 72 | self.as_str() == other.as_str() 73 | } 74 | } 75 | impl PartialEq> for String { 76 | fn eq(&self, other: &TokenText<'_>) -> bool { 77 | other == self 78 | } 79 | } 80 | impl PartialEq for TokenText<'_> { 81 | fn eq(&self, other: &TokenText<'_>) -> bool { 82 | self.as_str() == other.as_str() 83 | } 84 | } 85 | impl Eq for TokenText<'_> {} 86 | impl Ord for TokenText<'_> { 87 | fn cmp(&self, other: &Self) -> Ordering { 88 | self.as_str().cmp(other.as_str()) 89 | } 90 | } 91 | impl PartialOrd for TokenText<'_> { 92 | fn partial_cmp(&self, other: &Self) -> Option { 93 | Some(self.cmp(other)) 94 | } 95 | } 96 | impl fmt::Display for TokenText<'_> { 97 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 98 | fmt::Display::fmt(self.as_str(), f) 99 | } 100 | } 101 | impl fmt::Debug for TokenText<'_> { 102 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 103 | fmt::Debug::fmt(self.as_str(), f) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__measure.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/invalid/statements/measure.qasm 6 | expect-parse: Diag 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 15 11 | --- ast --- 12 | SOURCE_FILE@0..234: 13 | measure $0, $1; 14 | a[0:1] = measure $0, $1; 15 | a = measure $0 -> b; 16 | creg a[1] = measure $0; 17 | measure $0 -> creg a[1]; 18 | measure $0 -> bit[1] a; 19 | // Measure can't be used in sub-expressions. 20 | a = 2 * measure $0; 21 | a = (measure $0) + (measure $1); 22 | 23 | EXPR_STMT@1..11: measure $0 24 | MEASURE_EXPRESSION@1..11: measure $0 25 | HARDWARE_QUBIT@9..11: $0 26 | ERROR@11..12: , 27 | EXPR_STMT@13..16: $1; 28 | HARDWARE_QUBIT@13..15: $1 29 | ASSIGNMENT_STMT@17..36: a[0:1] = measure $0 30 | INDEXED_IDENTIFIER@17..23: a[0:1] 31 | IDENTIFIER@17..18: a 32 | INDEX_OPERATOR@18..23: [0:1] 33 | EXPRESSION_LIST@19..22: 0:1 34 | RANGE_EXPR@19..22: 0:1 35 | LITERAL@19..20: 0 36 | LITERAL@21..22: 1 37 | MEASURE_EXPRESSION@26..36: measure $0 38 | HARDWARE_QUBIT@34..36: $0 39 | ERROR@36..37: , 40 | EXPR_STMT@38..41: $1; 41 | HARDWARE_QUBIT@38..40: $1 42 | EXPR_STMT@42..59: a = measure $0 -> 43 | BIN_EXPR@42..59: a = measure $0 -> 44 | ASSIGNMENT_STMT@42..56: a = measure $0 45 | IDENTIFIER@42..43: a 46 | MEASURE_EXPRESSION@46..56: measure $0 47 | HARDWARE_QUBIT@54..56: $0 48 | ERROR@58..59: > 49 | EXPR_STMT@60..62: b; 50 | IDENTIFIER@60..61: b 51 | OLD_STYLE_DECLARATION_STATEMENT@63..72: creg a[1] 52 | OLD_TYPED_PARAM@63..72: creg a[1] 53 | INDEX_OPERATOR@69..72: [1] 54 | EXPRESSION_LIST@70..71: 1 55 | LITERAL@70..71: 1 56 | ERROR@73..74: = 57 | EXPR_STMT@75..86: measure $0; 58 | MEASURE_EXPRESSION@75..85: measure $0 59 | HARDWARE_QUBIT@83..85: $0 60 | EXPR_STMT@87..100: measure $0 -> 61 | BIN_EXPR@87..100: measure $0 -> 62 | MEASURE_EXPRESSION@87..97: measure $0 63 | HARDWARE_QUBIT@95..97: $0 64 | ERROR@99..100: > 65 | OLD_STYLE_DECLARATION_STATEMENT@101..111: creg a[1]; 66 | OLD_TYPED_PARAM@101..110: creg a[1] 67 | INDEX_OPERATOR@107..110: [1] 68 | EXPRESSION_LIST@108..109: 1 69 | LITERAL@108..109: 1 70 | EXPR_STMT@112..125: measure $0 -> 71 | BIN_EXPR@112..125: measure $0 -> 72 | MEASURE_EXPRESSION@112..122: measure $0 73 | HARDWARE_QUBIT@120..122: $0 74 | ERROR@124..125: > 75 | CLASSICAL_DECLARATION_STATEMENT@126..135: bit[1] a; 76 | SCALAR_TYPE@126..132: bit[1] 77 | DESIGNATOR@129..132: [1] 78 | LITERAL@130..131: 1 79 | NAME@133..134: a 80 | EXPR_STMT@181..200: a = 2 * measure $0; 81 | BIN_EXPR@181..199: a = 2 * measure $0 82 | ASSIGNMENT_STMT@181..186: a = 2 83 | IDENTIFIER@181..182: a 84 | LITERAL@185..186: 2 85 | MEASURE_EXPRESSION@189..199: measure $0 86 | HARDWARE_QUBIT@197..199: $0 87 | EXPR_STMT@201..233: a = (measure $0) + (measure $1); 88 | BIN_EXPR@201..232: a = (measure $0) + (measure $1) 89 | ASSIGNMENT_STMT@201..217: a = (measure $0) 90 | IDENTIFIER@201..202: a 91 | PAREN_EXPR@205..217: (measure $0) 92 | MEASURE_EXPRESSION@206..216: measure $0 93 | HARDWARE_QUBIT@214..216: $0 94 | PAREN_EXPR@220..232: (measure $1) 95 | MEASURE_EXPRESSION@221..231: measure $1 96 | HARDWARE_QUBIT@229..231: $1 97 | -------------------------------------------------------------------------------- /crates/oq3_syntax/src/syntax_node.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! This module defines Concrete Syntax Tree (CST), used by rust-analyzer. 5 | //! 6 | //! The CST includes comments and whitespace, provides a single node type, 7 | //! `SyntaxNode`, and a basic traversal API (parent, children, siblings). 8 | //! 9 | //! The *real* implementation is in the (language-agnostic) `rowan` crate, this 10 | //! module just wraps its API. 11 | 12 | use rowan::{GreenNodeBuilder, Language}; 13 | 14 | use crate::{Parse, SyntaxError, SyntaxKind, TextSize}; 15 | 16 | // FIXME: GJL Using this in demo program, so make it public. 17 | // actually rustc should warn if this is not used. 18 | pub use rowan::GreenNode; 19 | // pub(crate) use rowan::{GreenNode}; 20 | 21 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 22 | pub enum OpenQASM3Language {} 23 | impl Language for OpenQASM3Language { 24 | type Kind = SyntaxKind; 25 | 26 | fn kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind { 27 | SyntaxKind::from(raw.0) 28 | } 29 | 30 | fn kind_to_raw(kind: SyntaxKind) -> rowan::SyntaxKind { 31 | rowan::SyntaxKind(kind.into()) 32 | } 33 | } 34 | 35 | pub type SyntaxNode = rowan::SyntaxNode; 36 | pub type SyntaxToken = rowan::SyntaxToken; 37 | pub type SyntaxElement = rowan::SyntaxElement; 38 | pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren; 39 | pub type SyntaxElementChildren = rowan::SyntaxElementChildren; 40 | pub type PreorderWithTokens = rowan::api::PreorderWithTokens; 41 | 42 | #[derive(Default)] 43 | pub struct SyntaxTreeBuilder { 44 | errors: Vec, 45 | inner: GreenNodeBuilder<'static>, 46 | } 47 | 48 | impl SyntaxTreeBuilder { 49 | pub(crate) fn finish_raw(self) -> (GreenNode, Vec) { 50 | let green = self.inner.finish(); 51 | (green, self.errors) 52 | } 53 | 54 | pub fn finish(self) -> Parse { 55 | let (green, errors) = self.finish_raw(); 56 | // Disable block validation, see https://github.com/rust-lang/rust-analyzer/pull/10357 57 | #[allow(clippy::overly_complex_bool_expr)] 58 | // if cfg!(debug_assertions) && false { 59 | // let node = SyntaxNode::new_root(green.clone()); 60 | // crate::validation::validate_block_structure(&node); FIXME GJL 61 | // } 62 | Parse::new(green, errors) 63 | } 64 | 65 | pub fn token(&mut self, kind: SyntaxKind, text: &str) { 66 | let kind = OpenQASM3Language::kind_to_raw(kind); 67 | self.inner.token(kind, text); 68 | } 69 | 70 | pub fn start_node(&mut self, kind: SyntaxKind) { 71 | let kind = OpenQASM3Language::kind_to_raw(kind); 72 | self.inner.start_node(kind); 73 | } 74 | 75 | pub fn finish_node(&mut self) { 76 | self.inner.finish_node(); 77 | } 78 | 79 | pub fn error(&mut self, error: String, text_pos: TextSize) { 80 | self.errors 81 | .push(SyntaxError::new_at_offset(error, text_pos)); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tools/expect_summary.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import pathlib 4 | import re 5 | from collections import Counter, defaultdict 6 | 7 | STAGES = ("lex", "parse", "sema") 8 | STAGE_W = max(len(s) for s in STAGES) 9 | 10 | TAG_MAP = { 11 | "ok": "ok", 12 | "pass": "ok", 13 | "diag": "diag", 14 | "diagnostic": "diag", 15 | "todo": "todo", 16 | "panic": "panic", 17 | "fail": "panic", 18 | "skip": "skip", 19 | } 20 | 21 | 22 | DIR_RE = re.compile(r'^\s*//\s*(lex|parse|sema|analy[sz]e)\s*:\s*([A-Za-z]+)\s*$', re.I) 23 | 24 | def parse_expectations(path: pathlib.Path, head_lines: int = 16): 25 | lex = parse = sema = None 26 | try: 27 | with path.open("r", encoding="utf-8") as f: 28 | for i, line in enumerate(f): 29 | if i >= head_lines: 30 | break 31 | m = DIR_RE.match(line) 32 | if not m: 33 | continue 34 | stage = m.group(1).lower() 35 | if stage.startswith("analy"): 36 | stage = "sema" 37 | tag = TAG_MAP.get(m.group(2).lower()) 38 | if tag is None: 39 | continue 40 | if stage == "lex": lex = tag 41 | if stage == "parse": parse = tag 42 | if stage == "sema": sema = tag 43 | except Exception: 44 | pass 45 | return {"lex": lex, "parse": parse, "sema": sema} 46 | 47 | def main(): 48 | ap = argparse.ArgumentParser() 49 | ap.add_argument("root", nargs="?", default="tests/snippets", 50 | help="root directory to scan (default: tests/snippets)") 51 | ap.add_argument("--summary-only", action="store_true", 52 | help="only print totals per stage/tag") 53 | args = ap.parse_args() 54 | 55 | root = pathlib.Path(args.root) 56 | files = sorted(root.rglob("*.qasm")) 57 | if not files: 58 | print(f"No .qasm under {root}") 59 | return 1 60 | 61 | # Counters per stage 62 | counts = {st: Counter() for st in STAGES} 63 | 64 | rows = [] 65 | for p in files: 66 | exp = parse_expectations(p) 67 | rows.append((p.relative_to(root), exp)) 68 | for st in STAGES: 69 | counts[st][exp[st] or "unset"] += 1 70 | 71 | if not args.summary_only: 72 | # Column widths 73 | w_path = max(len(str(r[0])) for r in rows + [(pathlib.Path("path"), {"lex":"","parse":"","sema":""})]) 74 | print(f"{'path'.ljust(w_path)} lex parse sema") 75 | for rel, exp in rows: 76 | print(f"{str(rel).ljust(w_path)} {exp['lex'] or '-':<5} {exp['parse'] or '-':<5} {exp['sema'] or '-':<5}") 77 | 78 | print("\nTotals:") 79 | order = ["ok", "diag", "todo", "panic", "skip", "unset"] 80 | tag_w = max(len(k) for k in order) 81 | for st in STAGES: 82 | c = counts[st] 83 | # Print in a fixed order; include unset if present 84 | # parts = [f"{k}={c[k]}" for k in order if c[k] > 0] 85 | parts = [f"{k}={c[k]:<3}" for k in order if c[k] > 0] 86 | total = sum(c.values()) 87 | print(f"- {st:<{STAGE_W}}: total={total:<3}; " + ", ".join(parts)) 88 | 89 | return 0 90 | 91 | if __name__ == "__main__": 92 | raise SystemExit(main()) 93 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__invalid__statements__io.qasm-lex.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: lex_snap 4 | --- 5 | id: tests/snippets/invalid/statements/io.qasm 6 | expect-lex: Ok 7 | --- source --- 8 | 9 | input int[8]; 10 | output int[8]; 11 | input qreg myvar[4]; 12 | output qreg myvar[4]; 13 | input int[8] myvar = 32; 14 | output int[8] myvar = 32; 15 | input myvar; 16 | output myvar; 17 | --- lexer --- 18 | ok: true 19 | errors: 0 20 | [0] Whitespace "\n" @0..1 21 | [1] Ident "input" @1..6 22 | [2] Whitespace " " @6..7 23 | [3] Ident "int" @7..10 24 | [4] OpenBracket "[" @10..11 25 | [5] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @11..12 26 | [6] CloseBracket "]" @12..13 27 | [7] Semi ";" @13..14 28 | [8] Whitespace "\n" @14..15 29 | [9] Ident "output" @15..21 30 | [10] Whitespace " " @21..22 31 | [11] Ident "int" @22..25 32 | [12] OpenBracket "[" @25..26 33 | [13] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @26..27 34 | [14] CloseBracket "]" @27..28 35 | [15] Semi ";" @28..29 36 | [16] Whitespace "\n" @29..30 37 | [17] Ident "input" @30..35 38 | [18] Whitespace " " @35..36 39 | [19] Ident "qreg" @36..40 40 | [20] Whitespace " " @40..41 41 | [21] Ident "myvar" @41..46 42 | [22] OpenBracket "[" @46..47 43 | [23] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "4" @47..48 44 | [24] CloseBracket "]" @48..49 45 | [25] Semi ";" @49..50 46 | [26] Whitespace "\n" @50..51 47 | [27] Ident "output" @51..57 48 | [28] Whitespace " " @57..58 49 | [29] Ident "qreg" @58..62 50 | [30] Whitespace " " @62..63 51 | [31] Ident "myvar" @63..68 52 | [32] OpenBracket "[" @68..69 53 | [33] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "4" @69..70 54 | [34] CloseBracket "]" @70..71 55 | [35] Semi ";" @71..72 56 | [36] Whitespace "\n" @72..73 57 | [37] Ident "input" @73..78 58 | [38] Whitespace " " @78..79 59 | [39] Ident "int" @79..82 60 | [40] OpenBracket "[" @82..83 61 | [41] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @83..84 62 | [42] CloseBracket "]" @84..85 63 | [43] Whitespace " " @85..86 64 | [44] Ident "myvar" @86..91 65 | [45] Whitespace " " @91..92 66 | [46] Eq "=" @92..93 67 | [47] Whitespace " " @93..94 68 | [48] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "32" @94..96 69 | [49] Semi ";" @96..97 70 | [50] Whitespace "\n" @97..98 71 | [51] Ident "output" @98..104 72 | [52] Whitespace " " @104..105 73 | [53] Ident "int" @105..108 74 | [54] OpenBracket "[" @108..109 75 | [55] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 } "8" @109..110 76 | [56] CloseBracket "]" @110..111 77 | [57] Whitespace " " @111..112 78 | [58] Ident "myvar" @112..117 79 | [59] Whitespace " " @117..118 80 | [60] Eq "=" @118..119 81 | [61] Whitespace " " @119..120 82 | [62] Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 2 } "32" @120..122 83 | [63] Semi ";" @122..123 84 | [64] Whitespace "\n" @123..124 85 | [65] Ident "input" @124..129 86 | [66] Whitespace " " @129..130 87 | [67] Ident "myvar" @130..135 88 | [68] Semi ";" @135..136 89 | [69] Whitespace "\n" @136..137 90 | [70] Ident "output" @137..143 91 | [71] Whitespace " " @143..144 92 | [72] Ident "myvar" @144..149 93 | [73] Semi ";" @149..150 94 | [74] Whitespace "\n" @150..151 95 | -------------------------------------------------------------------------------- /crates/pipeline-tests/tests/snapshots/runner__tests__snippets__reference__assignment__assignment.qasm-parse.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/pipeline-tests/tests/runner.rs 3 | expression: parse_snap 4 | --- 5 | id: tests/snippets/reference/assignment/assignment.qasm 6 | expect-parse: Todo 7 | --- parser --- 8 | ok: false 9 | panicked: false 10 | errors: 3 11 | --- ast --- 12 | SOURCE_FILE@0..161: 13 | bit[2] a; 14 | bit[2] b; 15 | creg b[2]; 16 | qubit[3] q; 17 | int[10] x = 12; 18 | a[0] = b[1]; 19 | x += int[10](a[1]); 20 | measure q[1] -> a[0]; 21 | a = measure q[1:2]; 22 | measure q[0]; 23 | b = a == 0; 24 | 25 | CLASSICAL_DECLARATION_STATEMENT@1..10: bit[2] a; 26 | SCALAR_TYPE@1..7: bit[2] 27 | DESIGNATOR@4..7: [2] 28 | LITERAL@5..6: 2 29 | NAME@8..9: a 30 | CLASSICAL_DECLARATION_STATEMENT@11..20: bit[2] b; 31 | SCALAR_TYPE@11..17: bit[2] 32 | DESIGNATOR@14..17: [2] 33 | LITERAL@15..16: 2 34 | NAME@18..19: b 35 | OLD_STYLE_DECLARATION_STATEMENT@21..31: creg b[2]; 36 | OLD_TYPED_PARAM@21..30: creg b[2] 37 | INDEX_OPERATOR@27..30: [2] 38 | EXPRESSION_LIST@28..29: 2 39 | LITERAL@28..29: 2 40 | QUANTUM_DECLARATION_STATEMENT@32..43: qubit[3] q; 41 | QUBIT_TYPE@32..40: qubit[3] 42 | DESIGNATOR@37..40: [3] 43 | LITERAL@38..39: 3 44 | NAME@41..42: q 45 | CLASSICAL_DECLARATION_STATEMENT@44..59: int[10] x = 12; 46 | SCALAR_TYPE@44..51: int[10] 47 | DESIGNATOR@47..51: [10] 48 | LITERAL@48..50: 10 49 | NAME@52..53: x 50 | LITERAL@56..58: 12 51 | ASSIGNMENT_STMT@60..72: a[0] = b[1]; 52 | INDEXED_IDENTIFIER@60..64: a[0] 53 | IDENTIFIER@60..61: a 54 | INDEX_OPERATOR@61..64: [0] 55 | EXPRESSION_LIST@62..63: 0 56 | LITERAL@62..63: 0 57 | INDEXED_IDENTIFIER@67..71: b[1] 58 | IDENTIFIER@67..68: b 59 | INDEX_OPERATOR@68..71: [1] 60 | EXPRESSION_LIST@69..70: 1 61 | LITERAL@69..70: 1 62 | EXPR_STMT@73..92: x += int[10](a[1]); 63 | BIN_EXPR@73..91: x += int[10](a[1]) 64 | IDENTIFIER@73..74: x 65 | CAST_EXPRESSION@78..91: int[10](a[1]) 66 | SCALAR_TYPE@78..85: int[10] 67 | DESIGNATOR@81..85: [10] 68 | LITERAL@82..84: 10 69 | INDEXED_IDENTIFIER@86..90: a[1] 70 | IDENTIFIER@86..87: a 71 | INDEX_OPERATOR@87..90: [1] 72 | EXPRESSION_LIST@88..89: 1 73 | LITERAL@88..89: 1 74 | EXPR_STMT@93..108: measure q[1] -> 75 | BIN_EXPR@93..108: measure q[1] -> 76 | MEASURE_EXPRESSION@93..105: measure q[1] 77 | INDEXED_IDENTIFIER@101..105: q[1] 78 | IDENTIFIER@101..102: q 79 | INDEX_OPERATOR@102..105: [1] 80 | EXPRESSION_LIST@103..104: 1 81 | LITERAL@103..104: 1 82 | ERROR@107..108: > 83 | EXPR_STMT@109..114: a[0]; 84 | INDEXED_IDENTIFIER@109..113: a[0] 85 | IDENTIFIER@109..110: a 86 | INDEX_OPERATOR@110..113: [0] 87 | EXPRESSION_LIST@111..112: 0 88 | LITERAL@111..112: 0 89 | ASSIGNMENT_STMT@115..134: a = measure q[1:2]; 90 | IDENTIFIER@115..116: a 91 | MEASURE_EXPRESSION@119..133: measure q[1:2] 92 | INDEXED_IDENTIFIER@127..133: q[1:2] 93 | IDENTIFIER@127..128: q 94 | INDEX_OPERATOR@128..133: [1:2] 95 | EXPRESSION_LIST@129..132: 1:2 96 | RANGE_EXPR@129..132: 1:2 97 | LITERAL@129..130: 1 98 | LITERAL@131..132: 2 99 | EXPR_STMT@135..148: measure q[0]; 100 | MEASURE_EXPRESSION@135..147: measure q[0] 101 | INDEXED_IDENTIFIER@143..147: q[0] 102 | IDENTIFIER@143..144: q 103 | INDEX_OPERATOR@144..147: [0] 104 | EXPRESSION_LIST@145..146: 0 105 | LITERAL@145..146: 0 106 | EXPR_STMT@149..160: b = a == 0; 107 | BIN_EXPR@149..159: b = a == 0 108 | ASSIGNMENT_STMT@149..154: b = a 109 | IDENTIFIER@149..150: b 110 | IDENTIFIER@153..154: a 111 | LITERAL@158..159: 0 112 | -------------------------------------------------------------------------------- /crates/oq3_semantics/tests/ast_tests.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to the openqasm-parser project 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use oq3_semantics::asg; 5 | use oq3_semantics::symbols; 6 | use oq3_semantics::types; 7 | 8 | const NUM_BUILTIN_CONSTS: usize = 7; 9 | 10 | // 11 | // TExpr 12 | // 13 | 14 | #[test] 15 | fn test_texpr_bool_literal() { 16 | use asg::BoolLiteral; 17 | use types::{IsConst, Type}; 18 | 19 | let bool_value = true; 20 | let literal = BoolLiteral::new(bool_value); 21 | let texpr = literal.clone().to_texpr(); 22 | assert_eq!(texpr.expression(), &literal.to_expr()); 23 | assert_eq!(texpr.get_type(), &Type::Bool(IsConst::True)); 24 | } 25 | 26 | #[test] 27 | fn test_texpr_int_literal() { 28 | use asg::IntLiteral; 29 | use types::{IsConst, Type}; 30 | 31 | let literal = IntLiteral::new(1_u32, true); 32 | let texpr = literal.clone().to_texpr(); 33 | assert_eq!(texpr.expression(), &literal.to_expr()); 34 | assert_eq!(texpr.get_type(), &Type::Int(Some(128), IsConst::True)); 35 | } 36 | 37 | // 38 | // Structs representing expressions in ASG 39 | // 40 | 41 | // 42 | // Literal 43 | // 44 | 45 | #[test] 46 | fn test_int_literal() { 47 | use asg::IntLiteral; 48 | 49 | let int_value = 42; 50 | let literal = IntLiteral::new(int_value as u32, true); 51 | assert_eq!(*literal.value(), int_value as u128); 52 | } 53 | 54 | #[test] 55 | fn test_bitstring_literal() { 56 | use asg::BitStringLiteral; 57 | // use types::{Type, IsConst}; 58 | 59 | let bit_string_value = "10110"; 60 | let literal = BitStringLiteral::new(bit_string_value.to_string()); 61 | assert_eq!(literal.value(), bit_string_value); 62 | let texpr = literal.clone().to_texpr(); 63 | assert_eq!(texpr.expression(), &literal.clone().to_expr()); 64 | // assert_eq!(texpr.get_type(), &Type::Bit(Some(5), IsConst::True)); 65 | assert_eq!(texpr.expression(), &literal.to_expr()); 66 | } 67 | 68 | // 69 | // Cast 70 | // 71 | 72 | #[test] 73 | fn test_cast() { 74 | use asg::{Cast, IntLiteral}; 75 | use types::{IsConst, Type}; 76 | 77 | let typ = Type::Int(Some(32), IsConst::True); 78 | let literal = IntLiteral::new(1_u64, true).to_texpr(); 79 | let cast = Cast::new(literal.clone(), typ.clone()); 80 | assert_eq!(cast.get_type(), &typ); 81 | assert_eq!(cast.operand(), &literal); 82 | } 83 | 84 | #[test] 85 | fn test_declaration() { 86 | // use asg::{ClassicalDeclaration}; 87 | use symbols::SymbolTable; 88 | use types::{IsConst, Type}; 89 | 90 | let mut table = SymbolTable::new(); 91 | let x = table.new_binding("x", &Type::Bool(IsConst::False)); 92 | assert!(x.is_ok()); 93 | assert_eq!(table.len_current_scope(), 1 + NUM_BUILTIN_CONSTS); 94 | let result = table.lookup("x"); 95 | assert!(result.is_ok()); 96 | assert_eq!(result.unwrap().symbol_id(), x.unwrap()); 97 | } 98 | 99 | #[test] 100 | fn test_ident() { 101 | // use asg::{Identifier}; 102 | // use symbols::{SymbolTable}; 103 | // let table = SymbolTable::new(); 104 | } 105 | 106 | #[test] 107 | fn test_binary_expr_add() { 108 | // use asg::{BinaryExpr, Identifier}; 109 | // use asg::{BinaryOp::*}; 110 | // let expr = BinaryExpr::new(Add, 111 | } 112 | 113 | #[test] 114 | fn test_annotation() { 115 | let a = asg::Annotation::new("ann details".to_string()); 116 | assert_eq!(a.annotation_text(), "ann details"); 117 | } 118 | --------------------------------------------------------------------------------