mirror of https://github.com/openqasm/openqasm.git
231 lines
9.8 KiB
ANTLR
231 lines
9.8 KiB
ANTLR
parser grammar qasm3Parser;
|
|
|
|
options {
|
|
tokenVocab = qasm3Lexer;
|
|
}
|
|
|
|
program: version? statementOrScope* EOF;
|
|
version: OPENQASM VersionSpecifier SEMICOLON;
|
|
|
|
// A statement is any valid single statement of an OpenQASM 3 program, with the
|
|
// exception of the version-definition statement (which must be unique, and the
|
|
// first statement of the file if present). This file just defines rules for
|
|
// parsing; we leave semantic analysis and rejection of invalid scopes for
|
|
// compiler implementations.
|
|
statement:
|
|
pragma
|
|
// All the actual statements of the language.
|
|
| annotation* (
|
|
aliasDeclarationStatement
|
|
| assignmentStatement
|
|
| barrierStatement
|
|
| boxStatement
|
|
| breakStatement
|
|
| calStatement
|
|
| calibrationGrammarStatement
|
|
| classicalDeclarationStatement
|
|
| constDeclarationStatement
|
|
| continueStatement
|
|
| defStatement
|
|
| defcalStatement
|
|
| delayStatement
|
|
| endStatement
|
|
| expressionStatement
|
|
| externStatement
|
|
| forStatement
|
|
| gateCallStatement
|
|
| gateStatement
|
|
| ifStatement
|
|
| includeStatement
|
|
| ioDeclarationStatement
|
|
| measureArrowAssignmentStatement
|
|
| oldStyleDeclarationStatement
|
|
| quantumDeclarationStatement
|
|
| resetStatement
|
|
| returnStatement
|
|
| switchStatement
|
|
| whileStatement
|
|
)
|
|
;
|
|
annotation: AnnotationKeyword RemainingLineContent?;
|
|
scope: LBRACE statementOrScope* RBRACE;
|
|
pragma: PRAGMA RemainingLineContent;
|
|
|
|
statementOrScope: statement | scope;
|
|
|
|
|
|
/* Start top-level statement definitions. */
|
|
|
|
// Inclusion statements.
|
|
calibrationGrammarStatement: DEFCALGRAMMAR StringLiteral SEMICOLON;
|
|
includeStatement: INCLUDE StringLiteral SEMICOLON;
|
|
|
|
// Control-flow statements.
|
|
breakStatement: BREAK SEMICOLON;
|
|
continueStatement: CONTINUE SEMICOLON;
|
|
endStatement: END SEMICOLON;
|
|
forStatement: FOR scalarType Identifier IN (setExpression | LBRACKET rangeExpression RBRACKET | expression) body=statementOrScope;
|
|
ifStatement: IF LPAREN expression RPAREN if_body=statementOrScope (ELSE else_body=statementOrScope)?;
|
|
returnStatement: RETURN (expression | measureExpression)? SEMICOLON;
|
|
whileStatement: WHILE LPAREN expression RPAREN body=statementOrScope;
|
|
switchStatement: SWITCH LPAREN expression RPAREN LBRACE switchCaseItem* RBRACE;
|
|
switchCaseItem:
|
|
CASE expressionList scope
|
|
| DEFAULT scope
|
|
;
|
|
|
|
// Quantum directive statements.
|
|
barrierStatement: BARRIER gateOperandList? SEMICOLON;
|
|
boxStatement: BOX designator? scope;
|
|
delayStatement: DELAY designator gateOperandList? SEMICOLON;
|
|
/* `gateCallStatement` is split in two to avoid a potential ambiguity with an
|
|
* `expressionStatement` that consists of a single function call. The only
|
|
* "gate" that can have no operands is `gphase` with no control modifiers, and
|
|
* `gphase(pi);` looks grammatically identical to `fn(pi);`. We disambiguate by
|
|
* having `gphase` be its own token, and requiring that all other gate calls
|
|
* grammatically have at least one qubit. Strictly, as long as `gphase` is a
|
|
* separate token, ANTLR can disambiguate the statements by the definition
|
|
* order, but this is more robust. */
|
|
gateCallStatement:
|
|
gateModifier* Identifier (LPAREN expressionList? RPAREN)? designator? gateOperandList SEMICOLON
|
|
| gateModifier* GPHASE (LPAREN expressionList? RPAREN)? designator? gateOperandList? SEMICOLON
|
|
;
|
|
// measureArrowAssignmentStatement also permits the case of not assigning the
|
|
// result to any classical value too.
|
|
measureArrowAssignmentStatement: measureExpression (ARROW indexedIdentifier)? SEMICOLON;
|
|
resetStatement: RESET gateOperand SEMICOLON;
|
|
|
|
// Primitive declaration statements.
|
|
aliasDeclarationStatement: LET Identifier EQUALS aliasExpression SEMICOLON;
|
|
classicalDeclarationStatement: (scalarType | arrayType) Identifier (EQUALS declarationExpression)? SEMICOLON;
|
|
constDeclarationStatement: CONST scalarType Identifier EQUALS declarationExpression SEMICOLON;
|
|
ioDeclarationStatement: (INPUT | OUTPUT) (scalarType | arrayType) Identifier SEMICOLON;
|
|
oldStyleDeclarationStatement: (CREG | QREG) Identifier designator? SEMICOLON;
|
|
quantumDeclarationStatement: qubitType Identifier SEMICOLON;
|
|
|
|
// Declarations and definitions of higher-order objects.
|
|
defStatement: DEF Identifier LPAREN argumentDefinitionList? RPAREN returnSignature? scope;
|
|
externStatement: EXTERN Identifier LPAREN externArgumentList? RPAREN returnSignature? SEMICOLON;
|
|
gateStatement: GATE Identifier (LPAREN params=identifierList? RPAREN)? qubits=identifierList scope;
|
|
|
|
// Non-declaration assignments and calculations.
|
|
assignmentStatement: indexedIdentifier op=(EQUALS | CompoundAssignmentOperator) (expression | measureExpression) SEMICOLON;
|
|
expressionStatement: expression SEMICOLON;
|
|
|
|
// Statements where the bulk is in the calibration language.
|
|
calStatement: CAL LBRACE CalibrationBlock? RBRACE;
|
|
defcalStatement: DEFCAL defcalTarget (LPAREN defcalArgumentDefinitionList? RPAREN)? defcalOperandList returnSignature? LBRACE CalibrationBlock? RBRACE;
|
|
|
|
|
|
/* End top-level statement definitions. */
|
|
/* Start expression definitions. */
|
|
|
|
|
|
// ANTLR4 can handle direct left-recursive rules, and ambiguities are guaranteed
|
|
// to resolve in the order of definition. This means that the order of rules
|
|
// here defines the precedence table, from most tightly binding to least.
|
|
expression:
|
|
LPAREN expression RPAREN # parenthesisExpression
|
|
| expression indexOperator # indexExpression
|
|
| <assoc=right> expression op=DOUBLE_ASTERISK expression # powerExpression
|
|
| op=(TILDE | EXCLAMATION_POINT | MINUS) expression # unaryExpression
|
|
| expression op=(ASTERISK | SLASH | PERCENT) expression # multiplicativeExpression
|
|
| expression op=(PLUS | MINUS) expression # additiveExpression
|
|
| expression op=BitshiftOperator expression # bitshiftExpression
|
|
| expression op=ComparisonOperator expression # comparisonExpression
|
|
| expression op=EqualityOperator expression # equalityExpression
|
|
| expression op=AMPERSAND expression # bitwiseAndExpression
|
|
| expression op=CARET expression # bitwiseXorExpression
|
|
| expression op=PIPE expression # bitwiseOrExpression
|
|
| expression op=DOUBLE_AMPERSAND expression # logicalAndExpression
|
|
| expression op=DOUBLE_PIPE expression # logicalOrExpression
|
|
| (scalarType | arrayType) LPAREN expression RPAREN # castExpression
|
|
| DURATIONOF LPAREN scope RPAREN # durationofExpression
|
|
| Identifier LPAREN expressionList? RPAREN # callExpression
|
|
| (
|
|
Identifier
|
|
| BinaryIntegerLiteral
|
|
| OctalIntegerLiteral
|
|
| DecimalIntegerLiteral
|
|
| HexIntegerLiteral
|
|
| FloatLiteral
|
|
| ImaginaryLiteral
|
|
| BooleanLiteral
|
|
| BitstringLiteral
|
|
| TimingLiteral
|
|
| HardwareQubit
|
|
) # literalExpression
|
|
;
|
|
|
|
// Special-case expressions that are only valid in certain contexts. These are
|
|
// not in the expression tree, but can contain elements that are within it.
|
|
aliasExpression: expression (DOUBLE_PLUS expression)*;
|
|
declarationExpression: arrayLiteral | expression | measureExpression;
|
|
measureExpression: MEASURE gateOperand;
|
|
rangeExpression: expression? COLON expression? (COLON expression)?;
|
|
setExpression: LBRACE expression (COMMA expression)* COMMA? RBRACE;
|
|
arrayLiteral: LBRACE ((expression | arrayLiteral) (COMMA (expression | arrayLiteral))* COMMA?)? RBRACE;
|
|
|
|
// The general form is a comma-separated list of indexing entities.
|
|
// `setExpression` is only valid when being used as a single index: registers
|
|
// can support it for creating aliases, but arrays cannot.
|
|
indexOperator:
|
|
LBRACKET
|
|
(
|
|
setExpression
|
|
| (expression | rangeExpression) (COMMA (expression | rangeExpression))* COMMA?
|
|
)
|
|
RBRACKET;
|
|
// Alternative form to `indexExpression` for cases where an obvious l-value is
|
|
// better grammatically than a generic expression. Some current uses of this
|
|
// rule may be better as `expression`, leaving the semantic analysis to later
|
|
// (for example in gate calls).
|
|
indexedIdentifier: Identifier indexOperator*;
|
|
|
|
/* End expression definitions. */
|
|
/* Start type definitions. */
|
|
|
|
returnSignature: ARROW scalarType;
|
|
gateModifier: (
|
|
INV
|
|
| POW LPAREN expression RPAREN
|
|
| (CTRL | NEGCTRL) (LPAREN expression RPAREN)?
|
|
) AT;
|
|
|
|
scalarType:
|
|
BIT designator?
|
|
| INT designator?
|
|
| UINT designator?
|
|
| FLOAT designator?
|
|
| ANGLE designator?
|
|
| BOOL
|
|
| DURATION
|
|
| STRETCH
|
|
| COMPLEX (LBRACKET scalarType RBRACKET)?
|
|
;
|
|
qubitType: QUBIT designator?;
|
|
arrayType: ARRAY LBRACKET scalarType COMMA expressionList RBRACKET;
|
|
arrayReferenceType: (READONLY | MUTABLE) ARRAY LBRACKET scalarType COMMA (expressionList | DIM EQUALS expression) RBRACKET;
|
|
|
|
designator: LBRACKET expression RBRACKET;
|
|
|
|
defcalTarget: MEASURE | RESET | DELAY | Identifier;
|
|
defcalArgumentDefinition: expression | argumentDefinition;
|
|
defcalOperand: HardwareQubit | Identifier;
|
|
gateOperand: indexedIdentifier | HardwareQubit;
|
|
externArgument: scalarType | arrayReferenceType | CREG designator?;
|
|
argumentDefinition:
|
|
scalarType Identifier
|
|
| qubitType Identifier
|
|
| (CREG | QREG) Identifier designator?
|
|
| arrayReferenceType Identifier
|
|
;
|
|
|
|
argumentDefinitionList: argumentDefinition (COMMA argumentDefinition)* COMMA?;
|
|
defcalArgumentDefinitionList: defcalArgumentDefinition (COMMA defcalArgumentDefinition)* COMMA?;
|
|
defcalOperandList: defcalOperand (COMMA defcalOperand)* COMMA?;
|
|
expressionList: expression (COMMA expression)* COMMA?;
|
|
identifierList: Identifier (COMMA Identifier)* COMMA?;
|
|
gateOperandList: gateOperand (COMMA gateOperand)* COMMA?;
|
|
externArgumentList: externArgument (COMMA externArgument)* COMMA?;
|