Failing to fix a BNFC grammar in order to parse some custom code

35 Views Asked by At

I have the following BNFC grammar:

layout toplevel ;
layout "let" ;
layout stop "in" ;

entrypoints Program;

-- A program is a list of functions --
ProgDef .  Program ::= [FunctionDeclaration] ;

-- Types --
TypeBit     . Type3  ::= "Bit" ;
TypeQbit    . Type3  ::= "Qbit" ;
TypeState   . Type3  ::= "State" ;
TypeUnitary . Type3  ::= "Unitary" ;
TypeUnit    . Type3  ::= "()" ;
TypeNonLin  . Type2  ::= "!" Type3 ;
TypeExp     . Type2  ::= Type3 "**" Integer ;
TypeSum     . Type1  ::= Type2 "+" Type1 ;      -- right-associative
TypeTensr   . Type1  ::= Type2 "*" Type1 ;      -- right-associative
TypeFunc    . Type   ::= Type1 "->" Type ;      -- right-associative
coercions Type 3 ;

-- Angle is a fraction of 2π --
Angle . Angle ::= Double ;

-- Basis States --
BasisStateZero   . BasisState ::= "@0" ;
BasisStateOne    . BasisState ::= "@1" ;
BasisStatePlus   . BasisState ::= "@+" ;
BasisStateMinus  . BasisState ::= "@-" ;
BasisStatePlusI  . BasisState ::= "@+i" ;
BasisStateMinusI . BasisState ::= "@-i" ;

--- Bits ---
BitValue . Bit ::= Integer;

GateH             . Gate ::= "H" ;                                      -- Hadamard Gate
GateX             . Gate ::= "X"  ;                                     -- Pauli X Gate
GateY             . Gate ::= "Y"  ;                                     -- Pauli Y Gate
GateZ             . Gate ::= "Z"  ;                                     -- Pauli Z Gate
GateID            . Gate ::= "ID"  ;                                    -- Identity Gate
GateXRt           . Gate ::= "ROOT_X" Integer  ;                        -- Root of Pauli X gate (root is specified as k in 1/2^k)
GateXRtDag        . Gate ::= "ROOT_X_DAG" Integer  ;                    -- Conjugate of Root of Pauli X gate (root is specified as k in 1/2^k)
GateYRt           . Gate ::= "ROOT_Y" Integer  ;                        -- Root of Pauli Y gate (root is specified as k in 1/2^k)
GateYRtDag        . Gate ::= "ROOT_Y_DAG" Integer  ;                    -- Conjugate of Root of Pauli Y gate (root is specified as k in 1/2^k)
GateZRt           . Gate ::= "ROOT_Z" Integer  ;                        -- Root of Pauli Z gate (root is specified as k in 1/2^k)
GateZRtDag        . Gate ::= "ROOT_Z_DAG" Integer  ;                    -- Conjugate of Root of Pauli Z gate (root is specified as k in 1/2^k)
GateS             . Gate ::= "S"  ;                                     -- S gate: sqrt of Z
GateSDag          . Gate ::= "S_DAG"  ;                                 -- Conjugate of S gate
GateT             . Gate ::= "T"  ;                                     -- T Gate: sqrt of S
GateTDag          . Gate ::= "T_DAG"  ;                                 -- Conjugate of T gate
GateSqrtX         . Gate ::= "SQRT_X"  ;                                -- V gate: sqrt of X
GateSqrtXDag      . Gate ::= "SQRT_X_DAG"  ;                            -- Conjugate of V gate
GateSqrtY         . Gate ::= "SQRT_Y"  ;                                -- h gate: sqrt of Y
GateSqrtYDag      . Gate ::= "SQRT_Y_DAG"  ;                            -- Conjugate of h gate
GateRxTheta       . Gate ::= "RX" Angle  ;                              -- Single parametric rotation around X axis on the Bloch sphere
GateRyTheta       . Gate ::= "RY" Angle  ;                              -- Single parametric rotation around Y axis on the Bloch sphere
GateRzTheta       . Gate ::= "RZ" Angle  ;                              -- Single parametric rotation around Z axis on the Bloch sphere
GateU1            . Gate ::= "U1" Angle  ;                              -- One parametric generic gate
GateU2            . Gate ::= "U2" "(" Angle "," Angle ")"  ;            -- Two parametric generic gate
GateU3            . Gate ::= "U3" "(" Angle "," Angle "," Angle ")" ;   -- Thee parametric generic gate
GateSwp           . Gate ::= "SWAP"  ;                                  -- Swap gate
GateSqrtSwp       . Gate ::= "SQRT_SWAP"  ;                             -- sqrt of Swap gate
GateSqrtSwpDag    . Gate ::= "SQRT_SWAP_DAG"  ;                         -- Conjugate of root of Swap gate
GateISwp          . Gate ::= "ISWAP"  ;                                 -- ISwap gate
GateFSwp          . Gate ::= "FSWAP"  ;                                 -- FSwap gate
GateSwpTheta      . Gate ::= "SWAP_THETA" Angle ;                       -- Swap theta gate
GateSwpRt         . Gate ::= "ROOT_SWAP" Integer ;                      -- Root of Swap gate (root is specified as k in 1/2^k)
GateSwpRtDag      . Gate ::= "ROOT_SWAP_DAG" Integer  ;                 -- Conjugate of Root of Swap gate (root is specified as k in 1/2^k)

-- Names for Variables --
position token Var ((lower | '_') (letter | digit | '_' | '\'')*) ;

-- Declaring Control states --
CtrlBasisState . ControlBasisState ::= "[" BasisState  "]" ;
CtrlBasisStates . ControlBasisStates ::= "[" BasisState "," [BasisState] "]" ;
separator nonempty BasisState "," ;

CtrlBit . ControlBit   ::= "[" Integer "]" ;
CtrlBits . ControlBits ::= "[" Integer "," [Integer] "]" ;
separator nonempty Integer "," ;

-- Lambda token --
token Lambda '\\' ;

-- Declaring Tuples --
Tupl . Tuple ::= "(" Term "," [Term] ")" ;
-- Declaring Controls --
CtrlTerm . ControlTerm ::= "[" Term "]" ;
CtrlTerms . ControlTerms ::= "[" Term "," [Term] "]" ;
separator nonempty Term "," ;

-- Terms --
TermIfElse           . Term1 ::= "if" Term "then" Term "else" Term ;
TermLetSingle        . Term1 ::= "let" "{" LetVariable "=" Term "}" "in" Term ;
TermLetMultiple      . Term1 ::= "let" "{" "(" LetVariable "," [LetVariable] ")" "=" Term "}" "in" Term ;
TermLetSugarSingle   . Term1 ::=  LetVariable "<-" Term ";" Term ;
TermLetSugarMultiple . Term1 ::=  LetVariable "," [LetVariable] "<-" Term ";" Term ;
TermCase             . Term1 ::= "case" Term "of" CaseExpression [CaseExpression] ;
TermLambda           . Term1 ::= Lambda FunctionType "." Term ;
TermQuantumCtrlGate  . Term2 ::= "with" ControlTerm "ctrl" ControlBasisState ;
TermQuantumCtrlsGate . Term2 ::= "with" ControlTerms "ctrl" ControlBasisStates ;
TermClassicCtrlGate  . Term2 ::= "with" ControlTerm "ctrl" ControlBit ;
TermClassicCtrlsGate . Term2 ::= "with" ControlTerms "ctrl" ControlBits ;
TermApply            . Term2 ::= Term2 Term3 ;      -- left-associative  --
TermDollar           . Term1 ::= Term2 "$" Term1 ;  -- right-associative --
TermCompose          . Term2 ::= Term2 "." Term3 ;  -- left-associative  --
TermVariable         . Term3 ::= Var ;
TermBasisState       . Term3 ::= BasisState ;
TermGate             . Term3 ::= Gate ;
TermTuple            . Term3 ::= Tuple ;
TermUnit             . Term3 ::= "()" ;
coercions Term 3 ;

LetVar . LetVariable ::= Var ;
separator LetVariable "," ;

-- Case Expressions --
CaseExp . CaseExpression ::= Term "->" Var ;
separator nonempty CaseExpression " " ;

-- Function Arguments --
FunArg . Arg ::= Var ;
separator Arg " " ;

-- Function Definition --
FunDef . FunctionDefinition ::= Var [Arg] "=" Term ;
_      . FunctionDefinition ::= FunctionDefinition ";" ;   -- Semantic dummies: parser accepts extra semicolons

-- Type Definition --
FunType . FunctionType  ::= Var "::" Type ;
_       . FunctionType  ::= FunctionType ";" ;             -- Semantic dummies: parser accepts extra semicolons

-- Function Declaration --
FunDecl . FunctionDeclaration ::= FunctionType ";" FunctionDefinition ";" ;
separator FunctionDeclaration "" ;

-- Format for specifying comments --
comment "--" ; 
comment "{-" "-}" ;

and I am trying but failing to parse the next fragment of code:

balancedOracle' :: Qbit ** 3 -> Qbit ** 3
balancedOracle' qubits = q0, q1, q2 <- qubits;
                         (q0, q1, q2)

Oddly enough the next fragment of code is parsed correctly:

balancedOracle' :: Qbit ** 3 -> Qbit ** 3  
balancedOracle' qubits = q0, q1, q2 <- qubits;
                         ((q0), (q1), q2)

as:

Parse Successful!

[Abstract Syntax]

ProgDef [FunDecl (FunType (Var ((1,1),"balancedOracle'")) (TypeFunc (TypeExp TypeQbit 3) (TypeExp TypeQbit 3))) (FunDef (Var ((2,1),"balancedOracle'")) [FunArg (Var ((2,17),"qubits"))] (TermLetSugarMultiple (LetVar (Var ((2,26),"q0"))) [LetVar (Var ((2,30),"q1")),LetVar (Var ((2,34),"q2"))] (TermVariable (Var ((2,40),"qubits"))) (TermTuple (Tupl (TermVariable (Var ((3,28),"q0"))) [TermVariable (Var ((3,34),"q1")),TermVariable (Var ((3,39),"q2"))]))))]

[Linearized tree]

balancedOracle' :: Qbit ** 3 -> Qbit ** 3;
balancedOracle' qubits = q0, q1, q2 <- qubits;
(q0, q1, q2);

Perhaps this should be a good enough hint for some, but I just cannot figure where is the problem. Any hint on how to better approach this problem would be appreciated.

0

There are 0 best solutions below