61
61
DOT " ."
62
62
LBRAK " ["
63
63
RBRAK " ]"
64
+ LCURL " {"
65
+ RCURL " }"
64
66
;
65
67
66
68
%token <std::string> ID SUBID UNKNOWN ;
76
78
%nterm <std::pair<Expression*,Tree*> > ElseIf
77
79
%nterm <std::vector<std::pair<Expression*,Tree*> >> ElseIfs
78
80
%nterm <std::vector<std::pair<std::string,ExpI> >> Fields Params
79
- %nterm <std::vector<Expression*> > Array Args
81
+ %nterm <std::vector<Expression*> > Args
80
82
%nterm <std::vector<std::variant<Expression *,std::vector<Expression*> >>> Array2
81
83
82
84
%left OR
@@ -201,6 +203,24 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
201
203
YYERROR ;
202
204
}
203
205
}
206
+ | ID ASSIGN ID LCURL Args RCURL EOL {
207
+ if ($5 .size() != std::get<RecordT>(table->value ($3 )).size()) {
208
+ error (@2 , " wrong number of fields for record type: " + $3 );
209
+ YYERROR;
210
+ }
211
+ std::vector<std::string> fields;
212
+ for (int i = 0 ; auto & e : $5 ) {
213
+ if (e->type () != table->fieldtype($3 , i)) {
214
+ error (@2 , " wrong type(s) of field value(s) for record type: " + $3 );
215
+ YYERROR;
216
+ }
217
+ fields.push_back(table->fieldname ($3 , i++));
218
+ }
219
+ table->store ($1 , ExpT{ ObjectT{ $3 } });
220
+ $$ = new ObjectAssign(std::move(fields), $1 , std::move($5 ));
221
+ prev->link ($$);
222
+ prev = $$ ;
223
+ }
204
224
| ID LBRAK Exp RBRAK ASSIGN Exp EOL {
205
225
if ($3 ->type () != ExpI::IntT) {
206
226
error (@3 , " array index must be IntExp" );
@@ -252,10 +272,12 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
252
272
$5 ->link ($$);
253
273
prev = $$ ;
254
274
}
255
- | OUTPUT Exp EOL {
256
- if ($2 ->type () != ExpI::StringT) {
257
- error (@2 , " expression to output must be a StringExp" );
258
- YYERROR;
275
+ | OUTPUT Args EOL {
276
+ for (auto & exp : $2 ) {
277
+ if (exp->type () != ExpI::StringT) {
278
+ error (@2 , " expression to output must be a StringExp" );
279
+ YYERROR;
280
+ }
259
281
}
260
282
$$ = new Output($2 );
261
283
prev->link ($$);
@@ -307,16 +329,30 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
307
329
YYERROR;
308
330
}
309
331
table->store ($2 , ExpT{ $4 });
310
- $$ = new Assign (new Value ($4 ), $2 );
332
+ $$ = new Empty;
333
+ prev->link ($$);
334
+ prev = $$;
335
+ }
336
+ | ID ASSIGN ID LPAREN Args RPAREN {
337
+ if (!table->check ($3 ).first || table->type ($3 ) != ExpI::RecordT) {
338
+ error (@3 , " no such record: " + $3 );
339
+ YYERROR;
340
+ }
341
+ $$ = new Empty;
311
342
prev->link ($$);
312
343
prev = $$;
313
344
}
314
345
| ID DOT ID ASSIGN Exp {
315
- if (!table->check ($1 ).first ) {
346
+ if (!table->check ($1 ).first || table-> type ($ 1 ) != ExpI::ObjectT ) {
316
347
error (@1 , " no such record: " + $1 );
317
348
YYERROR;
318
349
}
319
- auto type = table->fieldtype ($1 , $3 );
350
+ auto record_type = table->record ($1 );
351
+ if (record_type.empty ()) {
352
+ error (@1 , " no such record type: " + record_type);
353
+ YYERROR;
354
+ }
355
+ auto type = table->fieldtype (record_type, $3 );
320
356
if (type == ExpI::None) {
321
357
error (@3 , " no such field: " + $3 );
322
358
YYERROR;
@@ -347,7 +383,6 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
347
383
}
348
384
| SubCall Args RPAREN EOL {
349
385
if ($2 .size () != table->types ($1 ).first .size ()) {
350
- std::cerr << $2 .size () << ' ' << table->types ($1 ).first .size () << ' \n ' ;
351
386
error (@2 , " wrong number of arguments for call to subroutine: " + $1 );
352
387
YYERROR;
353
388
}
8000
@@ -458,21 +493,16 @@ SubCall : SUBID {
458
493
}
459
494
;
460
495
461
- Args : Args COMMA Exp { $$ = $ 1 ; $$. push_back ($ 3 ) ; }
496
+ Args : %empty { $$ = {} ; }
462
497
| Exp { $$.push_back ($1 ); }
463
- | %empty { $$ = {}; }
464
- ;
465
-
466
- Array : %empty { $$ = {}; }
467
- | Exp { $$.push_back ($1 ); }
468
- | Array COMMA Exp { $$ = $1 ; $$.push_back ($3 ); }
498
+ | Args COMMA Exp { $$ = $1 ; $$.push_back ($3 ); }
469
499
;
470
500
471
501
Array2 : %empty { $$ = {}; }
472
502
| Exp { $$.push_back ($1 ); }
473
503
| Array2 COMMA Exp { $$ = $1 ; $$.push_back ($3 ); }
474
- | LBRAK Array RBRAK { $$.push_back ($2 ); }
475
- | Array2 COMMA LBRAK Array RBRAK { $$ = $1 ; $$.push_back ($4 ); }
504
+ | LBRAK Args RBRAK { $$.push_back ($2 ); }
505
+ | Array2 COMMA LBRAK Args RBRAK { $$ = $1 ; $$.push_back ($4 ); }
476
506
;
477
507
478
508
BoolExp : Exp {
@@ -503,16 +533,21 @@ Exp : STRING { $$ = new Value($1); }
503
533
}
504
534
}
505
535
| ID DOT ID {
506
- if (!table->check ($1 ).first ) {
536
+ if (!table->check ($1 ).first || table-> type ($ 1 ) != ExpI::ObjectT ) {
507
537
error (@1 , " no such record: " + $1 );
508
538
YYERROR;
509
539
}
510
- auto type = table->fieldtype ($1 , $3 );
540
+ auto record_type = table->record ($1 );
541
+ if (record_type.empty ()) {
542
+ error (@1 , " no such record type: " + record_type);
543
+ YYERROR;
544
+ }
545
+ auto type = table->fieldtype (record_type, $3 );
511
546
if (type == ExpI::None) {
512
547
error (@3 , " no such field: " + $3 );
513
548
YYERROR;
514
549
}
515
- $$ = new Variable (table->fieldtype ($ 1 , $3 ), $1 + ' .' + $3 );
550
+ $$ = new Variable (table->fieldtype (record_type , $3 ), $1 + ' .' + $3 );
516
551
}
517
552
| ID LBRAK Exp RBRAK { $$ = new Element ($1 , $3 , std::get<ExpI>(std::get<Array2T>(table->value ($1 )).at (0 ))); }
518
553
| ID LBRAK Exp RBRAK LBRAK Exp RBRAK { $$ = new Element2 ($1 , $3 , $6 , std::get<ArrayT>(std::get<Array2T>(table->value ($1 )).at (0 )).at (0 )); }
@@ -536,7 +571,6 @@ Exp : STRING { $$ = new Value($1); }
536
571
| USERINPUT { $$ = new UserInput (); }
537
572
| SubCall Args RPAREN {
538
573
if ($2 .size () != table->types ($1 ).first .size ()) {
539
- std::cerr << $2 .size () << ' ' << table->types ($1 ).first .size () << ' \n ' ;
540
574
error (@2 , " wrong number of arguments for call to subroutine: " + $1 );
541
575
YYERROR;
542
576
}
@@ -635,7 +669,7 @@ Exp : STRING { $$ = new Value($1); }
635
669
%%
636
670
637
671
void yy::Parser::error(const location_type& loc, const std::string &e) {
638
- *err << "Location " << loc.begin.line << ':' << loc.begin.column;
672
+ *err << loc.begin.line << ':' << loc.begin.column;
639
673
if (loc.end.line != loc.begin.line) {
640
674
*err << '-' << loc.end.line << ':' << loc.end.column - 1;
641
675
}
0 commit comments