From 6b377719c10d5ab3343fd5221f99a4a21008e25a Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Thu, 14 Mar 2024 08:26:58 +0100 Subject: Initial commit --- lib/configuration/expression_parser.mly | 185 ++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 lib/configuration/expression_parser.mly (limited to 'lib/configuration/expression_parser.mly') diff --git a/lib/configuration/expression_parser.mly b/lib/configuration/expression_parser.mly new file mode 100644 index 0000000..1304c4d --- /dev/null +++ b/lib/configuration/expression_parser.mly @@ -0,0 +1,185 @@ +%token IDENT +%token L_PAREN +%token R_PAREN +%token L_BRACKET R_BRACKET +%token COLUMN +%token DOT +%token LITERAL +%token INTEGER +%token COMA +%token EOF +%token CONCAT_OPERATOR + +%token BINARY_OPERATOR +%token INEQUALITY_OPERATOR +%token EQUALITY_OPERATOR +%token BOOL_OPERATOR + +%start path_expr +%start column_expr + +%right BOOL_OPERATOR +%right INEQUALITY_OPERATOR EQUALITY_OPERATOR +%right CONCAT_OPERATOR BINARY_OPERATOR + +%{ + + let function_of_name param f = + match (String.lowercase_ascii f, param) with + | "nvl", _ -> + ImportExpression.T.Nvl param + | "join", (ImportExpression.T.Literal sep:: tl) -> + ImportExpression.T.Join (sep, tl) + | "join", (ImportExpression.T.Empty:: tl) -> + ImportExpression.T.Join ("", tl) + | "upper", _ -> + ImportExpression.T.Function' (ImportExpression.T.Upper, param) + | "trim", _ -> + ImportExpression.T.Function' (ImportExpression.T.Trim, param) + | other, _ -> + ImportExpression.T.Function (other, param) + +%} + +%% + +path_expr: + | expr_(path_, EOF) EOF { $1 } + | EOF { ImportExpression.T.Empty } +column_expr: + | expr_(column_, EOF) EOF { $1 } + | EOF { ImportExpression.T.Empty } + + +path_: + | COLUMN + column = IDENT + { ImportExpression.T.Path + Syntax.Path.{ alias = None + ; column = ImportCSV.Csv.column_of_string column + } + } + + | COLUMN + table = IDENT + DOT + column = IDENT + { ImportExpression.T.Path + Syntax.Path.{ alias = Some table + ; column = ImportCSV.Csv.column_of_string column} + } + +column_: + | COLUMN + column = IDENT + { try ImportExpression.T.Path (ImportCSV.Csv.column_of_string column) + with _ -> ImportExpression.T.Literal column } + +arguments(PATH): + | L_PAREN + expr = separated_list(COMA, expr_(PATH, COMA)) + R_PAREN + { expr } + +group(PATH): + | L_BRACKET + expr = separated_list(COMA, expr_(PATH, COMA)) + R_BRACKET + { expr } + +fixed(PATH): + | d = INTEGER + { ImportExpression.T.Integer d } + | l = LITERAL + { + if String.equal String.empty l then + ImportExpression.T.Empty + else + ImportExpression.T.Literal l + } + +%inline boperator: + | e = BINARY_OPERATOR { e } + | e = INEQUALITY_OPERATOR { e } + | e = EQUALITY_OPERATOR { e } + | e = BOOL_OPERATOR { e } + +(* The expression evaluation receveive in parameters : + 1. the way to buidl a path, as we have two distinct ways to build them in + the case of externals (the external_key does not allow a table name) + 2. a phantom type telling wich kind of element will end the expression. + This can be EOF for the root expression, or COMA when inside a function. + This prevent merlin to optimize thoses two path, and allow more precise + error messages. *) +expr_(PATH, ENDING_PHANTOM): + | L_PAREN + e = expr_(PATH, R_PAREN) + R_PAREN + { ImportExpression.T.Expr e + } + | + p1 = expr_(PATH, ENDING_PHANTOM) + CONCAT_OPERATOR + p2 = expr_(PATH, COMA) + { match p2 with + | ImportExpression.T.Concat args -> ImportExpression.T.Concat (p1::args) + | _ -> ImportExpression.T.Concat (p1::p2::[]) + } + | p1 = expr_(PATH, ENDING_PHANTOM) + + op = boperator + p2 = expr_(PATH, COMA) + { ImportExpression.T.BOperator (op, p1, p2) } + + | p1 = expr_(PATH, ENDING_PHANTOM) + op = EQUALITY_OPERATOR + p2 = group(PATH) + { ImportExpression.T.GEquality(op, p1, p2) } + + + + | p = PATH + { p } + | f = fixed(PATH) + { f } + | s = IDENT + args = arguments(PATH) + { function_of_name args s } + | + s = IDENT + L_PAREN + opt_arg = opt_arg(PATH, COMA)? + args1 = group(PATH) + COMA + args2 = group(PATH) + R_PAREN + { let window_name = ImportExpression.T.window_of_name s opt_arg in + ImportExpression.T.Window (window_name, args1, args2) } +(* + | (* This case is here to describe a window function which has 2 arguments + level. + I’m not completely satisfied with it, as it prevent the ability to + create a exprpression block with parens arround. *) + s = IDENT + L_PAREN + opt_arg = opt_arg(PATH, COMA)? + args1 = arguments(PATH) + COMA + args2 = arguments(PATH) + R_PAREN + { let window_name = ImportExpression.T.window_of_name s opt_arg in + let expr = ImportExpression.T.Window (window_name, args1, args2) in + + let expr_repr = ImportExpression.Repr.repr ~top:true (fun _ -> "") + expr in + Printf.printf "Deprecated syntax in \"%s\" use [] instead of ()\n" expr_repr; + + + expr + } +*) + +opt_arg(PATH, SEP): + | expr = expr_(PATH, COMA) + SEP + { expr } -- cgit v1.2.3