-- | Parser for a PascaLigo contract. module AST.Pascaligo.Parser where import Data.Maybe (isJust) import AST.Skeleton import Duplo.Error import Duplo.Tree import Duplo.Pretty import Product import Parser import ParseTree -- import Debug.Trace -- example :: FilePath -- example = "../../../src/test/contracts/arithmetic.ligo" -- example = "../../../src/test/contracts/address.ligo" -- example = "../../../src/test/contracts/annotation.ligo" -- example = "../../../src/test/contracts/amount.ligo" -- example = "../../../src/test/contracts/attributes.ligo" -- example = "../../../src/test/contracts/application.ligo" -- example = "../../../src/test/contracts/assign.ligo" -- example = "../../../src/test/contracts/big_map.ligo" -- example = "../../../src/test/contracts/blockless.ligo" -- example = "../../../src/test/contracts/bad_timestamp.ligo" -- example = "../../../src/test/contracts/boolean_operators.ligo" -- example = "../../../src/test/contracts/bitwise_arithmetic.ligo" -- example = "../../../src/test/contracts/bad_type_operator.ligo" -- example = "../../../src/test/contracts/blocks.ligo" -- example = "../../../src/test/contracts/bytes_unpack.ligo" -- example = "../../../src/test/contracts/balance_constant.ligo" -- example = "../../../src/test/contracts/blockless.ligo" -- example = "../../../src/test/contracts/bytes_arithmetic.ligo" -- example = "../../../src/test/contracts/chain_id.ligo" -- example = "../../../src/test/contracts/closure-3.ligo" -- sample' :: FilePath -> IO (LIGO Info) -- sample' f -- = toParseTree (Path f) -- >>= runParserM . recognise -- >>= return . fst source' :: FilePath -> IO () source' f = toParseTree (Path f) >>= print . pp -- sample :: IO () -- sample -- = toParseTree (Path example) -- >>= runParserM . recognise -- >>= print . pp . fst -- source :: IO () -- source -- = toParseTree (Path example) -- >>= print . pp recognise :: RawTree -> ParserM (LIGO Info) recognise = descent (\_ -> error . show . pp) $ map usingScope [ -- Contract Descent do boilerplate \case "Start" -> RawContract <$> fields "declaration" _ -> fallthrough -- Expr , Descent do boilerplate \case "let_expr" -> Let <$> field "locals" <*> field "body" "fun_call" -> Apply <$> field "f" <*> fields "arguments" "par_call" -> Apply <$> field "f" <*> fields "arguments" "projection_call" -> Apply <$> field "f" <*> fields "arguments" "Some_call" -> Apply <$> field "constr" <*> fields "arguments" "constr_call" -> Apply <$> field "constr" <*> fields "arguments" "arguments" -> Tuple <$> fields "argument" "unop" -> UnOp <$> field "negate" <*> field "arg" "binop" -> BinOp <$> field "arg1" <*> field "op" <*> field "arg2" "block" -> Seq <$> fields "statement" "clause_block" -> Seq <$> fields "statement" "list_expr" -> List <$> fields "element" "annot_expr" -> Annot <$> field "subject" <*> field "type" "conditional" -> If <$> field "selector" <*> field "then" <*> fieldOpt "else" "cond_expr" -> If <$> field "selector" <*> field "then" <*> fieldOpt "else" "assignment" -> Assign <$> field "LHS" <*> field "RHS" "attr_decl" -> Attrs <$> fields "attribute" "record_expr" -> Record <$> fields "assignment" "big_map_injection" -> BigMap <$> fields "binding" "map_remove" -> MapRemove <$> field "key" <*> field "container" "tuple_expr" -> Tuple <$> fields "element" "skip" -> return Skip "case_expr" -> Case <$> field "subject" <*> fields "case" "case_instr" -> Case <$> field "subject" <*> fields "case" "fun_expr" -> Lambda <$> fields "parameters" <*> fieldOpt "type" <*> field "body" "for_cycle" -> ForLoop <$> field "name" <*> field "begin" <*> field "end" <*> fieldOpt "step" <*> field "body" "for_box" -> ForBox <$> field "key" <*> fieldOpt "value" <*> field "kind" <*> field "collection" <*> field "body" "while_loop" -> WhileLoop <$> field "breaker" <*> field "body" "map_injection" -> Map <$> fields "binding" "list_injection" -> List <$> fields "element" "set_expr" -> Set <$> fields "element" "map_patch" -> MapPatch <$> field "container" <*> fields "binding" "set_patch" -> SetPatch <$> field "container" <*> fields "key" "set_remove" -> SetRemove <$> field "key" <*> field "container" "update_record" -> RecordUpd <$> field "record" <*> fields "assignment" _ -> fallthrough -- Pattern , Descent do boilerplate \case "user_constr_pattern" -> IsConstr <$> field "constr" <*> fieldOpt "arguments" "tuple_pattern" -> IsTuple <$> fields "element" "nil" -> return $ IsList [] "list_pattern" -> IsList <$> fields "element" "cons_pattern" -> IsCons <$> field "head" <*> field "tail" _ -> fallthrough -- Alt , Descent do boilerplate \case "case_clause_expr" -> Alt <$> field "pattern" <*> field "body" "case_clause_instr" -> Alt <$> field "pattern" <*> field "body" _ -> fallthrough -- FieldAssignment , Descent do boilerplate \case "field_assignment" -> FieldAssignment <$> field "name" <*> field "_rhs" "field_path_assignment" -> FieldAssignment <$> field "lhs" <*> field "_rhs" _ -> fallthrough -- MapBinding , Descent do boilerplate \case "binding" -> MapBinding <$> field "key" <*> field "value" _ -> fallthrough , Descent do boilerplate' \case ("negate", op) -> return $ Op op ("adder", op) -> return $ Op op ("multiplier", op) -> return $ Op op ("comparison", op) -> return $ Op op ("^", _) -> return $ Op "^" ("#", _) -> return $ Op "#" _ -> fallthrough , Descent do boilerplate \case "data_projection" -> QualifiedName <$> field "struct" <*> fields "index" "map_lookup" -> QualifiedName <$> field "container" <*> fields "index" "module_field" -> QualifiedName <$> field "module" <*> fields "method" _ -> fallthrough -- Literal , Descent do boilerplate' \case ("Int", i) -> return $ Int i ("Nat", i) -> return $ Nat i ("Bytes", i) -> return $ Bytes i ("String", i) -> return $ String i ("Tez", i) -> return $ Tez i _ -> fallthrough -- Declaration , Descent do boilerplate \case "fun_decl" -> Function <$> flag "recursive" <*> field "name" <*> fields "parameters" <*> fieldOpt "type" <*> field "body" "const_decl" -> Const <$> field "name" <*> fieldOpt "type" <*> field "value" "var_decl" -> Var <$> field "name" <*> fieldOpt "type" <*> field "value" "type_decl" -> TypeDecl <$> field "typeName" <*> field "typeValue" "include" -> Include <$> field "filename" _ -> fallthrough -- Parameters , Descent do boilerplate \case "parameters" -> Parameters <$> fields "parameter" _ -> fallthrough -- VarDecl , Descent do boilerplate \case "param_decl" -> Decl <$> field "access" <*> field "name" <*> fieldOpt "type" _ -> fallthrough -- Mutable , Descent do boilerplate \case "const" -> return Immutable "var" -> return Mutable _ -> fallthrough -- Name , Descent do boilerplate' \case ("Name", n) -> return $ Name n ("and", _) -> return $ Name "and" ("or", _) -> return $ Name "or" _ -> fallthrough -- Type , Descent do boilerplate \case "fun_type" -> TArrow <$> field "domain" <*> field "codomain" "cartesian" -> TProduct <$> fields "element" "invokeBinary" -> TApply <$> field "typeConstr" <*> fields "arguments" "invokeUnary" -> TApply <$> field "typeConstr" <*> fields "arguments" "type_tuple" -> TTuple <$> fields "element" "record_type" -> TRecord <$> fields "field" "sum_type" -> TSum <$> fields "variant" "michelsonTypeOr" -> TOr <$> field "left_type" <*> field "left_type_name" <*> field "right_type" <*> field "right_type_name" "michelsonTypeAnd" -> TAnd <$> field "left_type" <*> field "left_type_name" <*> field "right_type" <*> field "right_type_name" _ -> fallthrough -- Variant , Descent do boilerplate \case "variant" -> Variant <$> field "constructor" <*> fieldOpt "arguments" _ -> fallthrough -- TField , Descent do boilerplate \case "field_decl" -> TField <$> field "fieldName" <*> field "fieldType" _ -> fallthrough -- TypeName , Descent do boilerplate' \case ("TypeName", name) -> return $ TypeName name ("list", _) -> return $ TypeName "list" ("big_map", _) -> return $ TypeName "big_map" ("map", _) -> return $ TypeName "map" ("set", _) -> return $ TypeName "set" ("option", _) -> return $ TypeName "option" ("contract", _) -> return $ TypeName "contract" _ -> fallthrough -- Ctor , Descent do boilerplate' \case ("Name_Capital", name) -> return $ Ctor name ("Some", _) -> return $ Ctor "Some" ("Some_pattern", _) -> return $ Ctor "Some" ("None", _) -> return $ Ctor "None" ("True", _) -> return $ Ctor "True" ("False", _) -> return $ Ctor "False" ("Unit", _) -> return $ Ctor "Unit" ("constr", n) -> return $ Ctor n _ -> fallthrough -- FieldName , Descent do boilerplate' \case ("FieldName", name) -> return $ FieldName name _ -> fallthrough -- Err , Descent do \(r :> _, ParseTree _ _ text') -> do withComments do return (r :> N :> Nil, Err text') , Descent do \case (r :> _, ParseTree "ERROR" _ text') -> do return ([] :> r :> Y :> Nil, Err text') _ -> fallthrough ]