55
66namespace jucc ::parser {
77
8+ std::string ParsingTable::GenerateErrorMessage (const std::string &production, const std::string &symbol) {
9+ std::string ret;
10+ ret += " parsing table error: duplicate entry in parsing table, " ;
11+ ret += " production: " ;
12+ ret = ret.append (production);
13+ ret += " symbol: " ;
14+ ret = ret.append (symbol);
15+ return ret;
16+ }
17+
818void ParsingTable::BuildTable () {
919 // fill initially all errors
1020 for (auto &nt : non_terminals_) {
@@ -17,6 +27,9 @@ void ParsingTable::BuildTable() {
1727 for (auto &nt : non_terminals_) {
1828 if (follows_.count (nt) != 0U ) {
1929 for (const auto &symbol : follows_[nt]) {
30+ if (table_[nt][symbol] != std::string (ERROR_TOKEN)) {
31+ errors_.push_back (GenerateErrorMessage (nt, symbol));
32+ }
2033 table_[nt][symbol] = std::string (SYNCH_TOKEN);
2134 }
2235 }
@@ -27,32 +40,38 @@ void ParsingTable::BuildTable() {
2740 auto rules = productions_[prod_no].GetRules ();
2841 for (int rule_no = 0 ; rule_no < static_cast <int >(rules.size ()); rule_no++) {
2942 std::string first_entity = rules[rule_no].GetEntities ()[0 ];
30-
3143 // check if first_entity is terminal
3244 if (std::find (terminals_.begin (), terminals_.end (), first_entity) != terminals_.end ()) {
45+ std::string entry = table_[productions_[prod_no].GetParent ()][first_entity];
46+ if ((entry != std::string (ERROR_TOKEN)) && (entry != std::string (SYNCH_TOKEN))) {
47+ errors_.push_back (GenerateErrorMessage (productions_[prod_no].GetParent (), first_entity));
48+ }
49+
3350 table_[productions_[prod_no].GetParent ()][first_entity] = std::to_string (prod_no * 100 + rule_no);
3451 } else if (std::find (non_terminals_.begin (), non_terminals_.end (), first_entity) != non_terminals_.end ()) {
3552 // first entity is a non-terminal
3653 if (firsts_.count (first_entity) != 0U ) {
3754 for (auto &symbol : firsts_[first_entity]) {
3855 if (symbol != std::string (grammar::EPSILON)) {
39- table_[productions_[prod_no].GetParent ()][symbol] = std::to_string (prod_no * 100 + rule_no);
40- }
41- }
42- // if epsilon present add production under follow(A) symbols
43- if (std::find (firsts_[first_entity].begin (), firsts_[first_entity].end (), std::string (grammar::EPSILON)) !=
44- firsts_[first_entity].end ()) {
45- if (follows_.count (productions_[prod_no].GetParent ()) != 0U ) {
46- for (auto &symbol : follows_[productions_[prod_no].GetParent ()]) {
47- table_[productions_[prod_no].GetParent ()][symbol] = std::to_string (prod_no * 100 + rule_no);
56+ std::string entry = table_[productions_[prod_no].GetParent ()][symbol];
57+ if ((entry != std::string (ERROR_TOKEN)) && (entry != std::string (SYNCH_TOKEN))) {
58+ errors_.push_back (GenerateErrorMessage (productions_[prod_no].GetParent (), symbol));
4859 }
60+
61+ table_[productions_[prod_no].GetParent ()][symbol] = std::to_string (prod_no * 100 + rule_no);
4962 }
5063 }
5164 }
65+
5266 } else if (first_entity == std::string (grammar::EPSILON)) {
5367 // first entity is epsilon
5468 if (follows_.count (productions_[prod_no].GetParent ()) != 0U ) {
5569 for (auto &symbol : follows_[productions_[prod_no].GetParent ()]) {
70+ std::string entry = table_[productions_[prod_no].GetParent ()][symbol];
71+ if ((entry != std::string (ERROR_TOKEN)) && (entry != std::string (SYNCH_TOKEN))) {
72+ errors_.push_back (GenerateErrorMessage (productions_[prod_no].GetParent (), symbol));
73+ }
74+
5675 table_[productions_[prod_no].GetParent ()][symbol] = std::to_string (prod_no * 100 + rule_no);
5776 }
5877 }
0 commit comments