aboutsummaryrefslogtreecommitdiff
path: root/expressionParser.mly
blob: b7f77ae2ff17ac1a9126e458c063f3d51795f085 (plain)
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
%{
    open ScTypes
    module F = Functions

    let u = UTF8.from_utf8string

    let extractColumnNameFromNum (fixed, (str, value)) = (fixed, value)

%}

%token <string> REAL
%token <string> 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 $2)}
  | MINUS num               {Result (number (DataType.Num.neg $2))}
  | num                     {Result (number $1)}
  | NUM DIVIDE NUM DIVIDE NUM {Result (
      date (
        DataType.Date.get_julian_day 
          (int_of_string $1)
          (int_of_string $3)
          (int_of_string $5)
        ))}
  | NUM COLON NUM COLON NUM {Result (
      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                     {Value (number ($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, 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 }