Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/oq3_parser/src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,8 @@ impl SyntaxKind {
pub fn is_type(&self) -> bool {
self.is_classical_type() || self.is_quantum_type()
}

pub fn is_creg_or_qreg(&self) -> bool {
matches!(self, T![qreg] | T![creg])
}
}
16 changes: 11 additions & 5 deletions crates/oq3_parser/src/grammar/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,24 +148,30 @@ pub(crate) fn stmt(p: &mut Parser<'_>) {
}
}

fn q_or_c_reg_declaration(p: &mut Parser<'_>, m: Marker) {
p.bump_any();
/// The designator is on the identifier, rather than the type
/// in OQ2. So we don't parse the identifier and type separately
/// as we do for OQ3 constructions.
pub fn q_or_c_reg_param(p: &mut Parser<'_>) {
let m = p.start();
p.bump_any(); // creg or qreg
if !p.at(IDENT) {
p.error("Expected qubit register name");
m.abandon(p);
return;
}
let m1 = p.start();
p.bump_any();
if p.at(T!['[']) && !p.at(EOF) {
index_operator(p);
} else {
p.error("Expected index operator");
m1.abandon(p);
m.abandon(p);
return;
}
m1.complete(p, INDEXED_IDENTIFIER);
m.complete(p, OLD_TYPED_PARAM);
}

fn q_or_c_reg_declaration(p: &mut Parser<'_>, m: Marker) {
q_or_c_reg_param(p);
p.expect(T![;]);
m.complete(p, OLD_STYLE_DECLARATION_STATEMENT);
}
Expand Down
11 changes: 10 additions & 1 deletion crates/oq3_parser/src/grammar/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,11 @@ fn _param_list_openqasm(p: &mut Parser<'_>, flavor: DefFlavor) {
// Allowed starts for an item: either a type or a first-token of a param/expression,
// or first token of array literal.
if matches!(flavor, DefParams) && (p.at(T![mutable]) || p.at(T![readonly])) {
} else if !(p.current().is_type() || p.at_ts(PARAM_FIRST) || inner_array_literal) {
} else if !(p.current().is_type()
|| p.at_ts(PARAM_FIRST)
|| inner_array_literal
|| p.current().is_creg_or_qreg())
{
p.error("expected value parameter");
m.abandon(p);
break;
Expand Down Expand Up @@ -294,6 +298,11 @@ fn param_untyped_or_hardware_qubit(p: &mut Parser<'_>, m: Marker) -> bool {
/// Parse one parameter in the list of parameters in the signature
/// of a subroutine defintion (that is, a `def` statement)
fn param_typed(p: &mut Parser<'_>, m: Marker) -> bool {
if p.at(T![creg]) || p.at(T![qreg]) {
m.abandon(p);
expressions::q_or_c_reg_param(p);
return true;
}
expressions::param_type_spec(p);
expressions::var_name(p);
m.complete(p, TYPED_PARAM);
Expand Down
1 change: 1 addition & 0 deletions crates/oq3_parser/src/syntax_kind/syntax_kind_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ pub enum SyntaxKind {
RANGE_EXPR,
TYPE,
TYPED_PARAM,
OLD_TYPED_PARAM,
TYPED_PARAM_LIST,
TYPE_LIST,
VERSION,
Expand Down
8 changes: 7 additions & 1 deletion crates/oq3_semantics/src/syntax_to_semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1471,7 +1471,13 @@ fn bind_typed_parameter_list(
param_list
.typed_params()
.map(|param| {
let typ = param_type_to_type(&param.param_type().unwrap(), false, context);
let typ = if let Some(pt) = param.param_type() {
param_type_to_type(&pt, false, context)
} else if param.old_typed_param().is_some() {
Type::ToDo
} else {
panic!("You have found a bug in oq3_parser")
};
let namestr = param.name().unwrap().string();
context.new_binding(namestr.as_ref(), &typ, &param)
})
Expand Down
1 change: 1 addition & 0 deletions crates/oq3_syntax/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ mod sourcegen {
"RANGE_EXPR",
"TYPE",
"TYPED_PARAM",
"OLD_TYPED_PARAM",
"TYPED_PARAM_LIST",
"TYPE_LIST",
"VERSION",
Expand Down
7 changes: 5 additions & 2 deletions crates/oq3_syntax/openqasm3.ungram
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,10 @@ ParamType =
(ScalarType | ArrayRefType)

TypedParam =
ParamType Name
(ParamType Name) | OldTypedParam

OldTypedParam =
('creg' | 'qreg') Name Designator?

TypedParamList =
'(' (TypedParam (',' TypedParam)* ','?)? ')'
Expand Down Expand Up @@ -446,7 +449,7 @@ IODeclarationStatement =
('input' | 'output') (ScalarType | ArrayType) Name ';'

OldStyleDeclarationStatement =
('creg' | 'qreg') Name Designator? ';'
OldTypedParam ';'

QuantumDeclarationStatement =
QubitType (Name | HardwareQubit) ';'
Expand Down
50 changes: 41 additions & 9 deletions crates/oq3_syntax/src/ast/generated/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,15 +405,8 @@ impl Measure {
pub struct OldStyleDeclarationStatement {
pub(crate) syntax: SyntaxNode,
}
impl ast::HasName for OldStyleDeclarationStatement {}
impl OldStyleDeclarationStatement {
pub fn creg_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![creg])
}
pub fn qreg_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![qreg])
}
pub fn designator(&self) -> Option<Designator> {
pub fn old_typed_param(&self) -> Option<OldTypedParam> {
support::child(&self.syntax)
}
pub fn semicolon_token(&self) -> Option<SyntaxToken> {
Expand Down Expand Up @@ -761,6 +754,25 @@ impl TypedParam {
pub fn param_type(&self) -> Option<ParamType> {
support::child(&self.syntax)
}
pub fn old_typed_param(&self) -> Option<OldTypedParam> {
support::child(&self.syntax)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct OldTypedParam {
pub(crate) syntax: SyntaxNode,
}
impl ast::HasName for OldTypedParam {}
impl OldTypedParam {
pub fn creg_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![creg])
}
pub fn qreg_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![qreg])
}
pub fn designator(&self) -> Option<Designator> {
support::child(&self.syntax)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ArrayExpr {
Expand Down Expand Up @@ -1955,6 +1967,21 @@ impl AstNode for TypedParam {
&self.syntax
}
}
impl AstNode for OldTypedParam {
fn can_cast(kind: SyntaxKind) -> bool {
kind == OLD_TYPED_PARAM
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl AstNode for ArrayExpr {
fn can_cast(kind: SyntaxKind) -> bool {
kind == ARRAY_EXPR
Expand Down Expand Up @@ -3037,10 +3064,10 @@ impl AstNode for AnyHasName {
| GATE
| I_O_DECLARATION_STATEMENT
| LET_STMT
| OLD_STYLE_DECLARATION_STATEMENT
| QUANTUM_DECLARATION_STATEMENT
| PARAM
| TYPED_PARAM
| OLD_TYPED_PARAM
| GATE_CALL_EXPR
| HARDWARE_QUBIT
| INDEXED_IDENTIFIER
Expand Down Expand Up @@ -3318,6 +3345,11 @@ impl std::fmt::Display for TypedParam {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for OldTypedParam {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ArrayExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ I_O_DECLARATION_STATEMENT@30..36: input
SCALAR_TYPE@36..36:
NAME@36..36:
OLD_STYLE_DECLARATION_STATEMENT@36..50: qreg myvar[4];
INDEXED_IDENTIFIER@41..49: myvar[4]
OLD_TYPED_PARAM@36..49: qreg myvar[4]
INDEX_OPERATOR@46..49: [4]
EXPRESSION_LIST@47..48: 4
LITERAL@47..48: 4
I_O_DECLARATION_STATEMENT@51..58: output
SCALAR_TYPE@58..58:
NAME@58..58:
OLD_STYLE_DECLARATION_STATEMENT@58..72: qreg myvar[4];
INDEXED_IDENTIFIER@63..71: myvar[4]
OLD_TYPED_PARAM@58..71: qreg myvar[4]
INDEX_OPERATOR@68..71: [4]
EXPRESSION_LIST@69..70: 4
LITERAL@69..70: 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ ERROR@58..59: >
EXPR_STMT@60..62: b;
IDENTIFIER@60..61: b
OLD_STYLE_DECLARATION_STATEMENT@63..72: creg a[1]
INDEXED_IDENTIFIER@68..72: a[1]
OLD_TYPED_PARAM@63..72: creg a[1]
INDEX_OPERATOR@69..72: [1]
EXPRESSION_LIST@70..71: 1
LITERAL@70..71: 1
Expand All @@ -63,7 +63,7 @@ MEASURE_EXPRESSION@87..97: measure $0
HARDWARE_QUBIT@95..97: $0
ERROR@99..100: >
OLD_STYLE_DECLARATION_STATEMENT@101..111: creg a[1];
INDEXED_IDENTIFIER@106..110: a[1]
OLD_TYPED_PARAM@101..110: creg a[1]
INDEX_OPERATOR@107..110: [1]
EXPRESSION_LIST@108..109: 1
LITERAL@108..109: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ DESIGNATOR@4..7: [2]
LITERAL@5..6: 2
NAME@8..9: a
OLD_STYLE_DECLARATION_STATEMENT@11..21: creg b[2];
INDEXED_IDENTIFIER@16..20: b[2]
OLD_TYPED_PARAM@11..20: creg b[2]
INDEX_OPERATOR@17..20: [2]
EXPRESSION_LIST@18..19: 2
LITERAL@18..19: 2
Expand All @@ -37,7 +37,7 @@ DESIGNATOR@27..30: [5]
LITERAL@28..29: 5
NAME@31..33: q1
OLD_STYLE_DECLARATION_STATEMENT@35..46: qreg q2[7];
INDEXED_IDENTIFIER@40..45: q2[7]
OLD_TYPED_PARAM@35..45: qreg q2[7]
INDEX_OPERATOR@42..45: [7]
EXPRESSION_LIST@43..44: 7
LITERAL@43..44: 7
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ DESIGNATOR@14..17: [2]
LITERAL@15..16: 2
NAME@18..19: b
OLD_STYLE_DECLARATION_STATEMENT@21..31: creg b[2];
INDEXED_IDENTIFIER@26..30: b[2]
OLD_TYPED_PARAM@21..30: creg b[2]
INDEX_OPERATOR@27..30: [2]
EXPRESSION_LIST@28..29: 2
LITERAL@28..29: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ source: crates/pipeline-tests/tests/runner.rs
expression: parse_snap
---
id: tests/snippets/reference/subroutine/subroutine.qasm
expect-parse: Todo
expect-parse: Ok
--- parser ---
ok: false
ok: true
panicked: false
errors: 14
errors: 0
--- ast ---
SOURCE_FILE@0..293:
def test_sub1(int[5] i, qubit[2] q1, qreg q2[5]) -> int[10] {
Expand All @@ -24,9 +24,13 @@ def returns_a_measure(qubit q) {
return measure q;
}

DEF@1..37: def test_sub1(int[5] i, qubit[2] q1,
DEF@1..137: def test_sub1(int[5] i, qubit[2] q1, qreg q2[5]) -> int[10] {
int[10] result;
if (result == 2) return 1 + result;
return result;
}
NAME@5..14: test_sub1
TYPED_PARAM_LIST@14..37: (int[5] i, qubit[2] q1,
TYPED_PARAM_LIST@14..49: (int[5] i, qubit[2] q1, qreg q2[5])
TYPED_PARAM@15..23: int[5] i
SCALAR_TYPE@15..21: int[5]
DESIGNATOR@18..21: [5]
Expand All @@ -37,24 +41,14 @@ SCALAR_TYPE@25..33: qubit[2]
DESIGNATOR@30..33: [2]
LITERAL@31..32: 2
NAME@34..36: q1
OLD_STYLE_DECLARATION_STATEMENT@38..48: qreg q2[5]
INDEXED_IDENTIFIER@43..48: q2[5]
OLD_TYPED_PARAM@38..48: qreg q2[5]
INDEX_OPERATOR@45..48: [5]
EXPRESSION_LIST@46..47: 5
LITERAL@46..47: 5
ERROR@48..49: )
EXPR_STMT@50..52: ->
PREFIX_EXPR@50..52: ->
ERROR@51..52: >
RETURN_SIGNATURE@50..60: -> int[10]
SCALAR_TYPE@53..60: int[10]
DESIGNATOR@56..60: [10]
LITERAL@57..59: 10
NAME@61..61:
EXPR_STMT@61..137: {
int[10] result;
if (result == 2) return 1 + result;
return result;
}
BLOCK_EXPR@61..137: {
int[10] result;
if (result == 2) return 1 + result;
Expand All @@ -77,9 +71,13 @@ IDENTIFIER@111..117: result
EXPR_STMT@121..135: return result;
RETURN_EXPR@121..134: return result
IDENTIFIER@128..134: result
DEF@138..171: def test_sub2(int[5] i, bit[2] b,
DEF@138..237: def test_sub2(int[5] i, bit[2] b, creg c[3]) {
for int[5] j in {2, 3}
i += j;
return i+1;
}
NAME@142..151: test_sub2
TYPED_PARAM_LIST@151..171: (int[5] i, bit[2] b,
TYPED_PARAM_LIST@151..182: (int[5] i, bit[2] b, creg c[3])
TYPED_PARAM@152..160: int[5] i
SCALAR_TYPE@152..158: int[5]
DESIGNATOR@155..158: [5]
Expand All @@ -90,17 +88,10 @@ SCALAR_TYPE@162..168: bit[2]
DESIGNATOR@165..168: [2]
LITERAL@166..167: 2
NAME@169..170: b
OLD_STYLE_DECLARATION_STATEMENT@172..181: creg c[3]
INDEXED_IDENTIFIER@177..181: c[3]
OLD_TYPED_PARAM@172..181: creg c[3]
INDEX_OPERATOR@178..181: [3]
EXPRESSION_LIST@179..180: 3
LITERAL@179..180: 3
ERROR@181..182: )
EXPR_STMT@183..237: {
for int[5] j in {2, 3}
i += j;
return i+1;
}
BLOCK_EXPR@183..237: {
for int[5] j in {2, 3}
i += j;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// lex: ok
// parse: todo
// parse: ok
// sema: skip

def test_sub1(int[5] i, qubit[2] q1, qreg q2[5]) -> int[10] {
Expand Down
Loading