summaryrefslogtreecommitdiff
path: root/src/mem/slicc/parser/parser.yy
blob: fa5a3b355319438462c3b001b7f4a681dcbee53b (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
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

/*
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * $Id$
 *
 * */

%{
#include <string>
#include <stdio.h>
#include <assert.h>
#include "mem/slicc/ast/ASTs.hh"
#include <vector>

#define YYMAXDEPTH 100000
#define YYERROR_VERBOSE

extern char* yytext;

extern "C" void yyerror(char*);
extern "C" int yylex();

%}

%union {
  string* str_ptr;
  Vector<string>* string_vector_ptr;
  std::vector<string*>* stdstring_vector_ptr;

  // Decls
  DeclAST* decl_ptr;
  DeclListAST* decl_list_ptr;
  Vector<DeclAST*>* decl_vector_ptr;

  // TypeField
  TypeFieldAST* type_field_ptr;
  Vector<TypeFieldAST*>* type_field_vector_ptr;

  // Type
  TypeAST* type_ptr;
  Vector<TypeAST*>* type_vector_ptr;

  // Formal Params
  FormalParamAST* formal_param_ptr;
  Vector<FormalParamAST*>* formal_param_vector_ptr;

  // Statements
  StatementAST* statement_ptr;
  StatementListAST* statement_list_ptr;
  Vector<StatementAST*>* statement_vector_ptr;

  // Pairs
  PairAST* pair_ptr;
  PairListAST* pair_list_ptr;

  // Expressions
  VarExprAST* var_expr_ptr;
  ExprAST* expr_ptr;
  Vector<ExprAST*>* expr_vector_ptr;
}

%type <type_ptr> type void type_or_void
%type <type_vector_ptr> types type_list

  // Formal Params
%type <formal_param_ptr> formal_param
%type <formal_param_vector_ptr> formal_params formal_param_list

%type <str_ptr> ident field
%type <string_vector_ptr> ident_list idents

%type <statement_ptr> statement if_statement
%type <statement_list_ptr> statement_list
%type <statement_vector_ptr> statements

%type <decl_ptr> decl
%type <decl_list_ptr> decl_list
%type <decl_vector_ptr> decls

%type <type_field_vector_ptr> type_members type_enums type_methods
%type <type_field_ptr> type_member type_enum type_method

%type <var_expr_ptr> var
%type <expr_ptr> expr literal enumeration
%type <expr_vector_ptr> expr_list

%type <stdstring_vector_ptr> myrule

%type <pair_ptr> pair
%type <pair_list_ptr> pair_list pairs

%token <str_ptr> IDENT STRING NUMBER FLOATNUMBER LIT_BOOL VOID
%token <str_ptr> IMBED IMBED_TYPE
%token CHIP THIS
%token ASSIGN DOUBLE_COLON DOT SEMICOLON COLON
%token GLOBAL_DECL MACHINE_DECL IN_PORT_DECL OUT_PORT_DECL
%token PEEK ENQUEUE COPY_HEAD CHECK_ALLOCATE CHECK_STOP_SLOTS
//%token DEQUEUE REMOVE_EARLY SKIP_EARLY PEEK_EARLY
%token DEBUG_EXPR_TOKEN DEBUG_MSG_TOKEN
%token ACTION_DECL TRANSITION_DECL TYPE_DECL STRUCT_DECL EXTERN_TYPE_DECL ENUM_DECL
%token TYPE_FIELD OTHER IF ELSE RETURN NEW

%token <str_ptr> EQ NE '<' '>' LE GE NOT AND OR PLUS DASH STAR SLASH RIGHTSHIFT LEFTSHIFT

%left OR
%left AND
%nonassoc EQ NE
%nonassoc '<' '>' GE LE
%left PLUS DASH
%left STAR SLASH
%nonassoc NOT
%nonassoc DOUBLE_COLON DOT '['

%%

file: decl_list { g_decl_list_ptr = $1; }

decl_list:  decls { $$ = new DeclListAST($1); }

decls: decl decls { $2->insertAtTop($1); $$ = $2; }
     | { $$ = new Vector<DeclAST*>; }
     ;

decl:  MACHINE_DECL     '(' ident pair_list ')' ':' myrule '{' decl_list '}' { $$ = new MachineAST($3, $4, NULL, $7, $9); }
//    |  MACHINE_DECL     '(' ident pair_list ')' ':' type_members '{' decl_list '}' { $$ = new MachineAST($3, $4, $7, string_vector, $9); }
    |  MACHINE_DECL     '(' ident pair_list ')' '{' decl_list '}' { $$ = new MachineAST($3, $4, NULL, new vector<string*>(), $7); }
    |  ACTION_DECL      '(' ident pair_list ')' statement_list { $$ = new ActionDeclAST($3, $4, $6); }
    |  IN_PORT_DECL     '(' ident ',' type ',' var pair_list ')' statement_list { $$ = new InPortDeclAST($3, $5, $7, $8, $10); }
    |  OUT_PORT_DECL    '(' ident ',' type ',' var pair_list ')' SEMICOLON { $$ = new OutPortDeclAST($3, $5, $7, $8); }
    |  TRANSITION_DECL  '(' ident_list ',' ident_list ',' ident pair_list ')' ident_list { $$ = new TransitionDeclAST($3, $5, $7, $8, $10); }
    |  TRANSITION_DECL  '(' ident_list ',' ident_list           pair_list ')' ident_list { $$ = new TransitionDeclAST($3, $5, NULL, $6, $8); }
    |  EXTERN_TYPE_DECL '(' type pair_list ')' SEMICOLON            { $4->addPair(new PairAST("external", "yes")); $$ = new TypeDeclAST($3, $4, NULL); }
    |  EXTERN_TYPE_DECL '(' type pair_list ')' '{' type_methods '}' { $4->addPair(new PairAST("external", "yes")); $$ = new TypeDeclAST($3, $4, $7); }
    |  GLOBAL_DECL      '(' type pair_list ')' '{' type_members '}' { $4->addPair(new PairAST("global", "yes"));$$ = new TypeDeclAST($3, $4, $7); }
    |  STRUCT_DECL      '(' type pair_list ')' '{' type_members '}' { $$ = new TypeDeclAST($3, $4, $7); }
    |  ENUM_DECL        '(' type pair_list ')' '{' type_enums   '}' { $4->addPair(new PairAST("enumeration", "yes")); $$ = new EnumDeclAST($3, $4, $7); }
    |  type ident pair_list SEMICOLON { $$ = new ObjDeclAST($1, $2, $3); }
    |  type ident '(' formal_param_list ')' pair_list SEMICOLON { $$ = new FuncDeclAST($1, $2, $4, $6, NULL); } // non-void function
    |  void ident '(' formal_param_list ')' pair_list SEMICOLON { $$ = new FuncDeclAST($1, $2, $4, $6, NULL); } // void function
    |  type ident '(' formal_param_list ')' pair_list statement_list { $$ = new FuncDeclAST($1, $2, $4, $6, $7); } // non-void function
    |  void ident '(' formal_param_list ')' pair_list statement_list { $$ = new FuncDeclAST($1, $2, $4, $6, $7); } // void function
    ;

// Type fields

type_members: type_member type_members { $2->insertAtTop($1); $$ = $2; }
            | { $$ = new Vector<TypeFieldAST*>; }
            ;

type_member: type ident pair_list SEMICOLON { $$ = new TypeFieldMemberAST($1, $2, $3, NULL); }
           | type ident ASSIGN expr SEMICOLON { $$ = new TypeFieldMemberAST($1, $2, new PairListAST(), $4); }
           ;

// Methods
type_methods: type_method type_methods { $2->insertAtTop($1); $$ = $2; }
            | { $$ = new Vector<TypeFieldAST*>; }
            ;

type_method: type_or_void ident '(' type_list ')' pair_list SEMICOLON { $$ = new TypeFieldMethodAST($1, $2, $4, $6); }
           ;

// Enum fields
type_enums: type_enum type_enums { $2->insertAtTop($1); $$ = $2; }
          | { $$ = new Vector<TypeFieldAST*>; }
          ;

type_enum: ident pair_list SEMICOLON { $$ = new TypeFieldEnumAST($1, $2); }
         ;

// Type
type_list : types { $$ = $1; }
          | { $$ = new Vector<TypeAST*>; }
          ;

types    : type ',' types { $3->insertAtTop($1); $$ = $3; }
         | type { $$ = new Vector<TypeAST*>; $$->insertAtTop($1); }
         ;

type: ident { $$ = new TypeAST($1); }
    ;

void: VOID { $$ = new TypeAST($1); }
    ;

type_or_void: type { $$ = $1; }
    | void { $$ = $1; }
    ;

// Formal Param
formal_param_list : formal_params { $$ = $1; }
                | { $$ = new Vector<FormalParamAST*>; }
                ;

formal_params : formal_param ',' formal_params { $3->insertAtTop($1); $$ = $3; }
              | formal_param { $$ = new Vector<FormalParamAST*>; $$->insertAtTop($1); }
              ;

formal_param : type ident { $$ = new FormalParamAST($1, $2); }
             ;

// Idents and lists
ident: IDENT { $$ = $1; };

ident_list: '{' idents '}' { $$ = $2; }
          | ident { $$ = new Vector<string>; $$->insertAtTop(*($1)); delete $1; }
          ;

idents:  ident SEMICOLON idents { $3->insertAtTop(*($1)); $$ = $3; delete $1; }
      |  ident ',' idents { $3->insertAtTop(*($1)); $$ = $3; delete $1; }
      |  ident idents { $2->insertAtTop(*($1)); $$ = $2; delete $1; }
      |  { $$ = new Vector<string>; }
      ;

// Pair and pair lists
pair_list: ',' pairs { $$ = $2; }
         | { $$ = new PairListAST(); }

pairs    : pair ',' pairs { $3->addPair($1); $$ = $3; }
         | pair { $$ = new PairListAST(); $$->addPair($1); }
         ;

pair     : ident '=' STRING { $$ = new PairAST($1, $3); }
         | ident '=' ident { $$ = new PairAST($1, $3); }
         | STRING { $$ = new PairAST(new string("short"), $1); }
         ;

// Below are the rules for action descriptions

statement_list:  '{' statements '}' { $$ = new StatementListAST($2); }
              ;

statements: statement statements  { $2->insertAtTop($1); $$ = $2; }
          |  { $$ = new Vector<StatementAST*>; }
          ;

expr_list:  expr ',' expr_list  { $3->insertAtTop($1); $$ = $3; }
         |  expr { $$ = new Vector<ExprAST*>; $$->insertAtTop($1); }
         |  { $$ = new Vector<ExprAST*>; }
         ;

statement:  expr SEMICOLON { $$ = new ExprStatementAST($1); }
         |  expr ASSIGN expr SEMICOLON { $$ = new AssignStatementAST($1, $3); }
         |  ENQUEUE      '(' var ',' type pair_list ')' statement_list { $$ = new EnqueueStatementAST($3, $5, $6, $8); }
         |  PEEK         '(' var ',' type ')' statement_list { $$ = new PeekStatementAST($3, $5, $7, "peek"); }
//         |  PEEK_EARLY   '(' var ',' type ')' statement_list { $$ = new PeekStatementAST($3, $5, $7, "peekEarly"); }
         |  COPY_HEAD    '(' var ',' var pair_list ')' SEMICOLON { $$ = new CopyHeadStatementAST($3, $5, $6); }
         |  CHECK_ALLOCATE '(' var ')' SEMICOLON { $$ = new CheckAllocateStatementAST($3); }
         |  CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMICOLON { $$ = new CheckStopSlotsStatementAST($3, $5, $7); }
         |  if_statement { $$ = $1; }
         |  RETURN expr SEMICOLON { $$ = new ReturnStatementAST($2); }
         ;

if_statement: IF '(' expr ')' statement_list ELSE statement_list { $$ = new IfStatementAST($3, $5, $7); }
            | IF '(' expr ')' statement_list { $$ = new IfStatementAST($3, $5, NULL); }
            | IF '(' expr ')' statement_list ELSE if_statement { $$ = new IfStatementAST($3, $5, new StatementListAST($7)); }
            ;

expr:  var { $$ = $1; }
    |  literal { $$ = $1; }
    |  enumeration { $$ = $1; }
    |  ident '(' expr_list ')' { $$ = new FuncCallExprAST($1, $3); }
    |  NEW type { $$ = new NewExprAST($2); }

// globally access a local chip component and call a method
    |  THIS DOT var '[' expr ']' DOT var DOT ident '(' expr_list ')' { $$ = new ChipComponentAccessAST($3, $5, $8, $10, $12 ); }
// globally access a local chip component and access a data member
    |  THIS DOT var '[' expr ']' DOT var DOT field { $$ = new ChipComponentAccessAST($3, $5, $8, $10 ); }
// globally access a specified chip component and call a method
    |  CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' expr_list ')' { $$ = new ChipComponentAccessAST($3, $6, $8, $11, $13, $15 ); }
// globally access a specified chip component and access a data member
    |  CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT field { $$ = new ChipComponentAccessAST($3, $6, $8, $11, $13 ); }


    |  expr DOT field { $$ = new MemberExprAST($1, $3); }
    |  expr DOT ident '(' expr_list ')' { $$ = new MethodCallExprAST($1, $3, $5); }
    |  type DOUBLE_COLON ident '(' expr_list ')' { $$ = new MethodCallExprAST($1, $3, $5); }
    |  expr '[' expr_list ']' { $$ = new MethodCallExprAST($1, new string("lookup"), $3); }
    |  expr STAR  expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr SLASH expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr PLUS  expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr DASH  expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr '<'   expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr '>'   expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr LE    expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr GE    expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr EQ    expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr NE    expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr AND   expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr OR    expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr RIGHTSHIFT expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
    |  expr LEFTSHIFT  expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
//    |  NOT expr        { $$ = NULL; }        // FIXME - unary not
//    |  DASH expr %prec NOT { $$ = NULL; }    // FIXME - unary minus
   |  '(' expr ')' { $$ = $2; }
    ;

literal: STRING   { $$ = new LiteralExprAST($1, "string"); }
       | NUMBER   { $$ = new LiteralExprAST($1, "int"); }
       | FLOATNUMBER   { $$ = new LiteralExprAST($1, "int"); }
       | LIT_BOOL { $$ = new LiteralExprAST($1, "bool");  }
       ;

enumeration: ident ':' ident { $$ = new EnumExprAST(new TypeAST($1), $3); }
           ;

var: ident { $$ = new VarExprAST($1); }
   ;

field: ident { $$ = $1; }
     ;

myrule: myrule IDENT { $1->push_back($2); }
      | IDENT { $$ = new vector<string*>(1, $1); }
      ;

%%

extern FILE *yyin;

DeclListAST* parse(string filename)
{
  FILE *file;
  file = fopen(filename.c_str(), "r");
  if (!file) {
    cerr << "Error: Could not open file: " << filename << endl;
    exit(1);
  }
  g_line_number = 1;
  g_file_name() = filename;
  yyin = file;
  g_decl_list_ptr = NULL;
  yyparse();
  return g_decl_list_ptr;
}

extern "C" void yyerror(char* s)
{
  fprintf(stderr, "%s:%d: %s at %s\n", g_file_name().c_str(), g_line_number, s, yytext);
  exit(1);
}