aboutsummaryrefslogtreecommitdiff
path: root/lib/configuration/expression_parser.mly
diff options
context:
space:
mode:
Diffstat (limited to 'lib/configuration/expression_parser.mly')
-rw-r--r--lib/configuration/expression_parser.mly185
1 files changed, 185 insertions, 0 deletions
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 <string>IDENT
+%token L_PAREN
+%token R_PAREN
+%token L_BRACKET R_BRACKET
+%token COLUMN
+%token DOT
+%token <string>LITERAL
+%token <string>INTEGER
+%token COMA
+%token EOF
+%token CONCAT_OPERATOR
+
+%token <ImportExpression.T.binary_operator>BINARY_OPERATOR
+%token <ImportExpression.T.binary_operator>INEQUALITY_OPERATOR
+%token <ImportExpression.T.binary_operator>EQUALITY_OPERATOR
+%token <ImportExpression.T.binary_operator>BOOL_OPERATOR
+
+%start <ImportDataTypes.Path.t ImportExpression.T.t> path_expr
+%start <ImportDataTypes.Path.column ImportExpression.T.t> 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 }