Skip to content

Commit

Permalink
Redesign gate call modifiers, and other things (#86)
Browse files Browse the repository at this point in the history
In order to work quickly, this PR does a few things. Some of which are
listed below.

1. Redesign modified gate calls. In the AST modifiers are represented as a `Vec` of modifiers
in a field in the `GateCall` struct.
A similar structure is used in `oq3_parser`.

2. Fix parsing gate call with HW qubit as first arg.
For example `h $0` now parses correctly
Fixes #84

3. Require parens around conditions in `if` and `while` statements.
   Parens around these conditions are demanded by the spec.

4. Remove cruft and unused tags and identifiers that are not caught
 by compiler, clippy, and QA tools.
  • Loading branch information
jlapeyre authored Jan 31, 2024
1 parent 61b5071 commit 8ae2f0b
Show file tree
Hide file tree
Showing 11 changed files with 536 additions and 734 deletions.
141 changes: 66 additions & 75 deletions crates/oq3_parser/src/grammar/expressions/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,8 @@ pub(super) fn atom_expr(
T![return] => return_expr(p),
T!['{'] => block_expr(p),
T![for] => for_expr(p, None),
T![inv] => inv_modifier_expr(p),
T![pow] => pow_modifier_expr(p),
T![ctrl] => ctrl_modifier_expr(p),
T![negctrl] => negctrl_modifier_expr(p),
// FIXME: This is the simplest gate call. Need to cover
// `mygate(myparam) q1, q2;` as well.
IDENT if la == IDENT => gate_call_expr(p),
T![inv] | T![pow] | T![ctrl] | T![negctrl] => modified_gate_call_expr(p),
IDENT if (la == IDENT || la == HARDWAREIDENT) => gate_call_expr(p),
IDENT if (la == T![=] && p.nth(2) != T![=]) => grammar::items::assignment_statement(p),
// FIXME: An identifer bound by the user in the program.
// Need to handle more than identifier.
Expand All @@ -106,76 +101,72 @@ pub(super) fn atom_expr(
Some((done, blocklike))
}

fn inv_modifier_expr(p: &mut Parser<'_>) -> CompletedMarker {
fn modified_gate_call_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
p.bump(T![inv]);
if p.at(T![@]) {
p.bump(T![@]);
} else if p.at(T!['(']) {
p.error("Modifier `inv` accepts no parameter. Expecting `@`");
} else {
p.error("Expecting `@`");
}
maybe_modified_gate_call_expr(p);
m.complete(p, INV_GATE_CALL_EXPR)
}

fn pow_modifier_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
assert!(p.at(T![pow]));
p.bump(T![pow]);
if p.at(T!['(']) {
let m1 = p.start();
p.expect(T!['(']);
expressions::expr(p);
p.expect(T![')']);
m1.complete(p, PAREN_EXPR);
} else {
p.error("expecting argument to pow gate modifier");
}
p.expect(T![@]);
maybe_modified_gate_call_expr(p);
m.complete(p, POW_GATE_CALL_EXPR)
}

fn ctrl_modifier_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
p.bump(T![ctrl]);
if p.at(T!['(']) {
let m1 = p.start();
p.expect(T!['(']);
expressions::expr(p);
p.expect(T![')']);
m1.complete(p, PAREN_EXPR);
}
p.expect(T![@]);
maybe_modified_gate_call_expr(p);
m.complete(p, CTRL_GATE_CALL_EXPR)
}

fn negctrl_modifier_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
p.bump(T![negctrl]);
if p.at(T!['(']) {
let m1 = p.start();
p.expect(T!['(']);
expressions::expr(p);
p.expect(T![')']);
m1.complete(p, PAREN_EXPR);
}
p.expect(T![@]);
maybe_modified_gate_call_expr(p);
m.complete(p, NEG_CTRL_GATE_CALL_EXPR)
}

fn maybe_modified_gate_call_expr(p: &mut Parser<'_>) -> CompletedMarker {
match p.current() {
T![inv] => inv_modifier_expr(p),
T![pow] => pow_modifier_expr(p),
T![ctrl] => ctrl_modifier_expr(p),
T![negctrl] => negctrl_modifier_expr(p),
_ => gate_call_expr(p),
loop {
match p.current() {
T![inv] => {
let m1 = p.start();
p.bump(T![inv]);
if p.at(T![@]) {
p.bump(T![@]);
} else if p.at(T!['(']) {
p.error("Modifier `inv` accepts no parameter. Expecting `@`");
} else {
p.error("Expecting `@`");
}
m1.complete(p, INV_MODIFIER);
}

T![pow] => {
let m1 = p.start();
p.bump(T![pow]);
if p.at(T!['(']) {
let m2 = p.start();
p.expect(T!['(']);
expressions::expr(p);
p.expect(T![')']);
m2.complete(p, PAREN_EXPR);
} else {
p.error("expecting argument to pow gate modifier");
}
p.expect(T![@]);
m1.complete(p, POW_MODIFIER);
}

T![ctrl] => {
let m1 = p.start();
p.bump(T![ctrl]);
if p.at(T!['(']) {
let m2 = p.start();
p.expect(T!['(']);
expressions::expr(p);
p.expect(T![')']);
m2.complete(p, PAREN_EXPR);
}
p.expect(T![@]);
m1.complete(p, CTRL_MODIFIER);
}

T![negctrl] => {
let m1 = p.start();
p.bump(T![negctrl]);
if p.at(T!['(']) {
let m2 = p.start();
p.expect(T!['(']);
expressions::expr(p);
p.expect(T![')']);
m2.complete(p, PAREN_EXPR);
}
p.expect(T![@]);
m1.complete(p, NEG_CTRL_MODIFIER);
}

_ => break,
}
}
gate_call_expr(p);
m.complete(p, MODIFIED_GATE_CALL_EXPR)
}

fn gate_call_expr(p: &mut Parser<'_>) -> CompletedMarker {
Expand Down
4 changes: 4 additions & 0 deletions crates/oq3_parser/src/grammar/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ fn if_stmt(p: &mut Parser<'_>, m: Marker) {
assert!(p.at(T![if]));
// let m = p.start();
p.bump(T![if]);
p.expect(T!['(']);
expressions::expr_no_struct(p);
p.expect(T![')']);
expressions::block_expr(p);
if p.at(T![else]) {
p.bump(T![else]);
Expand All @@ -156,7 +158,9 @@ fn if_stmt(p: &mut Parser<'_>, m: Marker) {
fn while_stmt(p: &mut Parser<'_>, m: Marker) {
assert!(p.at(T![while]));
p.bump(T![while]);
p.expect(T!['(']);
expressions::expr_no_struct(p);
p.expect(T![')']);
expressions::block_expr(p);
m.complete(p, WHILE_STMT);
}
Expand Down
14 changes: 7 additions & 7 deletions crates/oq3_parser/src/syntax_kind/syntax_kind_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,10 @@ pub enum SyntaxKind {
CONCATENATION_EXPR,
BOX_EXPR,
CALL_EXPR,
CAST_EXPRESSION,
GATE_CALL_STMT,
GATE_CALL_EXPR,
MODIFIED_GATE_CALL_EXPR,
G_PHASE_CALL_STMT,
CAST_EXPRESSION,
INDEX_EXPR,
PREFIX_EXPR,
RANGE_EXPR,
Expand Down Expand Up @@ -225,11 +225,11 @@ pub enum SyntaxKind {
MEASURE_EXPRESSION,
OLD_STYLE_DECLARATION_STATEMENT,
QUANTUM_DECLARATION_STATEMENT,
INV_GATE_CALL_EXPR,
CTRL_GATE_CALL_EXPR,
NEG_CTRL_GATE_CALL_EXPR,
POW_GATE_CALL_EXPR,
GEN_GATE_CALL_EXPR,
INV_MODIFIER,
POW_MODIFIER,
CTRL_MODIFIER,
NEG_CTRL_MODIFIER,
MODIFIER,
#[doc(hidden)]
__LAST,
}
Expand Down
Loading

0 comments on commit 8ae2f0b

Please sign in to comment.