From d989d193b75a686f7a0f731704abc3839c4e5ff4 Mon Sep 17 00:00:00 2001 From: bazina Date: Sun, 24 Dec 2023 14:56:16 +0200 Subject: [PATCH] ANYCC 29 - Add terminals to a terminals set. - Generate a md file that contains Predictive Table. - Call generateMarkdownTable in Parser. --- include/Parser/PredictiveTable.h | 3 +++ src/Parser/Parser.cpp | 1 + src/Parser/PredictiveTable.cpp | 46 ++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/include/Parser/PredictiveTable.h b/include/Parser/PredictiveTable.h index 001967e..9a9adfa 100644 --- a/include/Parser/PredictiveTable.h +++ b/include/Parser/PredictiveTable.h @@ -71,10 +71,13 @@ class PredictiveTable { */ void printPredictiveTable(); + void generateMarkdownTable(const std::string &outputFilePath); + private: std::unordered_map predictive_table; std::set non_terminals; + std::set terminals; std::unordered_map, CompareFirst>> computed_first_sets; std::unordered_map> computed_follow_sets; diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 85cf50c..579a552 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -40,6 +40,7 @@ void Parser::buildPredictiveTable() { predictiveTable->buildPredictiveTable(); std::cout << "\nPredictive Table:\n"; predictiveTable->printPredictiveTable(); + predictiveTable->generateMarkdownTable("../PredictiveTable.md"); } void Parser::buildPredictiveTopDownParser() { diff --git a/src/Parser/PredictiveTable.cpp b/src/Parser/PredictiveTable.cpp index 87c1d3a..3def57b 100644 --- a/src/Parser/PredictiveTable.cpp +++ b/src/Parser/PredictiveTable.cpp @@ -1,3 +1,4 @@ +#include #include "Parser/PredictiveTable.h" #include "constants.h" @@ -8,6 +9,7 @@ PredictiveTable::PredictiveTable( this->computed_first_sets = computed_first_sets; this->computed_follow_sets = computed_follow_sets; this->non_terminals = non_terminals; + this->terminals.insert("$"); } PredictiveTable::~PredictiveTable() { @@ -103,6 +105,7 @@ void PredictiveTable::insertProduction(const std::string &non_terminal, const st const Production &production, ParsingTableEntryType predictive_table_enum) { CellKey cell_key = CellKey(non_terminal, terminal); auto cell_value = new CellValue(production, predictive_table_enum); + terminals.insert(terminal); if (containsKey(non_terminal, terminal)) { std::cout << "\nGrammar isn't LL(1)\n"; printConflict(non_terminal, terminal, production); @@ -150,3 +153,46 @@ PredictiveTable::printConflict(const std::string &non_terminal, const std::strin } std::cout << "\n"; } + +// Function to generate a Markdown table +void PredictiveTable::generateMarkdownTable(const std::string &outputFilePath) { + std::ofstream outputFile(outputFilePath); + + // Write header row + outputFile << "| **Non-Terminal** |"; + for (const auto &terminal: terminals) { + if (terminal == "*") + outputFile << " __*__ |"; + else + outputFile << " **" << terminal << "** |"; + } + outputFile << "\n|------------------|"; + for (int i = 0; i < terminals.size(); ++i) { + outputFile << "------------|"; + } + outputFile << "\n"; + + // Iterate through non-terminals and terminals to fill in the table + for (const auto &non_terminal: non_terminals) { + outputFile << "| **" << non_terminal << "** |"; + for (const auto &terminal: terminals) { + const CellValue *cellValue = lookUp(non_terminal, terminal); + if (hasProduction(non_terminal, terminal)) { + const auto &production = cellValue->getProduction(); + std::string productionStr; + if (!production.productions.empty()) { + for (const auto &symbol: production.productions[0]) { + productionStr += symbol + " "; + } + productionStr.pop_back(); // Remove the extra space + } + outputFile << " `" << productionStr << "` |"; + } else if (isSynchronizing(non_terminal, terminal)) { + outputFile << " `Synch` |"; + } + } + outputFile << "\n"; + } + + outputFile.close(); +}