7777%nterm <std::pair<std::string,ExpI> > Field Param
7878%nterm <std::pair<Expression*,Tree*> > ElseIf
7979%nterm <std::vector<std::pair<Expression*,Tree*> >> ElseIfs
80- %nterm <std::vector<std::pair<std::string,ExpI> >> Fields Params
81- %nterm <std::vector<Expression*> > Args
80+ %nterm <std::vector<std::pair<std::string,ExpI> >> Fields OptParL ParList
81+ %nterm <std::vector<Expression*> > OptExpL ExpList
8282%nterm <std::vector<std::variant<Expression *,std::vector<Expression*> >>> Array2
8383
8484%left OR
@@ -203,25 +203,25 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
203203 YYERROR ;
204204 }
205205 }
206- | ID ASSIGN ID LCURL Args RCURL EOL {
207- if (!table->check ($3 ).first || table->type($3 ) != ExpI::RecordT) {
208- error (@1 , " no such record: " + $3 );
206+ | ID ASSIGN ID LCURL ExpList RCURL EOL {
207+ if (!table->check ($3 ).first || table->type($3 ) != ExpI::RecordT || !std::get<RecordT>(table-> value ($ 3 )).second ) {
208+ error (@1 , " no such record definition : " + $3 );
209209 YYERROR;
210210 }
211- if ($5 .size() != std::get<RecordT>(table->value ($3 )).size()) {
211+ if ($5 .size() != std::get<RecordT>(table->value ($3 )).first. size()) {
212212 error (@2 , " wrong number of fields for record type: " + $3 );
213213 YYERROR;
214214 }
215- std::vector<std::string> fields;
216- for (int i = 0 ; auto & e : $5 ) {
217- if (e->type () != table->fieldtype($3 , i)) {
215+ for (size_t i{ 0 }; auto & e : $5 ) {
216+ if (e->type () != table->fieldtype ($3 , i++)) {
218217 error (@2 , " wrong type(s) of field value(s) for record type: " + $3 );
219218 YYERROR;
220219 }
221- fields.push_back(table->fieldname ($3 , i++));
222220 }
223- table->store ($1 , ExpT{ ObjectT{ $3 } });
224- $$ = new ObjectAssign(std::move(fields), $1 , std::move($5 ));
221+ RecordT rec = std::get<RecordT>(table->value ($3 ));
222+ rec.second = false ;
223+ table->store ($1 , ExpT{ rec });
224+ $$ = new RecordAssign($1 , std::move($5 ), std::move(rec));
225225 prev->link ($$);
226226 prev = $$ ;
227227 }
@@ -276,7 +276,7 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
276276 $5 ->link ($$);
277277 prev = $$ ;
278278 }
279- | OUTPUT Args EOL {
279+ | OUTPUT ExpList EOL {
280280 for (auto & exp : $2 ) {
281281 if (exp->type () != ExpI::StringT) {
282282 error (@2 , " expression to output must be a StringExp" );
@@ -332,31 +332,17 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
332332 error (@2 , " already exists: " + $2 );
333333 YYERROR;
334334 }
335- table->store ($2 , ExpT{ $4 });
336- $$ = new Empty;
337- prev->link ($$);
338- prev = $$;
339- }
340- | ID ASSIGN ID LPAREN Args RPAREN {
341- if (!table->check ($3 ).first || table->type ($3 ) != ExpI::RecordT) {
342- error (@3 , " no such record: " + $3 );
343- YYERROR;
344- }
335+ table->store ($2 , ExpT{ RecordT{ $4 , true } });
345336 $$ = new Empty;
346337 prev->link ($$);
347338 prev = $$;
348339 }
349340 | ID DOT ID ASSIGN Exp {
350- if (!table->check ($1 ).first || table->type ($1 ) != ExpI::ObjectT ) {
341+ if (!table->check ($1 ).first || table->type ($1 ) != ExpI::RecordT || std::get<RecordT>(table-> value ($ 1 )). second ) {
351342 error (@1 , " no such record: " + $1 );
352343 YYERROR;
353344 }
354- auto record_type = table->record ($1 );
355- if (record_type.empty ()) {
356- error (@1 , " no such record type: " + record_type);
357- YYERROR;
358- }
359- auto type = table->fieldtype (record_type, $3 );
345+ auto type = table->fieldtype ($1 , $3 );
360346 if (type == ExpI::None) {
361347 error (@3 , " no such field: " + $3 );
362348 YYERROR;
@@ -369,13 +355,13 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
369355 prev->link ($$);
370356 prev = $$;
371357 }
372- | SUBROUTINE SubId Params RPAREN EOL Marker Block ENDSUBROUTINE EOL {
358+ | SUBROUTINE SubId OptParL RPAREN EOL Marker Block ENDSUBROUTINE EOL {
373359 table->endsub ($3 );
374360 $$ = new Subroutine (new Decls (table, $2 ), $2 , std::pair { $3 , ExpI::None }, $7 );
375361 $6 ->link ($$);
376362 prev = $$;
377363 }
378- | SUBROUTINE SubId Params RPAREN EOL Marker Block RETURN Exp EOL ENDSUBROUTINE EOL {
364+ | SUBROUTINE SubId OptParL RPAREN EOL Marker Block RETURN Exp EOL ENDSUBROUTINE EOL {
379365 table->endsub ($3 , $9 ->type ());
380366 if ($9 ->type () > ExpI::StringT) {
381367 error (@8 , " unsupported return type for subroutine" );
@@ -385,7 +371,7 @@ Stmnt : EOL { $$ = new Empty; prev->link($$); prev = $$; }
385371 $6 ->link ($$);
386372 prev = $$;
387373 }
388- | SubCall Args RPAREN EOL {
374+ | SubCall OptExpL RPAREN EOL {
389375 if ($2 .size () != table->types ($1 ).first .size ()) {
390376 error (@2 , " wrong number of arguments for call to subroutine: " + $1 );
391377 YYERROR;
@@ -469,9 +455,12 @@ Field : ID TYPESPEC ID EOL {
469455 }
470456 ;
471457
472- Params : Params COMMA Param { $$ = $1 ; $$.push_back ($3 ); }
458+ OptParL : %empty { $$ = {}; }
459+ | ParList { $$ = $1 ; }
460+ ;
461+
462+ ParList : ParList COMMA Param { $$ = $1 ; $$.push_back ($3 ); }
473463 | Param { $$.push_back ($1 ); }
474- | %empty { $$ = {}; }
475464 ;
476465
477466Param : ID TYPESPEC ID {
@@ -497,16 +486,18 @@ SubCall : SUBID {
497486 }
498487 ;
499488
500- Args : %empty { $$ = {}; }
501- | Exp { $$.push_back ($1 ); }
502- | Args COMMA Exp { $$ = $1 ; $$.push_back ($3 ); }
489+ OptExpL : %empty { $$ = {}; }
490+ | ExpList { $$ = $1 ; }
503491 ;
504492
505- Array2 : %empty { $$ = {}; }
506- | Exp { $$.push_back ($1 ); }
493+ ExpList : Exp { $$.push_back ($1 ); }
494+ | ExpList COMMA Exp { $$ = $1 ; $$.push_back ($3 ); }
495+ ;
496+
497+ Array2 : Exp { $$.push_back ($1 ); }
507498 | Array2 COMMA Exp { $$ = $1 ; $$.push_back ($3 ); }
508- | LBRAK Args RBRAK { $$.push_back ($2 ); }
509- | Array2 COMMA LBRAK Args RBRAK { $$ = $1 ; $$.push_back ($4 ); }
499+ | LBRAK ExpList RBRAK { $$.push_back ($2 ); }
500+ | Array2 COMMA LBRAK ExpList RBRAK { $$ = $1 ; $$.push_back ($4 ); }
510501 ;
511502
512503BoolExp : Exp {
@@ -537,21 +528,16 @@ Exp : STRING { $$ = new Value($1); }
537528 }
538529 }
539530 | ID DOT ID {
540- if (!table->check ($1 ).first || table->type ($1 ) != ExpI::ObjectT ) {
531+ if (!table->check ($1 ).first || table->type ($1 ) != ExpI::RecordT || std::get<RecordT>(table-> value ($ 1 )). second ) {
541532 error (@1 , " no such record: " + $1 );
542533 YYERROR;
543534 }
544- auto record_type = table->record ($1 );
545- if (record_type.empty ()) {
546- error (@1 , " no such record type: " + record_type);
547- YYERROR;
548- }
549- auto type = table->fieldtype (record_type, $3 );
535+ auto type = table->fieldtype ($1 , $3 );
550536 if (type == ExpI::None) {
551537 error (@3 , " no such field: " + $3 );
552538 YYERROR;
553539 }
554- $$ = new Variable (table->fieldtype (record_type , $3 ), $1 + ' .' + $3 );
540+ $$ = new Variable (table->fieldtype ($ 1 , $3 ), $1 + ' .' + $3 );
555541 }
556542 | ID LBRAK Exp RBRAK { $$ = new Element ($1 , $3 , std::get<ExpI>(std::get<Array2T>(table->value ($1 )).at (0 ))); }
557543 | 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 )); }
@@ -561,10 +547,10 @@ Exp : STRING { $$ = new Value($1); }
561547 | Exp DIVIDE Exp { VALID_OP ($1 , $3 , Operator::divide, @$); if ($3 ->isConstant () && (std::get<RealT>($3 ->apply ()) == 0.0 )) { error (@$, " division by zero" ); YYERROR; } $$ = new ExpressionOp ($1 , $3 , Operator::divide); }
562548 | Exp DIV Exp { VALID_OP ($1 , $3 , Operator::DIV, @$); if ($3 ->isConstant () && (std::get<IntT>($3 ->apply ()) == 0 )) { error (@$, " division by zero" ); YYERROR; } $$ = new ExpressionOp ($1 , $3 , Operator::DIV); }
563549 | Exp MOD Exp { VALID_OP ($1 , $3 , Operator::MOD, @$); if ($3 ->isConstant () && (std::get<IntT>($3 ->apply ()) == 0 )) { error (@$, " division by zero" ); YYERROR; } $$ = new ExpressionOp ($1 , $3 , Operator::MOD); }
564- | MINUS Exp %prec UMINUS { VALID_OP ($2 , $2 , Operator::negative, @$); $$ = new ExpressionOp ($2 , $ 2 , Operator::negative); }
550+ | MINUS Exp %prec UMINUS { VALID_OP ($2 , $2 , Operator::negative, @$); $$ = new ExpressionOp ($2 , nullptr , Operator::negative); }
565551 | Exp OR Exp { VALID_OP ($1 , $3 , Operator::OR, @$); $$ = new ExpressionOp ($1 , $3 , Operator::OR); }
566552 | Exp AND Exp { VALID_OP ($1 , $3 , Operator::AND, @$); $$ = new ExpressionOp ($1 , $3 , Operator::AND); }
567- | NOT Exp { VALID_OP ($2 , $2 , Operator::NOT, @$); $$ = new ExpressionOp ($2 , $ 2 , Operator::NOT); }
553+ | NOT Exp { VALID_OP ($2 , $2 , Operator::NOT, @$); $$ = new ExpressionOp ($2 , nullptr , Operator::NOT); }
568554 | Exp EQ Exp { VALID_OP ($1 , $3 , Operator::equal, @$); $$ = new ExpressionOp ($1 , $3 , Operator::equal); }
569555 | Exp NE Exp { VALID_OP ($1 , $3 , Operator::not_equal, @$); $$ = new ExpressionOp ($1 , $3 , Operator::not_equal); }
570556 | Exp LT Exp { VALID_OP ($1 , $3 , Operator::less_than, @$); $$ = new ExpressionOp ($1 , $3 , Operator::less_than); }
@@ -573,7 +559,7 @@ Exp : STRING { $$ = new Value($1); }
573559 | Exp GT Exp { VALID_OP ($1 , $3 , Operator::greater_than, @$); $$ = new ExpressionOp ($1 , $3 , Operator::greater_than); }
574560 | LPAREN Exp RPAREN { $$ = $2 ; }
575561 | USERINPUT { $$ = new UserInput (); }
576- | SubCall Args RPAREN {
562+ | SubCall OptExpL RPAREN {
577563 if ($2 .size () != table->types ($1 ).first .size ()) {
578564 error (@2 , " wrong number of arguments for call to subroutine: " + $1 );
579565 YYERROR;
0 commit comments