6161 DOT  " ." 
6262 LBRAK  " [" 
6363 RBRAK  " ]" 
64+  LCURL  " {" 
65+  RCURL  " }" 
6466 ;
6567
6668%token  <std::string>  ID  SUBID  UNKNOWN ;
7678%nterm  <std::pair<Expression*,Tree*> > ElseIf 
7779%nterm  <std::vector<std::pair<Expression*,Tree*> >> ElseIfs 
7880%nterm  <std::vector<std::pair<std::string,ExpI> >> Fields  Params 
79- %nterm  <std::vector<Expression*> > Array Args 
81+ %nterm  <std::vector<Expression*> > Args 
8082%nterm  <std::vector<std::variant<Expression *,std::vector<Expression*> >>> Array2 
8183
8284%left  OR 
@@ -201,6 +203,24 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
201203 YYERROR ;
202204 }
203205 }
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+  }
204224 |  ID  LBRAK  Exp  RBRAK  ASSIGN  Exp  EOL  {
205225 if  (3ドル ->type () != ExpI::IntT) {
206226 error (@3 , " array index must be IntExp" 
@@ -252,10 +272,12 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
252272 5ドル ->link ($$);
253273 prev = $$ ;
254274 }
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+  }
259281 }
260282 $$  = new  Output(2ドル );
261283 prev->link ($$);
@@ -307,16 +329,30 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
307329 YYERROR;
308330 }
309331 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;
311342 prev->link ($$);
312343 prev = $$;
313344 }
314345 | ID DOT ID ASSIGN Exp {
315-  if  (!table->check ($1 ).first ) {
346+  if  (!table->check ($1 ).first  || table-> type ($ 1 ) != ExpI::ObjectT ) {
316347 error (@1 , " no such record: " 1 );
317348 YYERROR;
318349 }
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: " 
353+  YYERROR;
354+  }
355+  auto  type = table->fieldtype (record_type, $3 );
320356 if  (type == ExpI::None) {
321357 error (@3 , " no such field: " 3 );
322358 YYERROR;
@@ -347,7 +383,6 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
347383 }
348384 | SubCall Args RPAREN EOL {
349385 if  ($2 .size () != table->types ($1 ).first .size ()) {
350-  std::cerr << $2 .size () << '  ' types ($1 ).first .size () << ' \n ' 
351386 error (@2 , " wrong number of arguments for call to subroutine: " 1 );
352387 YYERROR;
353388 }
@@ -458,21 +493,16 @@ SubCall : SUBID {
458493 }
459494 ;
460495
461- Args : Args COMMA Exp  { $$ = $ 1 ; $$. push_back ($ 3 ) ; }
496+ Args : %empty  { $$ = {} ; }
462497 | 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 ); }
469499 ;
470500
471501Array2 : %empty { $$ = {}; }
472502 | Exp { $$.push_back ($1 ); }
473503 | 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 ); }
476506 ;
477507
478508BoolExp : Exp {
@@ -503,16 +533,21 @@ Exp : STRING { $$ = new Value(1ドル); }
503533 }
504534 }
505535 | ID DOT ID {
506-  if  (!table->check ($1 ).first ) {
536+  if  (!table->check ($1 ).first  || table-> type ($ 1 ) != ExpI::ObjectT ) {
507537 error (@1 , " no such record: " 1 );
508538 YYERROR;
509539 }
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: " 
543+  YYERROR;
544+  }
545+  auto  type = table->fieldtype (record_type, $3 );
511546 if  (type == ExpI::None) {
512547 error (@3 , " no such field: " 3 );
513548 YYERROR;
514549 }
515-  $$ = new  Variable (table->fieldtype ($ 1 , $3 ), $1  + ' .' 3 );
550+  $$ = new  Variable (table->fieldtype (record_type , $3 ), $1  + ' .' 3 );
516551 }
517552 | ID LBRAK Exp RBRAK { $$ = new  Element ($1 , $3 , std::get<ExpI>(std::get<Array2T>(table->value ($1 )).at (0 ))); }
518553 | 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ドル); }
536571 | USERINPUT { $$ = new  UserInput (); }
537572 | SubCall Args RPAREN {
538573 if  ($2 .size () != table->types ($1 ).first .size ()) {
539-  std::cerr << $2 .size () << '  ' types ($1 ).first .size () << ' \n ' 
540574 error (@2 , " wrong number of arguments for call to subroutine: " 1 );
541575 YYERROR;
542576 }
@@ -635,7 +669,7 @@ Exp : STRING { $$ = new Value(1ドル); }
635669%% 
636670
637671void 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;
639673 if (loc.end.line != loc.begin.line) {
640674 *err << '-' << loc.end.line << ':' << loc.end.column - 1;
641675 }
0 commit comments