Skip to content

Commit 9e5b799

Browse files
committed
Fix unary operators (major bug), rewrite Args as ExpList and OptExpL, and code clean up for implementation of RecordT
1 parent 2f2f5b6 commit 9e5b799

File tree

4 files changed

+56
-82
lines changed

4 files changed

+56
-82
lines changed

Expression.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -282,19 +282,19 @@ class ArrayAssign : public Tree {
282282
}
283283
};
284284

285-
class ObjectAssign : public Tree {
286-
std::vector<std::string> fields;
285+
class RecordAssign : public Tree {
287286
std::string label;
288287
std::vector<Expression *> values;
288+
RecordT rec;
289289
public:
290-
ObjectAssign(std::vector<std::string>&& f, std::string_view l, std::vector<Expression *>&& v)
291-
: Tree(nullptr, nullptr), fields{ f }, label{ l }, values{ v } {}
290+
RecordAssign(std::string_view l, std::vector<Expression *>&& v, RecordT&& r)
291+
: Tree(nullptr, nullptr), label{ l }, values{ v }, rec{ r } {}
292292
virtual void emit() override {
293-
size_t v{ 0 };
293+
size_t i{ 0 };
294294
output << indent << label << " = { ";
295-
for (auto sep = ""; auto& f : fields) {
296-
output << sep << f << ": ";
297-
values.at(v++)->emit();
295+
for (auto sep = ""; auto& f : rec.first) {
296+
output << sep << f.first << ": ";
297+
values.at(i++)->emit();
298298
sep = ", ";
299299
}
300300
output << " };\n";

Symbol.hpp

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class Symbol {
6868
throw std::runtime_error("no such constant");
6969
}
7070
}
71-
ExpT value(std::string label) {
71+
const ExpT& value(std::string label) {
7272
if (auto iter = SymTab.find(subroutine + '.' + label); iter != SymTab.end()) {
7373
if (iter->second.index() == 1) {
7474
return std::get<ExpT>(iter->second);
@@ -92,7 +92,7 @@ class Symbol {
9292
ExpI fieldtype(const std::string& label, const std::string& field) {
9393
if (auto iter = SymTab.find(subroutine + '.' + label); iter != SymTab.end()) {
9494
if ((iter->second.index() == 1) && (static_cast<ExpI>(std::get<ExpT>(iter->second).index()) == ExpI::RecordT)) {
95-
for (const auto& recfield : std::get<RecordT>(std::get<ExpT>(iter->second))) {
95+
for (const auto& recfield : std::get<RecordT>(std::get<ExpT>(iter->second)).first) {
9696
if (recfield.first == field) {
9797
return recfield.second;
9898
}
@@ -104,7 +104,7 @@ class Symbol {
104104
ExpI fieldtype(const std::string& label, size_t field) {
105105
if (auto iter = SymTab.find(subroutine + '.' + label); iter != SymTab.end()) {
106106
if ((iter->second.index() == 1) && (static_cast<ExpI>(std::get<ExpT>(iter->second).index()) == ExpI::RecordT)) {
107-
const auto& recfield = std::get<RecordT>(std::get<ExpT>(iter->second));
107+
const auto& recfield = std::get<RecordT>(std::get<ExpT>(iter->second)).first;
108108
return recfield.at(field).second;
109109
}
110110
}
@@ -113,21 +113,12 @@ class Symbol {
113113
std::string fieldname(const std::string& label, size_t field) {
114114
if (auto iter = SymTab.find(subroutine + '.' + label); iter != SymTab.end()) {
115115
if ((iter->second.index() == 1) && (static_cast<ExpI>(std::get<ExpT>(iter->second).index()) == ExpI::RecordT)) {
116-
const auto& recfield = std::get<RecordT>(std::get<ExpT>(iter->second));
116+
const auto& recfield = std::get<RecordT>(std::get<ExpT>(iter->second)).first;
117117
return recfield.at(field).first;
118118
}
119119
}
120120
return "";
121121
}
122-
std::string record(const std::string& label) {
123-
if (auto iter = SymTab.find(subroutine + '.' + label); iter != SymTab.end()) {
124-
if ((iter->second.index() == 1) && (static_cast<ExpI>(std::get<ExpT>(iter->second).index()) == ExpI::ObjectT)) {
125-
const auto& obj = std::get<ObjectT>(std::get<ExpT>(iter->second));
126-
return static_cast<std::string>(obj);
127-
}
128-
}
129-
return "";
130-
}
131122
ExpI arraytype(const std::string& label) {
132123
if (auto iter = SymTab.find(subroutine + '.' + label); iter != SymTab.end()) {
133124
if ((iter->second.index() == 1) && (static_cast<ExpI>(std::get<ExpT>(iter->second).index()) == ExpI::Array2T)) {
@@ -169,7 +160,7 @@ class Decls : public Tree {
169160
if (s.second.index() == 2) {
170161
vars.push_back(s.first.substr(subroutine.length() + 1));
171162
}
172-
else if ((s.second.index() == 1) && (static_cast<ExpI>(std::get<ExpT>(s.second).index()) == ExpI::ObjectT)) {
163+
else if ((s.second.index() == 1) && (static_cast<ExpI>(std::get<ExpT>(s.second).index()) == ExpI::RecordT)) {
173164
vars.push_back(s.first.substr(subroutine.length() + 1));
174165
}
175166
else if ((s.second.index() == 1) && (static_cast<ExpI>(std::get<ExpT>(s.second).index()) == ExpI::Array2T)) {
@@ -209,7 +200,6 @@ class Decls : public Tree {
209200
output << " = []";
210201
break;
211202
case ExpI::RecordT:
212-
case ExpI::ObjectT:
213203
output << " = {}";
214204
break;
215205
default:
@@ -243,9 +233,8 @@ inline std::ostream& operator<<(std::ostream& os, const ExpT& expr) {
243233
case ExpI::Array2T:
244234
return os << "[]";
245235
case ExpI::RecordT:
246-
case ExpI::ObjectT:
247236
os << "{ ";
248-
for (auto sep = ""; const auto& field : std::get<RecordT>(expr)) {
237+
for (auto sep = ""; const auto& field : std::get<RecordT>(expr).first) {
249238
os << sep << field.first + ": ";
250239
switch (field.second) {
251240
case ExpI::BoolT:

SymbolTypes.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class String : public std::string {
88
: std::string(std::forward<Args>(args)...) {}
99
};
1010

11-
enum class ExpI { None, BoolT, IntT, RealT, StringT, ArrayT, Array2T, RecordT, ObjectT, SubroutineT };
11+
enum class ExpI { None, BoolT, IntT, RealT, StringT, ArrayT, Array2T, RecordT, SubroutineT };
1212

1313
const std::unordered_map<std::string,ExpI> ExpI_types{
1414
{ "Boolean", ExpI::BoolT },
@@ -22,14 +22,13 @@ using BoolT = bool;
2222
using IntT = int;
2323
using RealT = double;
2424
using StringT = String;
25-
using RecordT = std::vector<std::pair<std::string,ExpI>>;
26-
using ObjectT = std::string;
25+
using RecordT = std::pair<std::vector<std::pair<std::string,ExpI>>,bool>; // second field is true for definition, false for object
2726
using SubroutineT = std::pair<std::vector<std::pair<std::string,ExpI>>,ExpI>;
2827

2928
using ArrayT = std::vector<ExpI>;
3029
using Array2T = std::vector<std::variant<ExpI,ArrayT>>;
3130

32-
using ExpT = std::variant<std::monostate,BoolT,IntT,RealT,StringT,ArrayT,Array2T,RecordT,ObjectT,SubroutineT>;
31+
using ExpT = std::variant<std::monostate,BoolT,IntT,RealT,StringT,ArrayT,Array2T,RecordT,SubroutineT>;
3332
using SymbolT = std::variant<std::monostate,ExpT,ExpI>;
3433

3534
std::ostream& operator<<(std::ostream& os, const ExpT& expr);

grammar.y

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@
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

477466
Param : 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

512503
BoolExp : 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

Comments
 (0)