-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdevinput.lem
More file actions
114 lines (90 loc) · 3.04 KB
/
Copy pathdevinput.lem
File metadata and controls
114 lines (90 loc) · 3.04 KB
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
%include {
#include <assert.h>
#include <math.h>
#include <string>
#include "devinput-parser.h"
#include "devinput.h"
#define LOCAL(x, X) \
auto x{std::move(*X)}; \
delete X
}
%name DevInputParse
%token_prefix InputToken_
%parse_accept {
}
%parse_failure {
args->error = true;
}
%syntax_error {
args->error = true;
}
%extra_argument { DevInputArgs *__attribute__((unused)) args }
%token_type { const std::string * }
%token_destructor { delete $$; }
%type expr { ValueExpr * }
%destructor expr { delete $$; }
%type expr_ { ValueExpr * }
%destructor expr_ { delete $$; }
%type value_ref { ValueRef * }
%destructor value_ref { delete $$; }
%type value_const { ValueConst * }
%destructor value_const { delete $$; }
%type expr_comma_list { std::vector<std::unique_ptr<ValueExpr>> * }
%destructor expr_comma_list { delete $$; }
%type variable { Variable * }
//variable has no destructor because they live globally
%right QUESTION.
%left COMMA.
%left OR.
%left AND.
%nonassoc GT LT.
%left PLUS MINUS.
%left MULT DIV.
%nonassoc NOT.
input ::= expr(A). { args->input = A; }
expr(A) ::= expr_(B). { A = optimize(B); }
expr_(A) ::= LPAREN expr(B) RPAREN. { A = B; }
expr_(A) ::= value_ref(B). { A = B; }
expr_(A) ::= value_const(B). { A = B; }
expr_(A) ::= variable(B). { A = new ValueVariable(B); }
expr_(A) ::= expr(B) QUESTION expr(C) COLON expr(D). { A = new ValueCond(B, C, D); }
expr_(A) ::= expr(B) PLUS expr(C). { A = new ValueOper(InputToken_PLUS, B, C); }
expr_(A) ::= expr(B) MINUS expr(C). { A = new ValueOper(InputToken_MINUS, B, C); }
expr_(A) ::= expr(B) AND expr(C). { A = new ValueOper(InputToken_AND, B, C); }
expr_(A) ::= expr(B) OR expr(C). { A = new ValueOper(InputToken_OR, B, C); }
expr_(A) ::= expr(B) GT expr(C). { A = new ValueOper(InputToken_GT, B, C); }
expr_(A) ::= expr(B) LT expr(C). { A = new ValueOper(InputToken_LT, B, C); }
expr_(A) ::= expr(B) MULT expr(C). { A = new ValueOper(InputToken_MULT, B, C); }
expr_(A) ::= expr(B) DIV expr(C). { A = new ValueOper(InputToken_DIV, B, C); }
expr_(A) ::= MINUS expr(B). [NOT] { A = new ValueUnary(InputToken_MINUS, B); }
expr_(A) ::= NOT expr(B). { A = new ValueUnary(InputToken_NOT, B); }
expr_(A) ::= NAME(B) LPAREN expr_comma_list(C) RPAREN. {
LOCAL(b, B);
LOCAL(c, C);
A = create_func(std::move(b), std::move(c));
}
value_ref(A) ::= NAME(B) PERIOD NAME(C). {
LOCAL(b, B);
LOCAL(c, C);
A = create_value_ref(b, c, args->finder);
}
value_const(A) ::= NUMBER(B). {
LOCAL(b, B);
std::istringstream is(b);
value_t val;
if (!(is >> val))
throw std::runtime_error("invalid number: " + b);
A = new ValueConst(val);
}
value_const(A) ::= PI. {
A = new ValueConst(M_PI);
}
variable(A) ::= DOLLAR NAME(B). {
LOCAL(b, B);
Variable *v = args->finder.find_variable(b);
if (!v)
throw std::runtime_error("undefined variable: " + b);
A = v;
}
expr_comma_list(A) ::= expr(B). { A = new std::vector<std::unique_ptr<ValueExpr>>(); A->emplace_back(B); }
expr_comma_list(A) ::= expr_comma_list(B) COMMA expr(C). { B->emplace_back(C); A = B; }