(* This file is part of licht. licht is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. licht is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with licht. If not, see . *) %{ open ScTypes open ScTypes.Result module S = Symbols let u = UTF8.from_utf8string let extractColumnNameFromNum (fixed, (str, value)) = (fixed, value) let build_call ident = function | [] -> Expr.call0 ident | [p1] -> Expr.call1 ident p1 | [p1;p2] -> Expr.call2 ident p1 p2 | [p1;p2;p3] -> Expr.call3 ident p1 p2 p3 | n -> Expr.callN ident n %} %token REAL %token NUM %token STR %token LETTERS %token DOLLAR %token LPAREN %token RPAREN %token PLUS %token TIMES %token DIVIDE %token MINUS %token EQ NEQ %token LT LE GT GE %token EOF %token SEMICOLON %token COLON %token POW %nonassoc EQ NEQ LT LE GT GE %left PLUS MINUS %left TIMES DIVIDE %left POW %start value %start content %% value: | EQ expr EOF {$2} content: | basic EOF {$1} basic: | PLUS num {Ok (Type.number $2)} | MINUS num {Ok (Type.number (DataType.Num.neg $2))} | num {Ok (Type.number $1)} | NUM DIVIDE NUM DIVIDE NUM {Ok ( Type.date ( DataType.Date.get_julian_day (int_of_string $1) (int_of_string $3) (int_of_string $5) ))} | NUM COLON NUM COLON NUM {Ok ( Type.date ( let nhour = DataType.Num.div (DataType.Num.of_int @@ int_of_string $1) (DataType.Num.of_int 24) and nmin = DataType.Num.div (DataType.Num.of_int @@ int_of_string $3) (DataType.Num.of_int 1440) and nsec = DataType.Num.div (DataType.Num.of_int @@ int_of_string $5) (DataType.Num.of_int 86400) in DataType.Num.add (DataType.Num.add nhour nmin) nsec ) )} expr: | num {Expr.value (Type.number ($1))} | MINUS expr {Expr.call1 S.sub $2} | PLUS expr {Expr.call1 S.add $2} | LETTERS ident LPAREN separated_list(SEMICOLON, expr) RPAREN { build_call (u($1 ^ $2)) $4 } | cell {Expr.ref (Refs.cell $1)} | cell COLON cell {Expr.ref (Refs.range $1 $3)} | LPAREN expr RPAREN {Expr.expression $2} | STR {Expr.value (Type.string (u $1))} (* Mathematical operators *) | expr MINUS expr {Expr.call2 S.sub $1 $3} | expr DIVIDE expr {Expr.call2 S.div $1 $3} | expr TIMES expr {Expr.call2 S.mul $1 $3} | expr PLUS expr {Expr.call2 S.add $1 $3} | expr POW expr {Expr.call2 S.pow $1 $3} (* Comparaison *) | expr EQ expr {Expr.call2 S.eq $1 $3} | expr NEQ expr {Expr.call2 S.neq $1 $3} | expr LT expr {Expr.call2 S.lt $1 $3} | expr GT expr {Expr.call2 S.gt $1 $3} | expr LE expr {Expr.call2 S.le $1 $3} | expr GE expr {Expr.call2 S.ge $1 $3} %inline cell: | LETTERS NUM { Cell.from_string (false, $1) (false, int_of_string $2) } | DOLLAR LETTERS NUM { Cell.from_string (true, $2) (false, int_of_string $3) } | LETTERS DOLLAR NUM { Cell.from_string (false, $1) (true, int_of_string $3) } | DOLLAR LETTERS DOLLAR NUM { Cell.from_string (true, $2) (true, int_of_string $4) } num: | REAL {DataType.Num.of_float @@ float_of_string $1} | NUM {DataType.Num.of_int @@ int_of_string $1} ident: | text* { String.concat "" $1 } text: | LETTERS { $1 } | NUM { $1 }