aboutsummaryrefslogtreecommitdiff
path: root/src/Calculator.g4
blob: 354a2e9d8b4bfa5a786f1faf614c7c3e950c0bde (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
// Copyright 2021 Benjamin Barenblat
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

// The lexer and parser grammars for the EC language.

grammar Calculator;

options {
  language = Cpp;
}

@parser::postinclude {
#include <stdexcept>
#include <string>
#include <utility>

#include "third_party/abseil/absl/strings/numbers.h"
}

program : term* ;

term : number | identifier | error ;

number returns [double value]
  : s=NUMBER {
      if (!absl::SimpleAtod($s->getText(), &$value)) {
        throw std::runtime_error("Calculator: parser produced an invalid double");
      }
    }
  ;

identifier returns [std::string value]
  : s=IDENTIFIER {
      $value = std::move($s->getText());
    }
  | SUGARED_ADD { $value = "add"; }
  | SUGARED_SUB { $value = "sub"; }
  | SUGARED_MUL { $value = "mul"; }
  | SUGARED_DIV { $value = "div"; }
  ;

error : ERROR ;

NUMBER : [+-]? (DIGIT+ '.'? DIGIT* | '.' DIGIT+) ('e' [+-]? DIGIT+)? ;

IDENTIFIER : [\p{Alpha}\p{General_Category=Other_Letter}] [\p{Alnum}\p{General_Category=Other_Letter}]* ;

SUGARED_ADD : '+' ;
SUGARED_SUB : '-' ;
SUGARED_MUL : '*' ;
SUGARED_DIV : '/' ;

WS : [\p{White_Space}]+ -> skip ;

ERROR : . ;

fragment DIGIT : [0-9] ;