/** * OpenQASM 3.0 Parser Implementation * * This module implements a recursive descent parser for OpenQASM 3.0 that transforms * a stream of tokens into an Abstract Syntax Tree (AST). The parser handles the full * OpenQASM 3.0 language specification including classical programming constructs, * control flow, quantum operations, and advanced features. * * Key parsing capabilities: * - **Classical types**: int, uint, float, bool, bit, complex, angle * - **Control flow**: if/else, for/while loops, switch/case statements * - **Functions**: def, return, extern declarations, subroutine calls * - **Quantum operations**: gate definitions/calls, measurements, barriers, delays * - **Advanced features**: arrays, timing constructs, calibration grammar * - **Expressions**: Arithmetic, logical, function calls with proper precedence * * The parser maintains context about: * - Defined gates (built-in, standard library, custom) * - Declared subroutines and external functions * - Array declarations and aliases * - Type information for validation * * @module * * @example Basic parsing workflow * ```typescript * const tokens = lexer.lex(); * const parser = new Parser(tokens); * const ast = parser.parse(); * ``` */ import { Token } from "./token"; import { AstNode, Expression, Parameters, ArrayReference, CalibrationGrammarDeclaration, Include, Version, Range, Identifier, SubscriptedIdentifier, MathFunction, TrigFunction, DurationOf, IndexSet, ArrayDeclaration, ArrayInitializer, ArrayAccess, QuantumMeasurement, QuantumMeasurementAssignment, ClassicalDeclaration, AssignmentStatement, QuantumDeclaration, AliasStatement, QuantumGateModifier, QuantumGateCall, QuantumBarrier, QuantumReset, QuantumDelay, ReturnStatement, ProgramBlock, QuantumGateDefinition, BoxDefinition, ExternSignature, SubroutineDefinition, SubroutineCall, BranchingStatement, ForLoopStatement, WhileLoopStatement, IODeclaration, SwitchStatement, CaseStatement, DefaultStatement, ClassicalType, HardwareQubit, SizeOf } from "./ast"; /** * OpenQASM 3.0 Recursive Descent Parser * * Implements a comprehensive parser for the OpenQASM 3.0 language specification. * The parser uses recursive descent parsing with appropriate error recovery and * maintains symbol tables for gates, subroutines, and variables. * * Parser state includes: * - Token stream and current position * - Symbol tables for gates, subroutines, arrays, aliases * - Machine-specific defaults (float width, int size) * * @example Creating and using the parser * ```typescript * const parser = new Parser(tokens); * * // Parse the entire program * const ast = parser.parse(); * * // AST contains array of top-level statements and declarations * console.log(ast); // [VersionNode, IncludeNode, DeclarationNode, ...] * ``` */ declare class Parser { /** The tokens to parse. */ tokens: Array<[Token, (number | string)?]>; /** The built in gates. */ gates: Set; /** Custom defined gates. */ customGates: Set; /** Standard library gates. */ standardGates: Set; /** Custom defined subroutines. */ subroutines: Set; /** User defined arrays. */ customArrays: Set; /** User defined aliases. */ aliases: Map; /** Index of the current token. */ index: number; /** The default machine precision float width. */ machineFloatWidth: number; /** The default machine int size. */ machineIntSize: number; /** * Creates a parser. * @param tokens - Tokens to parse. * @param defaultFloatWidth - Optional default float width override. * @param machineIntSize - Optional default int size override. */ constructor(tokens: Array<[Token, (number | string)?]>, defaultFloatWidth?: number, machineIntSize?: number); /** * Loads the standard library gates. */ stdGates(): void; /** * Parses the token stream and generates an abstract syntax tree. * @return The abstract syntax tree. */ parse(): Array; /** * Parses a single statement or declaration by delegating the parsing of the next set of tokens to the appropriate method. * @param tokens - Remaining tokens to parse. * @param allowVariables - Whether encountered identifiers should be consider variable initializations or references. * @return A set of AST nodes and the number of consumed tokens. */ parseNode(tokens: Array<[Token, (number | string)?]>, allowVariables?: boolean): [Array, number]; /** * Checks if the next tokens match those expected. * @param tokens - Remaining tokens to parse. * @param expectedTokens - Expected tokens. * @return Whether these is a match. */ matchNext(tokens: Array<[Token, (number | string)?]>, expectedTokens: Array): boolean; /** * Parses a `defcalgrammar` declaration. * * calibrationGrammarStatement: * DEFCALGRAMMAR StringLiteral SEMICOLON * * @param tokens - Remaining tokens to parse. * @return The parsed CalibrationGrammarDeclaration AstNode node and the number of consumed tokens. */ defcalGrammarDeclaration(tokens: Array<[Token, (number | string)?]>): [CalibrationGrammarDeclaration, number]; /** * Parses a classical type declaration. * @param tokens - Remaining tokens to parse. * @param isConst - Whether the declaration is for a constant, defaults to False. * @return The parsed ClassicalDeclaration AstNode and the number of consumed tokens. */ classicalDeclaration(tokens: Array<[Token, (number | string)?]>, isConst?: boolean): [ClassicalDeclaration, number]; /** * Parses an IO declaration statement. * @param tokens - Remaining tokens to parse. * @return A tuple containing the parsed IODeclaration and the number of tokens consumed. */ ioType(tokens: Array<[Token, (number | string)?]>): [IODeclaration, number]; /** * Parses a unary expression. * @param tokens - Remaining tokens to parse. * @return A tuple containing the parsed Expression and the number of tokens consumed. */ unaryExpression(tokens: Array<[Token, (number | string)?]>): [Expression, number]; /** * Parses a binary expression. * @param tokens - Remaining tokens to parse. * @return A tuple containing the parsed Expression and the number of tokens consumed. */ binaryExpression(tokens: Array<[Token, (number | string)?]>): [Expression, number]; /** * Parses an assignment statement. * @param tokens - Remaining tokens to parse. * @return The parsed AssignmentStatement AstNode and the number of consumed tokens. */ assignment(tokens: Array<[Token, (number | string)?]>): [AssignmentStatement, number]; /** * Parses a quantum declaration. * @param tokens - Tokens to parse. * @return A QuantumDeclaration node and the number of tokens consumed. */ quantumDeclaration(tokens: Array<[Token, (number | string)?]>): [QuantumDeclaration, number]; /** * Parses a measure statement. * @param tokens - Remaining tokens to parse. * @return A tuple containing the QuantumMeasurementAssignment or QuantumMeasurement and the number of tokens consumed. */ measureStatement(tokens: Array<[Token, (number | string)?]>): [QuantumMeasurementAssignment | QuantumMeasurement, number]; /** * Parses a subroutine return statement. * @param tokens - Remaining tokens to parse. * @return A tuple containing the SubroutineDefinition and the number of tokens consumed. */ returnStatement(tokens: Array<[Token, (number | string)?]>): [ReturnStatement, number]; /** * Parses an extern signature. * @param tokens - Remaining tokens to parse. * @return A tuple containing the ExternSignature and the number of tokens consumed. */ externSignature(tokens: Array<[Token, (number | string)?]>): [ExternSignature, number]; /** * Parses a subroutine definition. * @param tokens - Remaining tokens to parse. * @return A tuple containing the SubroutineDefinition and the number of tokens consumed. */ subroutineDefinition(tokens: Array<[Token, (number | string)?]>): [SubroutineDefinition, number]; /** * Parses a subroutine call. * @param tokens - Remaining tokens to parse. * @return A tuple containing the SubroutineCall and the number of tokens consumed. */ subroutineCall(tokens: Array<[Token, (number | string)?]>): [SubroutineCall, number]; /** * Parses a quantum gate definition. * @param tokens - Remaining tokens to parse. * @return A tuple containing the QuantumGateDefinition and the number of tokens consumed. */ quantumGateDefinition(tokens: Array<[Token, (number | string)?]>): [QuantumGateDefinition, number]; /** * Parses a quantum gate call. * @param tokens - Remaining tokens to parse. * @return A tuple containing the QuantumGateCall and the number of tokens consumed. */ quantumGateCall(tokens: Array<[Token, (number | string)?]>): [QuantumGateCall, number]; /** * Parses a list of qubits. * @param tokens - Remaining tokens to parse. * @return A tuple containing the list of qubits and the number of tokens consumed. */ parseQubitList(tokens: Array<[Token, (number | string)?]>): [Array, number]; /** * Parses a hardware qubit. * @param tokens - Remaining tokens to parse. * @return A tuple containing the HardwareQubit and the number of tokens consumed. */ parseHardwareQubit(tokens: Array<[Token, (number | string)?]>): [HardwareQubit, number]; /** * Parses a gate modifier. * @param tokens - Remaining tokens to parse. * @return A tuple containing the gate modifier and the number of tokens consumed. */ parseQuantumGateModifier(tokens: Array<[Token, (number | string)?]>): [QuantumGateModifier, number]; /** * Parses a set of parameters. * @param tokens - Remaining tokens to parse. * @return A tuple containing the Parameters and the number of tokens consumed. */ parseParameters(tokens: Array<[Token, (number | string)?]>): [Parameters, number]; /** * Parses an array reference. * @param tokens - Remaining tokens to parse. * @return A tuple containing the ArrayReference and the number of tokens consumed. */ parseArrayReference(tokens: Array<[Token, (number | string)?]>): [ArrayReference, number]; /** * Parses an alias statement. * @param tokens - Remaining tokens to parse. * @return A tuple containing the AliasStatement and the number of tokens consumed. */ aliasStatement(tokens: Array<[Token, (number | string)?]>): [AliasStatement, number]; /** * Parses a quantum reset. * @param tokens - Remaining tokens to parse. * @return A tuple containing the QuantumReset and the number of tokens consumed. */ resetStatement(tokens: Array<[Token, (number | string)?]>): [QuantumReset, number]; /** * Parses a subscript expression as a Range. * @param tokens - Remaining tokens to parse. * @return A tuple containing the parsed Expression or Range and the number of tokens consumed. */ parseSubscript(tokens: Array<[Token, (number | string)?]>): [Expression | Range | IndexSet, number]; /** * Parses a type cast expression. * @param tokens - Remaining tokens to parse. * @return A tuple containing the parsed Cast Expression and the number of tokens consumed. */ parseTypeCast(tokens: Array<[Token, (number | string)?]>): [Expression, number]; /** * Parses a branching condition (if) statement. * @param tokens - Tokens to parse. * @return A BranchingStatement node representing the if statement and the number of tokens consumed. */ ifStatement(tokens: Array<[Token, (number | string)?]>): [BranchingStatement, number]; /** * Parses a for loop. * @param tokens - Tokens to parse. * @return A ForLoopStatement node and the number of tokens consumed. */ forLoopStatement(tokens: Array<[Token, (number | string)?]>): [ForLoopStatement, number]; /** * Parses a while loop. * @param tokens - Tokens to parse. * @return A ForLoopStatement node and the number of tokens consumed. */ whileLoopStatement(tokens: Array<[Token, (number | string)?]>): [WhileLoopStatement, number]; /** * Parses a barrier statement. * @param tokens - Tokens to parse. * @return An QuantumBarrier node and the number of tokens consumed. */ barrier(tokens: Array<[Token, (number | string)?]>): [QuantumBarrier, number]; /** * Parses a box statement. * @param tokens - Tokens to parse. * @return An BoxDefinition node and the number of tokens consumed. */ box(tokens: Array<[Token, (number | string)?]>): [BoxDefinition, number]; /** * Parses an array statement. * @param tokens - Tokens to parse. * @return An ArrayDeclaration node and the number of tokens consumed. */ arrayDeclaration(tokens: Array<[Token, (number | string)?]>): [ArrayDeclaration, number]; /** * Parses an array initializer. * @param tokens - Tokens to parse. * @return An ArrayInitializer node and the number of tokens consumed. */ parseArrayInitializer(tokens: Array<[Token, (number | string)?]>): [ArrayInitializer | Expression, number]; /** * Parses an array access. * @param tokens - Tokens to parse. * @return An ArrayAccess node and the number of tokens consumed. */ parseArrayAccess(tokens: Array<[Token, (number | string)?]>): [ArrayAccess, number]; /** * Parses a switch statement. * @param tokens - Tokens to parse. * @return A SwitchStatement node and the number of tokens consumed. */ switchStatement(tokens: Array<[Token, (number | string)?]>): [SwitchStatement, number]; /** * Parses a case statement. * @param tokens - Tokens to parse. * @return A CaseStatement node and the number of tokens consumed. */ parseCaseStatement(tokens: Array<[Token, (number | string)?]>): [CaseStatement, number]; /** * Parses a default statement. * @param tokens - Tokens to parse. * @return A DefaultStatement node and the number of tokens consumed. */ parseDefaultStatement(tokens: Array<[Token, (number | string)?]>): [DefaultStatement, number]; /** * Parses a delay statement. * @param tokens - Tokens to parse. * @return A QuantumDelay node and the number of tokens consumed. */ delay(tokens: Array<[Token, (number | string)?]>): [QuantumDelay, number]; /** * Parses a durationof function call. * @param tokens - Tokens to parse. * @return A DurationOf node and the number of tokens consumed. */ durationOf(tokens: Array<[Token, (number | string)?]>): [DurationOf, number]; /** * Parses a sizeof function call. * @param tokens - Tokens to parse. * @return A SizeOf node and the number of tokens consumed. */ sizeOf(tokens: Array<[Token, (number | string)?]>): [SizeOf, number]; /** * Parses a program block. * @param tokens - Tokens to parse. * @return A ProgramBlock node and the number of tokens consumed. */ programBlock(tokens: Array<[Token, (number | string)?]>): [ProgramBlock, number]; /** * Parses an include statement. * @param tokens - Tokens to parse. * @return An Include node representing the include statement and the number of consumed tokens. */ include(tokens: Array<[Token, (number | string)?]>): [Include, number]; /** * Parses the version header and sets the parser version. * @param tokens - Tokens to parse. * @return A Version node representing the version statement and the number of consumed tokens. */ versionHeader(tokens: Array<[Token, (number | string)?]>): [Version, number]; /** * Parses a classical type. * @param token - The token that represents the type. * @return The ClassicalType and the number of consumed tokens. */ parseClassicalType(tokens: Array<[Token, (number | string)?]>): [ClassicalType, number]; /** * Parses a set declaration. * @param token - The token that represents the type. * @return The resulting Identifier, IndexSet, or Range node and the number of consumed tokens. */ parseSetDeclaration(tokens: Array<[Token, (number | string)?]>): [Expression | IndexSet | Range, number]; /** * Parses an index set. * @param token - The token that represents the type. * @return The resulting Identifier, IndexSet, or Range node and the number of consumed tokens. */ parseIndexSet(tokens: Array<[Token, (number | string)?]>): [IndexSet, number]; /** * Creates a classical type. * @param token - The token that represents the type. * @param width - The type's width or size, if applicable. * @return The created ClassicalType. */ createClassicalType(token: Token, width?: Expression | number): ClassicalType; /** * Creates a math or trigonometric function node. * @param token - The token representing the function. * @param expr - The expression to which the function is applied. * @return The created MathFunction or TrigFunction node and the number of consumed tokens. */ createMathOrTrigFunction(token: Token, expr: Expression): [MathFunction | TrigFunction, number]; /** Checks whether a Bit token precedes a measurement statement. */ private isMeasurement; /** Checks whether the statement is part of an assignment. */ private isAssignment; /** Checks whether an identifier is a quantum gate call. */ private isQuantumGateCall; /** Checks whether an identifier is a subroutine call. */ private isSubroutineCall; /** Checks whether a number is imaginary. */ private isImaginary; /** Checks whether an identifier is an array. */ private isArray; /** Checks whether an identifier represents a duration literal unit. */ private isDuration; /** TODO : update this * Validates whether a register or gate identifier. * @param identifier - The identifier to validate. * @return Boolean indicating successful validation or not. */ private validateIdentifier; } export default Parser;