summaryrefslogtreecommitdiff
path: root/cpp/src/FreezeScript/Grammar.y
blob: eb34e61361214d8fcd7fce7bb37107d915cac145 (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
%{

// **********************************************************************
//
// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************

#include <FreezeScript/GrammarUtil.h>

#ifdef _MSC_VER
// I get these warnings from some bison versions:
// warning C4102: 'yyoverflowlab' : unreferenced label
#   pragma warning( disable : 4102 )
// warning C4065: switch statement contains 'default' but no 'case' labels
#   pragma warning( disable : 4065 )
#endif

using namespace std;
using namespace FreezeScript;

void
freeze_script_error(const char* s)
{
    // yacc and recent versions of Bison use "syntax error" instead
    // of "parse error".

    if(strcmp(s, "parse error") == 0)
    {
        parseErrorReporter->expressionSyntaxError("syntax error");
    }
    else
    {
        parseErrorReporter->expressionSyntaxError(s);
    }
}

%}

%pure_parser

%token TOK_AND
%token TOK_OR
%token TOK_NOT
%token TOK_ADD
%token TOK_SUB
%token TOK_MUL
%token TOK_DIV
%token TOK_MOD
%token TOK_LPAREN
%token TOK_RPAREN
%token TOK_LBRACKET
%token TOK_RBRACKET
%token TOK_LESS_THAN
%token TOK_GREATER_THAN
%token TOK_LESS_EQUAL
%token TOK_GREATER_EQUAL
%token TOK_EQUAL
%token TOK_NEQ
%token TOK_TRUE
%token TOK_FALSE
%token TOK_NIL
%token TOK_SCOPE_DELIMITER
%token TOK_IDENTIFIER
%token TOK_STRING_LITERAL
%token TOK_INTEGER_LITERAL
%token TOK_FLOATING_POINT_LITERAL

%left TOK_OR
%left TOK_AND
%nonassoc TOK_LESS_THAN TOK_GREATER_THAN TOK_LESS_EQUAL TOK_GREATER_EQUAL TOK_EQUAL TOK_NEQ
%left TOK_ADD TOK_SUB
%left TOK_MUL TOK_DIV TOK_MOD
%right UNARY_OP

%%

// ----------------------------------------------------------------------
start
// ----------------------------------------------------------------------
: expr
{
    parseResult = $1;
}
;

// ----------------------------------------------------------------------
expr
// ----------------------------------------------------------------------
: binary
{
    $$ = $1;
}
;

// ----------------------------------------------------------------------
binary
// ----------------------------------------------------------------------
: binary TOK_LESS_THAN binary
{
    $$ = new BinaryNode(BinOpLess, parseDataFactory, $1, $3);
}
| binary TOK_GREATER_THAN binary
{
    $$ = new BinaryNode(BinOpGreater, parseDataFactory, $1, $3);
}
| binary TOK_LESS_EQUAL binary
{
    $$ = new BinaryNode(BinOpLessEq, parseDataFactory, $1, $3);
}
| binary TOK_GREATER_EQUAL binary
{
    $$ = new BinaryNode(BinOpGrEq, parseDataFactory, $1, $3);
}
| binary TOK_EQUAL binary
{
    $$ = new BinaryNode(BinOpEq, parseDataFactory, $1, $3);
}
| binary TOK_NEQ binary
{
    $$ = new BinaryNode(BinOpNotEq, parseDataFactory, $1, $3);
}
| binary TOK_OR binary
{
    $$ = new BinaryNode(BinOpOr, parseDataFactory, $1, $3);
}
| binary TOK_AND binary
{
    $$ = new BinaryNode(BinOpAnd, parseDataFactory, $1, $3);
}
| binary TOK_MUL binary
{
    $$ = new BinaryNode(BinOpMul, parseDataFactory, $1, $3);
}
| binary TOK_DIV binary
{
    $$ = new BinaryNode(BinOpDiv, parseDataFactory, $1, $3);
}
| binary TOK_MOD binary
{
    $$ = new BinaryNode(BinOpMod, parseDataFactory, $1, $3);
}
| binary TOK_ADD binary
{
    $$ = new BinaryNode(BinOpAdd, parseDataFactory, $1, $3);
}
| binary TOK_SUB binary
{
    $$ = new BinaryNode(BinOpSub, parseDataFactory, $1, $3);
}
| unary
{
    $$ = $1;
}
;

// ----------------------------------------------------------------------
unary
// ----------------------------------------------------------------------
: TOK_LPAREN expr TOK_RPAREN
{
    $$ = $2;
}
| TOK_SUB unary       %prec UNARY_OP
{
    $$ = new UnaryNode(UnaryOpNeg, parseDataFactory, $2);
}
| TOK_NOT unary       %prec UNARY_OP
{
    $$ = new UnaryNode(UnaryOpNot, parseDataFactory, $2);
}
| TOK_INTEGER_LITERAL
{
    IntegerTokPtr intVal = IntegerTokPtr::dynamicCast($1);
    assert(intVal);
    $$ = new DataNode(parseDataFactory->createInteger(intVal->v, true));
}
| TOK_FLOATING_POINT_LITERAL
{
    FloatingTokPtr floatVal = FloatingTokPtr::dynamicCast($1);
    assert(floatVal);
    $$ = new DataNode(parseDataFactory->createDouble(floatVal->v, true));
}
| TOK_STRING_LITERAL
{
    StringTokPtr stringVal = StringTokPtr::dynamicCast($1);
    assert(stringVal);
    $$ = new DataNode(parseDataFactory->createString(stringVal->v, true));
}
| TOK_TRUE
{
    $$ = new DataNode(parseDataFactory->createBoolean(true, true));
}
| TOK_FALSE
{
    $$ = new DataNode(parseDataFactory->createBoolean(false, true));
}
| TOK_NIL
{
    $$ = new DataNode(parseDataFactory->createNil(true));
}
| entity
{
    $$ = $1;
}
| entity '.' function
{
    EntityNodePtr entity = EntityNodePtr::dynamicCast($1);
    assert(entity);
    FunctionNodePtr func = FunctionNodePtr::dynamicCast($3);
    assert(func);
    func->setTarget(entity);
    $$ = $3;
}
| function
{
    $$ = $1;
}
| constant
{
    StringTokPtr stringVal = StringTokPtr::dynamicCast($1);
    assert(stringVal);
    $$ = new ConstantNode(stringVal->v);
}
;

// ----------------------------------------------------------------------
entity
// ----------------------------------------------------------------------
: entity TOK_LBRACKET expr TOK_RBRACKET
{
    EntityNodePtr entity = EntityNodePtr::dynamicCast($1);
    assert(entity);
    entity->append(new ElementNode($3));
    $$ = $1;
}
| entity '.' TOK_IDENTIFIER
{
    StringTokPtr stringVal = StringTokPtr::dynamicCast($3);
    assert(stringVal);
    EntityNodePtr entity = EntityNodePtr::dynamicCast($1);
    assert(entity);
    entity->append(new IdentNode(stringVal->v));
    $$ = $1;
}
| TOK_IDENTIFIER
{
    StringTokPtr stringVal = StringTokPtr::dynamicCast($1);
    assert(stringVal);
    $$ = new IdentNode(stringVal->v);
}
;

// ----------------------------------------------------------------------
function
// ----------------------------------------------------------------------
: TOK_IDENTIFIER TOK_LPAREN arg_list TOK_RPAREN
{
    StringTokPtr func = StringTokPtr::dynamicCast($1);
    assert(func);
    NodeListTokPtr args = NodeListTokPtr::dynamicCast($3);
    assert(args);
    $$ = new FunctionNode(func->v, args->v);
}
;

// ----------------------------------------------------------------------
arg_list
// ----------------------------------------------------------------------
: arg_list ',' expr
{
    NodeListTokPtr l = NodeListTokPtr::dynamicCast($1);
    assert(l);
    l->v.push_back($3);
    $$ = $1;
}
| expr
{
    NodeListTokPtr result = new NodeListTok;
    result->v.push_back($1);
    $$ = result;
}
|
{
    $$ = new NodeListTok;
}
;

// ----------------------------------------------------------------------
constant
// ----------------------------------------------------------------------
: constant TOK_SCOPE_DELIMITER TOK_IDENTIFIER
{
    StringTokPtr stringVal = StringTokPtr::dynamicCast($1);
    assert(stringVal);
    StringTokPtr idVal = StringTokPtr::dynamicCast($3);
    assert(idVal);
    stringVal->v.append("::" + idVal->v);
    $$ = $1;
}
| TOK_SCOPE_DELIMITER TOK_IDENTIFIER
{
    StringTokPtr idVal = StringTokPtr::dynamicCast($2);
    assert(idVal);
    StringTokPtr stringVal = new StringTok;
    stringVal->v.append("::" + idVal->v);
    $$ = stringVal;
}
;

%%