diff --git a/src/Language/SystemVerilog/AST/Stmt.hs b/src/Language/SystemVerilog/AST/Stmt.hs index 90b0dec..83e68bb 100644 --- a/src/Language/SystemVerilog/AST/Stmt.hs +++ b/src/Language/SystemVerilog/AST/Stmt.hs @@ -12,8 +12,7 @@ module Language.SystemVerilog.AST.Stmt , CaseKW (..) , Case , ActionBlock (..) - , PropertyExpr (..) - , PESPBinOp (..) + , PropExpr (..) , SeqMatchItem , SeqExpr (..) , AssertionItem @@ -144,24 +143,21 @@ instance Show ActionBlock where show (ActionBlockElse Nothing s ) = printf " else %s" (show s) show (ActionBlockElse (Just s1) s2) = printf " %s else %s" (show s1) (show s2) -data PropertyExpr - = PESE SeqExpr - | PESPBinOp SeqExpr PESPBinOp PropertyExpr +data PropExpr + = PropExpr SeqExpr + | PropExprImpliesO SeqExpr PropExpr + | PropExprImpliesNO SeqExpr PropExpr + | PropExprFollowsO SeqExpr PropExpr + | PropExprFollowsNO SeqExpr PropExpr + | PropExprIff PropExpr PropExpr deriving Eq -instance Show PropertyExpr where - show (PESE se) = show se - show (PESPBinOp a o b) = printf "(%s %s %s)" (show a) (show o) (show b) -data PESPBinOp - = ImpliesO - | ImpliesNO - | FollowedByO - | FollowedByNO - deriving (Eq, Ord) -instance Show PESPBinOp where - show ImpliesO = "|->" - show ImpliesNO = "|=>" - show FollowedByO = "#-#" - show FollowedByNO = "#=#" +instance Show PropExpr where + show (PropExpr se) = show se + show (PropExprImpliesO a b) = printf "(%s |-> %s)" (show a) (show b) + show (PropExprImpliesNO a b) = printf "(%s |=> %s)" (show a) (show b) + show (PropExprFollowsO a b) = printf "(%s #-# %s)" (show a) (show b) + show (PropExprFollowsNO a b) = printf "(%s #=# %s)" (show a) (show b) + show (PropExprIff a b) = printf "(%s and %s)" (show a) (show b) type SeqMatchItem = Either (LHS, AsgnOp, Expr) (Identifier, Args) data SeqExpr = SeqExpr Expr @@ -195,7 +191,7 @@ instance Show Assertion where printf "assert property (%s)%s" (show p) (show a) data PropertySpec - = PropertySpec (Maybe Sense) (Maybe Expr) PropertyExpr + = PropertySpec (Maybe Sense) (Maybe Expr) PropExpr deriving Eq instance Show PropertySpec where show (PropertySpec ms me pe) = diff --git a/src/Language/SystemVerilog/Parser/Lex.x b/src/Language/SystemVerilog/Parser/Lex.x index df0107c..f2d05bd 100644 --- a/src/Language/SystemVerilog/Parser/Lex.x +++ b/src/Language/SystemVerilog/Parser/Lex.x @@ -14,17 +14,19 @@ - Trying to thread the IO Monad through alex's interface would be very - convoluted. The operations performed are not effectful, and are type safe. -} + {-# OPTIONS_GHC -fno-warn-unused-imports #-} -- The above pragma gets rid of annoying warning caused by alex 3.2.4. This has -- been fixed on their development branch, so this can be removed once they roll -- a new release. (no new release as of 3/29/2018) + module Language.SystemVerilog.Parser.Lex (lexFile) where import System.FilePath (dropFileName) import System.Directory (findFile) import System.IO.Unsafe (unsafePerformIO) import qualified Data.Map.Strict as Map -import Data.List (span, elemIndex, isPrefixOf, dropWhileEnd) +import Data.List (span, elemIndex, dropWhileEnd) import Data.Maybe (isJust, fromJust) import Language.SystemVerilog.Parser.Tokens diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index cf70c30..db27c48 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -1,3 +1,11 @@ +{- sv2v + - Author: Zachary Snow + - Original Parser Author: Tom Hawkins + - + - This file has been *heavily* modified and extended from the original version + - in tomahawkins/verilog. I have added support for numerous SystemVerilog + - constructs, which has necessitated rewriting nearly all of this. + -} { module Language.SystemVerilog.Parser.Parse (descriptions) where @@ -204,7 +212,6 @@ string { Token Lit_string _ _ } "<<<=" { Token Sym_lt_lt_lt_eq _ _ } ">>>=" { Token Sym_gt_gt_gt_eq _ _ } -directive { Token Spe_Directive _ _ } -- operator precedences, from *lowest* to *highest* %nonassoc NoElse @@ -233,7 +240,6 @@ directive { Token Spe_Directive _ _ } %right REDUCE_OP "!" "~" "++" "--" %left "(" ")" "[" "]" "." "'" - %% opt(p) :: { Maybe a } @@ -249,15 +255,12 @@ Description :: { Description } : Part(ModuleKW , "endmodule" ) { $1 } | Part(InterfaceKW, "endinterface") { $1 } | PackageItem { PackageItem $1 } - | Directive { Directive $1 } - -Directive :: { String } - : directive { tokenString $1 } Type :: { Type } - : PartialType Dimensions { $1 Unspecified $2 } - | PartialType Signing Dimensions { $1 $2 $3 } - | Identifier Dimensions { Alias $1 $2 } + : TypeNonIdent { $1 } + | Identifier Dimensions { Alias $1 $2 } +TypeNonIdent :: { Type } + : PartialType OptSigning Dimensions { $1 $2 $3 } PartialType :: { Signing -> [Range] -> Type } : NetType { \Unspecified -> Net $1 } | IntegerVectorType { IntegerVector $1 } @@ -265,10 +268,6 @@ PartialType :: { Signing -> [Range] -> Type } | NonIntegerType { \Unspecified -> \[] -> NonInteger $1 } | "enum" opt(Type) "{" EnumItems "}" { \Unspecified -> Enum $2 $4 } | "struct" Packing "{" StructItems "}" { \Unspecified -> Struct $2 $4 } -TypeNonIdent :: { Type } - : PartialType Dimensions { $1 Unspecified $2 } - | PartialType Signing Dimensions { $1 $2 $3 } - CastingType :: { Type } : IntegerVectorType { IntegerVector $1 Unspecified [] } | IntegerAtomType { IntegerAtom $1 Unspecified } @@ -276,8 +275,11 @@ CastingType :: { Type } | Signing { Implicit $1 [] } Signing :: { Signing } - : "signed" { Signed } + : "signed" { Signed } | "unsigned" { Unsigned } +OptSigning :: { Signing } + : Signing { $1 } + | {- empty -} { Unspecified } NetType :: { NetType } : "supply0" { TSupply0 } @@ -318,9 +320,8 @@ StructItem :: { [(Type, Identifier)] } : Type Identifiers ";" { map (\a -> ($1, a)) $2 } Packing :: { Packing } - : "packed" Signing { Packed $2 } - | "packed" { Packed Unspecified } - | {- empty -} { Unpacked } + : "packed" OptSigning { Packed $2 } + | {- empty -} { Unpacked } Part(begin, end) :: { Description } : begin opt(Lifetime) Identifier Params PortDecls ";" ModuleItems end opt(Tag) { Part False $1 $2 $3 (fst $5) ($4 ++ (snd $5) ++ $7) } @@ -464,20 +465,17 @@ SimpleImmediateAssertionStatement :: { Assertion } -- TODO: Add support for assume and cover PropertySpec :: { PropertySpec } - : opt(ClockingEvent) "disable" "iff" "(" Expr ")" PropertyExpr { PropertySpec $1 (Just $5) $7 } - | opt(ClockingEvent) PropertyExpr { PropertySpec $1 (Nothing) $2 } + : opt(ClockingEvent) "disable" "iff" "(" Expr ")" PropExpr { PropertySpec $1 (Just $5) $7 } + | opt(ClockingEvent) PropExpr { PropertySpec $1 (Nothing) $2 } --- TODO: This is pretty incomplete! -PropertyExpr :: { PropertyExpr } - : SeqExpr { PESE $1 } - | SeqExpr PESPBinOp PropertyExpr { PESPBinOp $1 $2 $3 } - -- | "(" PropertyExpr ")" { [] } - -PESPBinOp :: { PESPBinOp } - : "|->" { ImpliesO } - | "|=>" { ImpliesNO } - | "#-#" { FollowedByO } - | "#=#" { FollowedByNO } +PropExpr :: { PropExpr } + : SeqExpr { PropExpr $1 } + | SeqExpr "|->" PropExpr { PropExprImpliesO $1 $3 } + | SeqExpr "|=>" PropExpr { PropExprImpliesNO $1 $3 } + | SeqExpr "#-#" PropExpr { PropExprFollowsO $1 $3 } + | SeqExpr "#=#" PropExpr { PropExprFollowsNO $1 $3 } + | PropExpr "iff" PropExpr { PropExprIff $1 $3 } + -- | "(" PropExpr ")" { $2 } SeqExpr :: { SeqExpr } : Expr { SeqExpr $1 } @@ -572,8 +570,7 @@ TFItems :: { [Decl] } | ";" { [] } ParamType :: { Type } - : PartialType Dimensions { $1 Unspecified $2 } - | PartialType Signing Dimensions { $1 $2 $3 } + : PartialType OptSigning Dimensions { $1 $2 $3 } | DimensionsNonEmpty { Implicit Unspecified $1 } | Signing Dimensions { Implicit $1 $2 } @@ -853,7 +850,6 @@ GenItem :: { GenItem } | GenBlock { uncurry GenBlock $1 } | "case" "(" Expr ")" GenCases opt(GenCaseDefault) "endcase" { GenCase $3 $5 $6 } | "for" "(" Identifier "=" Expr ";" Expr ";" GenvarIteration ")" GenBlock { (uncurry $ GenFor ($3, $5) $7 $9) $11 } - -- TODO: We should restrict it to the module items that are actually allowed. | ModuleItem { genItemsToGenItem $ map GenModuleItem $1 } GenBlock :: { (Maybe Identifier, [GenItem]) } diff --git a/src/Language/SystemVerilog/Parser/Tokens.hs b/src/Language/SystemVerilog/Parser/Tokens.hs index e27307d..de3c50e 100644 --- a/src/Language/SystemVerilog/Parser/Tokens.hs +++ b/src/Language/SystemVerilog/Parser/Tokens.hs @@ -1,343 +1,353 @@ +{- sv2v + - Author: Tom Hawkins + - Modified by: Zachary Snow + - + - This file is largely the same as when we forked from tomahawkins/verilog. Of + - course, some additional token names have been added. + -} module Language.SystemVerilog.Parser.Tokens - ( Token (..) - , TokenName (..) - , Position (..) - , tokenString - ) where + ( Token (..) + , TokenName (..) + , Position (..) + , tokenString + ) where import Text.Printf tokenString :: Token -> String tokenString (Token _ s _) = s -data Position = Position String Int Int deriving Eq +data Position + = Position String Int Int + deriving Eq instance Show Position where - show (Position f l c) = printf "%s:%d:%d" f l c + show (Position f l c) = printf "%s:%d:%d" f l c -data Token = Token TokenName String Position deriving (Show, Eq) +data Token + = Token TokenName String Position + deriving (Show, Eq) data TokenName - = KW_alias - | KW_always - | KW_always_comb - | KW_always_ff - | KW_always_latch - | KW_and - | KW_assert - | KW_assign - | KW_assume - | KW_automatic - | KW_before - | KW_begin - | KW_bind - | KW_bins - | KW_binsof - | KW_bit - | KW_break - | KW_buf - | KW_bufif0 - | KW_bufif1 - | KW_byte - | KW_case - | KW_casex - | KW_casez - | KW_cell - | KW_chandle - | KW_class - | KW_clocking - | KW_cmos - | KW_config - | KW_const - | KW_constraint - | KW_context - | KW_continue - | KW_cover - | KW_covergroup - | KW_coverpoint - | KW_cross - | KW_deassign - | KW_default - | KW_defparam - | KW_design - | KW_disable - | KW_dist - | KW_do - | KW_dollar_bits - | KW_edge - | KW_else - | KW_end - | KW_endcase - | KW_endclass - | KW_endclocking - | KW_endconfig - | KW_endfunction - | KW_endgenerate - | KW_endgroup - | KW_endinterface - | KW_endmodule - | KW_endpackage - | KW_endprimitive - | KW_endprogram - | KW_endproperty - | KW_endspecify - | KW_endsequence - | KW_endtable - | KW_endtask - | KW_enum - | KW_event - | KW_expect - | KW_export - | KW_extends - | KW_extern - | KW_final - | KW_first_match - | KW_for - | KW_force - | KW_foreach - | KW_forever - | KW_fork - | KW_forkjoin - | KW_function - | KW_function_prototype - | KW_generate - | KW_genvar - | KW_highz0 - | KW_highz1 - | KW_if - | KW_iff - | KW_ifnone - | KW_ignore_bins - | KW_illegal_bins - | KW_import - | KW_incdir - | KW_include - | KW_initial - | KW_inout - | KW_input - | KW_inside - | KW_instance - | KW_int - | KW_integer - | KW_interface - | KW_intersect - | KW_join - | KW_join_any - | KW_join_none - | KW_large - | KW_liblist - | KW_library - | KW_local - | KW_localparam - | KW_logic - | KW_longint - | KW_macromodule - | KW_matches - | KW_medium - | KW_modport - | KW_module - | KW_nand - | KW_negedge - | KW_new - | KW_nmos - | KW_nor - | KW_noshowcancelled - | KW_not - | KW_notif0 - | KW_notif1 - | KW_null - | KW_option - | KW_or - | KW_output - | KW_package - | KW_packed - | KW_parameter - | KW_pathpulse_dollar - | KW_pmos - | KW_posedge - | KW_primitive - | KW_priority - | KW_program - | KW_property - | KW_protected - | KW_pull0 - | KW_pull1 - | KW_pulldown - | KW_pullup - | KW_pulsestyle_onevent - | KW_pulsestyle_ondetect - | KW_pure - | KW_rand - | KW_randc - | KW_randcase - | KW_randsequence - | KW_rcmos - | KW_real - | KW_realtime - | KW_ref - | KW_reg - | KW_release - | KW_repeat - | KW_return - | KW_rnmos - | KW_rpmos - | KW_rtran - | KW_rtranif0 - | KW_rtranif1 - | KW_scalared - | KW_sequence - | KW_shortint - | KW_shortreal - | KW_showcancelled - | KW_signed - | KW_small - | KW_solve - | KW_specify - | KW_specparam - | KW_static - | KW_strength0 - | KW_strength1 - | KW_string - | KW_strong0 - | KW_strong1 - | KW_struct - | KW_super - | KW_supply0 - | KW_supply1 - | KW_table - | KW_tagged - | KW_task - | KW_this - | KW_throughout - | KW_time - | KW_timeprecision - | KW_timeunit - | KW_tran - | KW_tranif0 - | KW_tranif1 - | KW_tri - | KW_tri0 - | KW_tri1 - | KW_triand - | KW_trior - | KW_trireg - | KW_type - | KW_typedef - | KW_type_option - | KW_union - | KW_unique - | KW_unique0 - | KW_unsigned - | KW_use - | KW_uwire - | KW_var - | KW_vectored - | KW_virtual - | KW_void - | KW_wait - | KW_wait_order - | KW_wand - | KW_weak0 - | KW_weak1 - | KW_while - | KW_wildcard - | KW_wire - | KW_with - | KW_within - | KW_wor - | KW_xnor - | KW_xor - | Id_simple - | Id_escaped - | Id_system - | Lit_number_unsigned - | Lit_number - | Lit_string - | Sym_paren_l - | Sym_paren_r - | Sym_brack_l - | Sym_brack_r - | Sym_brace_l - | Sym_brace_r - | Sym_tildy - | Sym_bang - | Sym_at - | Sym_pound - | Sym_percent - | Sym_hat - | Sym_amp - | Sym_bar - | Sym_aster - | Sym_dot - | Sym_comma - | Sym_colon - | Sym_semi - | Sym_eq - | Sym_lt - | Sym_gt - | Sym_plus - | Sym_dash - | Sym_question - | Sym_slash - | Sym_dollar - | Sym_s_quote - | Sym_tildy_amp - | Sym_tildy_bar - | Sym_tildy_hat - | Sym_hat_tildy - | Sym_eq_eq - | Sym_bang_eq - | Sym_amp_amp - | Sym_bar_bar - | Sym_aster_aster - | Sym_lt_eq - | Sym_gt_eq - | Sym_gt_gt - | Sym_lt_lt - | Sym_plus_plus - | Sym_dash_dash - | Sym_plus_eq - | Sym_dash_eq - | Sym_aster_eq - | Sym_slash_eq - | Sym_percent_eq - | Sym_amp_eq - | Sym_bar_eq - | Sym_hat_eq - | Sym_plus_colon - | Sym_dash_colon - | Sym_colon_colon - | Sym_dot_aster - | Sym_dash_gt - | Sym_colon_eq - | Sym_colon_slash - | Sym_pound_pound - | Sym_brack_l_aster - | Sym_brack_l_eq - | Sym_eq_gt - | Sym_at_aster - | Sym_paren_l_aster - | Sym_aster_paren_r - | Sym_aster_gt - | Sym_eq_eq_eq - | Sym_bang_eq_eq - | Sym_eq_eq_question - | Sym_bang_eq_question - | Sym_gt_gt_gt - | Sym_lt_lt_lt - | Sym_lt_lt_eq - | Sym_gt_gt_eq - | Sym_bar_dash_gt - | Sym_bar_eq_gt - | Sym_pound_dash_pound - | Sym_pound_eq_pound - | Sym_brack_l_dash_gt - | Sym_at_at_paren_l - | Sym_paren_l_aster_paren_r - | Sym_dash_gt_gt - | Sym_amp_amp_amp - | Sym_lt_lt_lt_eq - | Sym_gt_gt_gt_eq - | Spe_Directive - | Unknown - deriving (Show, Eq) + = KW_alias + | KW_always + | KW_always_comb + | KW_always_ff + | KW_always_latch + | KW_and + | KW_assert + | KW_assign + | KW_assume + | KW_automatic + | KW_before + | KW_begin + | KW_bind + | KW_bins + | KW_binsof + | KW_bit + | KW_break + | KW_buf + | KW_bufif0 + | KW_bufif1 + | KW_byte + | KW_case + | KW_casex + | KW_casez + | KW_cell + | KW_chandle + | KW_class + | KW_clocking + | KW_cmos + | KW_config + | KW_const + | KW_constraint + | KW_context + | KW_continue + | KW_cover + | KW_covergroup + | KW_coverpoint + | KW_cross + | KW_deassign + | KW_default + | KW_defparam + | KW_design + | KW_disable + | KW_dist + | KW_do + | KW_dollar_bits + | KW_edge + | KW_else + | KW_end + | KW_endcase + | KW_endclass + | KW_endclocking + | KW_endconfig + | KW_endfunction + | KW_endgenerate + | KW_endgroup + | KW_endinterface + | KW_endmodule + | KW_endpackage + | KW_endprimitive + | KW_endprogram + | KW_endproperty + | KW_endspecify + | KW_endsequence + | KW_endtable + | KW_endtask + | KW_enum + | KW_event + | KW_expect + | KW_export + | KW_extends + | KW_extern + | KW_final + | KW_first_match + | KW_for + | KW_force + | KW_foreach + | KW_forever + | KW_fork + | KW_forkjoin + | KW_function + | KW_function_prototype + | KW_generate + | KW_genvar + | KW_highz0 + | KW_highz1 + | KW_if + | KW_iff + | KW_ifnone + | KW_ignore_bins + | KW_illegal_bins + | KW_import + | KW_incdir + | KW_include + | KW_initial + | KW_inout + | KW_input + | KW_inside + | KW_instance + | KW_int + | KW_integer + | KW_interface + | KW_intersect + | KW_join + | KW_join_any + | KW_join_none + | KW_large + | KW_liblist + | KW_library + | KW_local + | KW_localparam + | KW_logic + | KW_longint + | KW_macromodule + | KW_matches + | KW_medium + | KW_modport + | KW_module + | KW_nand + | KW_negedge + | KW_new + | KW_nmos + | KW_nor + | KW_noshowcancelled + | KW_not + | KW_notif0 + | KW_notif1 + | KW_null + | KW_option + | KW_or + | KW_output + | KW_package + | KW_packed + | KW_parameter + | KW_pathpulse_dollar + | KW_pmos + | KW_posedge + | KW_primitive + | KW_priority + | KW_program + | KW_property + | KW_protected + | KW_pull0 + | KW_pull1 + | KW_pulldown + | KW_pullup + | KW_pulsestyle_onevent + | KW_pulsestyle_ondetect + | KW_pure + | KW_rand + | KW_randc + | KW_randcase + | KW_randsequence + | KW_rcmos + | KW_real + | KW_realtime + | KW_ref + | KW_reg + | KW_release + | KW_repeat + | KW_return + | KW_rnmos + | KW_rpmos + | KW_rtran + | KW_rtranif0 + | KW_rtranif1 + | KW_scalared + | KW_sequence + | KW_shortint + | KW_shortreal + | KW_showcancelled + | KW_signed + | KW_small + | KW_solve + | KW_specify + | KW_specparam + | KW_static + | KW_strength0 + | KW_strength1 + | KW_string + | KW_strong0 + | KW_strong1 + | KW_struct + | KW_super + | KW_supply0 + | KW_supply1 + | KW_table + | KW_tagged + | KW_task + | KW_this + | KW_throughout + | KW_time + | KW_timeprecision + | KW_timeunit + | KW_tran + | KW_tranif0 + | KW_tranif1 + | KW_tri + | KW_tri0 + | KW_tri1 + | KW_triand + | KW_trior + | KW_trireg + | KW_type + | KW_typedef + | KW_type_option + | KW_union + | KW_unique + | KW_unique0 + | KW_unsigned + | KW_use + | KW_uwire + | KW_var + | KW_vectored + | KW_virtual + | KW_void + | KW_wait + | KW_wait_order + | KW_wand + | KW_weak0 + | KW_weak1 + | KW_while + | KW_wildcard + | KW_wire + | KW_with + | KW_within + | KW_wor + | KW_xnor + | KW_xor + | Id_simple + | Id_escaped + | Id_system + | Lit_number_unsigned + | Lit_number + | Lit_string + | Sym_paren_l + | Sym_paren_r + | Sym_brack_l + | Sym_brack_r + | Sym_brace_l + | Sym_brace_r + | Sym_tildy + | Sym_bang + | Sym_at + | Sym_pound + | Sym_percent + | Sym_hat + | Sym_amp + | Sym_bar + | Sym_aster + | Sym_dot + | Sym_comma + | Sym_colon + | Sym_semi + | Sym_eq + | Sym_lt + | Sym_gt + | Sym_plus + | Sym_dash + | Sym_question + | Sym_slash + | Sym_dollar + | Sym_s_quote + | Sym_tildy_amp + | Sym_tildy_bar + | Sym_tildy_hat + | Sym_hat_tildy + | Sym_eq_eq + | Sym_bang_eq + | Sym_amp_amp + | Sym_bar_bar + | Sym_aster_aster + | Sym_lt_eq + | Sym_gt_eq + | Sym_gt_gt + | Sym_lt_lt + | Sym_plus_plus + | Sym_dash_dash + | Sym_plus_eq + | Sym_dash_eq + | Sym_aster_eq + | Sym_slash_eq + | Sym_percent_eq + | Sym_amp_eq + | Sym_bar_eq + | Sym_hat_eq + | Sym_plus_colon + | Sym_dash_colon + | Sym_colon_colon + | Sym_dot_aster + | Sym_dash_gt + | Sym_colon_eq + | Sym_colon_slash + | Sym_pound_pound + | Sym_brack_l_aster + | Sym_brack_l_eq + | Sym_eq_gt + | Sym_at_aster + | Sym_paren_l_aster + | Sym_aster_paren_r + | Sym_aster_gt + | Sym_eq_eq_eq + | Sym_bang_eq_eq + | Sym_eq_eq_question + | Sym_bang_eq_question + | Sym_gt_gt_gt + | Sym_lt_lt_lt + | Sym_lt_lt_eq + | Sym_gt_gt_eq + | Sym_bar_dash_gt + | Sym_bar_eq_gt + | Sym_pound_dash_pound + | Sym_pound_eq_pound + | Sym_brack_l_dash_gt + | Sym_at_at_paren_l + | Sym_paren_l_aster_paren_r + | Sym_dash_gt_gt + | Sym_amp_amp_amp + | Sym_lt_lt_lt_eq + | Sym_gt_gt_gt_eq + | Unknown + deriving (Show, Eq)