1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
%{
open ScTypes
module F = Functions
let u = UTF8.from_utf8string
let extractColumnNameFromNum (fixed, (str, value)) = (fixed, value)
%}
%token <string * Num.num> REAL
%token <string * Num.num> NUM
%token <string> STR
%token <string> 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<ScTypes.expression> value
%start<ScTypes.result> content
%%
value:
| EQ expr EOF {$2}
content:
| basic EOF {$1}
basic:
| PLUS num {Result (number (DataType.Num.of_num (snd $2)))}
| MINUS num {Result (number (DataType.Num.of_num @@ Num.minus_num (snd $2)))}
| num {Result (number (DataType.Num.of_num (snd $1)))}
| NUM DIVIDE NUM DIVIDE NUM {Result (
date (
DataType.Num.of_num @@ (Date.get_julian_day
(Num.int_of_num @@ snd $1)
(Num.int_of_num @@ snd $3)
(Num.int_of_num @@ snd $5)
)))}
| NUM COLON NUM COLON NUM {Result (
date (
Num.(
let nhour = (snd $1) // (num_of_int 24)
and nmin = (snd $3) // (num_of_int 1440)
and nsec = (snd $5) // (num_of_int 86400)
in DataType.Num.of_num @@ nhour +/ nmin +/ nsec)
)
)}
expr:
| num {Value (number (
DataType.Num.of_num (snd $1)
))}
| MINUS expr {Call (F.sub, [$2])}
| PLUS expr {Call (F.add, [$2])}
| LETTERS ident LPAREN separated_list(SEMICOLON, expr) RPAREN { Call (u($1 ^ $2), $4) }
| cell {Ref (Cell $1)}
| cell COLON cell {Ref (Range ($1, $3))}
| LPAREN expr RPAREN {Expression $2}
| STR {Value (string (u $1))}
(* Mathematical operators *)
| expr MINUS expr {Call (F.sub, [$1; $3])}
| expr DIVIDE expr {Call (F.div, [$1; $3])}
| expr TIMES expr {Call (F.mul, [$1; $3])}
| expr PLUS expr {Call (F.add, [$1; $3])}
| expr POW expr {Call (F.pow, [$1; $3])}
(* Comparaison *)
| expr EQ expr {Call (F.eq, [$1; $3])}
| expr NEQ expr {Call (F.neq, [$1; $3])}
| expr LT expr {Call (F.lt, [$1; $3])}
| expr GT expr {Call (F.gt, [$1; $3])}
| expr LE expr {Call (F.le, [$1; $3])}
| expr GE expr {Call (F.ge, [$1; $3])}
%inline cell:
| LETTERS NUM { Cell.from_string (false, $1) (false, snd $2) }
| DOLLAR LETTERS NUM { Cell.from_string (true, $2) (false, snd $3) }
| LETTERS DOLLAR NUM { Cell.from_string (false, $1) (true, snd $3) }
| DOLLAR LETTERS DOLLAR NUM { Cell.from_string (true, $2) (true, snd $4) }
num:
| REAL {$1}
| NUM {$1}
ident:
| text* { String.concat "" $1 }
text:
| LETTERS { $1 }
| NUM { fst $1 }
|