source/parser/parserExpression.ml (363 lines of code) (raw):

(* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. *) open Core open Pyre module AstExpression = Ast.Expression module Node = Ast.Node module Identifier = Ast.Identifier module Substring = struct module Kind = struct type t = | Literal | RawFormat end type t = { kind: Kind.t; location: Ast.Location.t; value: string; } end module rec BooleanOperator : sig type t = { left: Expression.t; operator: AstExpression.BooleanOperator.operator; right: Expression.t; } end = struct type t = { left: Expression.t; operator: AstExpression.BooleanOperator.operator; right: Expression.t; } end and Call : sig module Argument : sig type t = { name: Identifier.t Node.t option; value: Expression.t; } end type t = { callee: Expression.t; arguments: Argument.t list; } end = struct module Argument = struct type t = { name: Identifier.t Node.t option; value: Expression.t; } end type t = { callee: Expression.t; arguments: Argument.t list; } end and ComparisonOperator : sig type t = { left: Expression.t; operator: AstExpression.ComparisonOperator.operator; right: Expression.t; } end = struct type t = { left: Expression.t; operator: AstExpression.ComparisonOperator.operator; right: Expression.t; } end and Comprehension : sig module Generator : sig type t = { target: Expression.t; iterator: Expression.t; conditions: Expression.t list; async: bool; } end type 'element t = { element: 'element; generators: Generator.t list; } end = struct module Generator = struct type t = { target: Expression.t; iterator: Expression.t; conditions: Expression.t list; async: bool; } end type 'element t = { element: 'element; generators: Generator.t list; } end and Dictionary : sig module Entry : sig type t = { key: Expression.t; value: Expression.t; } end type t = { entries: Entry.t list; keywords: Expression.t list; } end = struct module Entry = struct type t = { key: Expression.t; value: Expression.t; } end type t = { entries: Entry.t list; keywords: Expression.t list; } end and Lambda : sig type t = { parameters: Parameter.t list; body: Expression.t; } end = struct type t = { parameters: Parameter.t list; body: Expression.t; } end and Name : sig module Attribute : sig type t = { base: Expression.t; attribute: Identifier.t; special: bool; } end type t = | Attribute of Attribute.t | Identifier of Identifier.t end = struct module Attribute = struct type t = { base: Expression.t; attribute: Identifier.t; special: bool; } end type t = | Attribute of Attribute.t | Identifier of Identifier.t end and Parameter : sig type parameter = { name: Identifier.t; value: Expression.t option; annotation: Expression.t option; } type t = parameter Node.t end = struct type parameter = { name: Identifier.t; value: Expression.t option; annotation: Expression.t option; } type t = parameter Node.t end and Starred : sig type t = | Once of Expression.t | Twice of Expression.t end = struct type t = | Once of Expression.t | Twice of Expression.t end and Ternary : sig type t = { target: Expression.t; test: Expression.t; alternative: Expression.t; } end = struct type t = { target: Expression.t; test: Expression.t; alternative: Expression.t; } end and UnaryOperator : sig type t = { operator: AstExpression.UnaryOperator.operator; operand: Expression.t; } end = struct type t = { operator: AstExpression.UnaryOperator.operator; operand: Expression.t; } end and WalrusOperator : sig type t = { target: Expression.t; value: Expression.t; } end = struct type t = { target: Expression.t; value: Expression.t; } end and Expression : sig type expression = | Await of t | BooleanOperator of BooleanOperator.t | Call of Call.t | ComparisonOperator of ComparisonOperator.t | Constant of AstExpression.Constant.t | Dictionary of Dictionary.t | DictionaryComprehension of Dictionary.Entry.t Comprehension.t | Generator of t Comprehension.t | FormatString of Substring.t list | Lambda of Lambda.t | List of t list | ListComprehension of t Comprehension.t | Name of Name.t | Parenthesis of t | Set of t list | SetComprehension of t Comprehension.t | Starred of Starred.t | Ternary of Ternary.t | Tuple of t list | UnaryOperator of UnaryOperator.t | WalrusOperator of WalrusOperator.t | Yield of t option | YieldFrom of t and t = expression Node.t end = struct type expression = | Await of t | BooleanOperator of BooleanOperator.t | Call of Call.t | ComparisonOperator of ComparisonOperator.t | Constant of AstExpression.Constant.t | Dictionary of Dictionary.t | DictionaryComprehension of Dictionary.Entry.t Comprehension.t | Generator of t Comprehension.t | FormatString of Substring.t list | Lambda of Lambda.t | List of t list | ListComprehension of t Comprehension.t | Name of Name.t | Parenthesis of t | Set of t list | SetComprehension of t Comprehension.t | Starred of Starred.t | Ternary of Ternary.t | Tuple of t list | UnaryOperator of UnaryOperator.t | WalrusOperator of WalrusOperator.t | Yield of t option | YieldFrom of t and t = expression Node.t end let rec convert { Node.location; value } = let convert_entry { Dictionary.Entry.key; value } = { AstExpression.Dictionary.Entry.key = convert key; value = convert value } in let convert_generator { Comprehension.Generator.target; iterator; conditions; async } = { AstExpression.Comprehension.Generator.target = convert target; iterator = convert iterator; conditions = List.map ~f:convert conditions; async; } in match value with | Expression.Await expression -> AstExpression.Expression.Await (convert expression) |> Node.create ~location | BooleanOperator { left; operator; right } -> AstExpression.Expression.BooleanOperator { left = convert left; operator; right = convert right } |> Node.create ~location | Call { callee; arguments } -> AstExpression.Expression.Call { callee = convert callee; arguments = List.map ~f:convert_argument arguments } |> Node.create ~location | ComparisonOperator { left; operator; right } -> AstExpression.Expression.ComparisonOperator { left = convert left; operator; right = convert right } |> Node.create ~location | Constant value -> AstExpression.Expression.Constant value |> Node.create ~location | Dictionary { Dictionary.entries; keywords } -> AstExpression.Expression.Dictionary { entries = List.map ~f:convert_entry entries; keywords = List.map ~f:convert keywords } |> Node.create ~location | DictionaryComprehension { Comprehension.element; generators } -> AstExpression.Expression.DictionaryComprehension { element = convert_entry element; generators = List.map ~f:convert_generator generators } |> Node.create ~location | Generator { Comprehension.element; generators } -> AstExpression.Expression.Generator { element = convert element; generators = List.map ~f:convert_generator generators } |> Node.create ~location | FormatString substrings -> let convert_substring { Substring.value; location; _ } = (* FIXME: The legacy parser no longer has the capability of parsing expressions in fstrings. *) AstExpression.Substring.Literal (Node.create ~location value) in AstExpression.Expression.FormatString (List.map substrings ~f:convert_substring) |> Node.create ~location | Lambda { Lambda.parameters; body } -> AstExpression.Expression.Lambda { parameters = List.map ~f:convert_parameter parameters; body = convert body } |> Node.create ~location | List expression_list -> AstExpression.Expression.List (List.map ~f:convert expression_list) |> Node.create ~location | ListComprehension { Comprehension.element; generators } -> AstExpression.Expression.ListComprehension { element = convert element; generators = List.map ~f:convert_generator generators } |> Node.create ~location | Name (Name.Attribute { base; attribute; special }) -> AstExpression.Expression.Name (AstExpression.Name.Attribute { base = convert base; attribute; special }) |> Node.create ~location | Name (Name.Identifier name) -> AstExpression.Expression.Name (AstExpression.Name.Identifier name) |> Node.create ~location | Parenthesis expression -> convert expression | Set expression_list -> AstExpression.Expression.Set (List.map ~f:convert expression_list) |> Node.create ~location | SetComprehension { Comprehension.element; generators } -> AstExpression.Expression.SetComprehension { element = convert element; generators = List.map ~f:convert_generator generators } |> Node.create ~location | Starred (Once expression) -> AstExpression.Expression.Starred (Once (convert expression)) |> Node.create ~location | Starred (Twice expression) -> AstExpression.Expression.Starred (Twice (convert expression)) |> Node.create ~location | Ternary { target; test; alternative } -> AstExpression.Expression.Ternary { target = convert target; test = convert test; alternative = convert alternative } |> Node.create ~location | Tuple expression_list -> AstExpression.Expression.Tuple (List.map ~f:convert expression_list) |> Node.create ~location | UnaryOperator { UnaryOperator.operator; operand } -> AstExpression.Expression.UnaryOperator { operator; operand = convert operand } |> Node.create ~location | WalrusOperator { target; value } -> AstExpression.Expression.WalrusOperator { target = convert target; value = convert value } |> Node.create ~location | Yield expression -> AstExpression.Expression.Yield (expression >>| convert) |> Node.create ~location | YieldFrom expression -> AstExpression.Expression.YieldFrom (expression |> convert) |> Node.create ~location and convert_argument { Call.Argument.name; value } = { AstExpression.Call.Argument.name; value = convert value } and convert_parameter { Node.location; value = { Parameter.name; value; annotation } } = { AstExpression.Parameter.name; value = value >>| convert; annotation = annotation >>| convert } |> Node.create ~location