Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <fstream>
- #include <string>
- #include <vector>
- #include <map>
- #include <set>
- #include <stack>
- #include <functional>
- #include <sstream>
- #include <time.h>
- #include <memory>
- #define DEBUG true
- namespace parser_package
- {
- namespace _token
- {
- using namespace std;
- template <class IDENT = string, class VAL = int>
- struct token
- {
- VAL value;
- IDENT id;
- string lexeme;
- int col;
- int row;
- bool empty;
- token(IDENT id, string lexeme, VAL value, int col = 0, int row = 0);
- token(const token<IDENT, VAL>& other);
- token(token<IDENT, VAL>&& other);
- token(IDENT id);
- token();
- token<IDENT, VAL>& operator=(const token<IDENT, VAL>& other);
- token<IDENT, VAL>& operator=(token<IDENT, VAL>&& other);
- string to_string();
- };
- template <class IDENT, class VAL>
- token<IDENT, VAL>::token(IDENT id, string lexeme, VAL value, int col, int row)
- {
- this->id = id;
- this->lexeme = lexeme;
- this->value = value;
- this->col = col;
- this->row = row;
- this->empty = false;
- }
- template<class IDENT, class VAL>
- token<IDENT, VAL>::token(const token<IDENT, VAL>& other)
- {
- this->id = other.id;
- this->lexeme = other.lexeme;
- this->value = other.value;
- this->col = other.col;
- this->row = other.row;
- this->empty = other.empty;
- }
- template<class IDENT, class VAL>
- token<IDENT, VAL>::token(token<IDENT, VAL>&& other)
- {
- this->id = other.id;
- this->lexeme = other.lexeme;
- this->value = other.value;
- this->col = other.col;
- this->row = other.row;
- this->empty = other.empty;
- }
- template<class IDENT, class VAL>
- token<IDENT, VAL>::token(IDENT id)
- {
- this->id = id;
- this->lexeme = string();
- this->value = VAL();
- this->col = -1;
- this->row = -1;
- this->empty = false;
- }
- template<class IDENT, class VAL>
- token<IDENT, VAL>::token()
- {
- this->id = IDENT();
- this->value = VAL();
- this->lexeme = string();
- this->col = 0;
- this->row = 0;
- this->empty = true;
- }
- template<class IDENT, class VAL>
- token<IDENT, VAL>& token<IDENT, VAL>::operator=(const token<IDENT, VAL>& other)
- {
- this->id = other.id;
- this->lexeme = other.lexeme;
- this->value = other.value;
- this->col = other.col;
- this->row = other.row;
- this->empty = other.empty;
- return *this;
- }
- template<class IDENT, class VAL>
- token<IDENT, VAL>& token<IDENT, VAL>::operator=(token<IDENT, VAL>&& other)
- {
- this->id = other.id;
- this->lexeme = other.lexeme;
- this->value = other.value;
- this->col = other.col;
- this->row = other.row;
- this->empty = other.empty;
- return *this;
- }
- template<class IDENT, class VAL>
- string token<IDENT, VAL>::to_string()
- {
- stringstream temp;
- if (empty)
- return "empty\n";
- temp << "id: " << id << endl;
- temp << "lexeme: " << lexeme << endl;
- temp << "value: " << value << endl;
- temp << "row:col " << row << " : " << col << endl;
- return temp.str();
- }
- }
- namespace _terminal
- {
- using namespace std;
- using namespace _token;
- template <class IDENT = string, class VAL = int>
- class terminal
- {
- vector<string> symbols;
- bool using_symbols;
- protected:
- function<VAL(const string&)> get_value;
- function<token<IDENT, VAL>(const string&, int)> comparison;
- public:
- IDENT id;
- terminal(IDENT id, vector<string> list = vector<string>(), function<VAL(const string&)> get_value = [](const string& str) -> int { return int(); });
- terminal(IDENT id, function<token<IDENT, VAL>(const string&, int)>, function<VAL(const string&)> get_value = [](const string& str) -> int { return int(); });
- terminal(terminal<IDENT, VAL>& other) = delete;
- terminal(terminal<IDENT, VAL>&& other) = delete;
- virtual token<IDENT, VAL> compare(const string& str, int pos);
- };
- template <class IDENT, class VAL>
- terminal<IDENT, VAL>::terminal(IDENT id, vector<string> list, function<VAL(const string&)> get_value)
- {
- this->id = move(id);
- this->symbols = move(list);
- this->get_value = move(get_value);
- this->using_symbols = true;
- }
- template<class IDENT, class VAL>
- terminal<IDENT, VAL>::terminal(IDENT id, function<token<IDENT, VAL>(const string&, int)> comparison, function<VAL(const string&)> get_value)
- {
- this->id = move(id);
- this->comparison = move(comparison);
- this->get_value = move(get_value);
- this->using_symbols = false;
- }
- template <class IDENT, class VAL>
- token<IDENT, VAL> terminal<IDENT, VAL>::compare(const string& str, int pos)
- {
- if (this->using_symbols)
- {
- for (auto& t : symbols)
- if (str.find(t, pos) == pos)
- return token<IDENT, VAL>(this->id, t, get_value(t), pos, -1);
- return token<IDENT, VAL>();
- }
- else
- return comparison(str, pos);
- }
- }
- namespace _nonterminal
- {
- using namespace _terminal;
- template <class IDENT = string>
- class nonterminal
- {
- vector<vector<IDENT>> variants;
- public:
- IDENT id;
- nonterminal(IDENT id, vector<vector<IDENT>> templates = vector<vector<IDENT>>());
- nonterminal(nonterminal<IDENT>& other) = delete;
- nonterminal(nonterminal<IDENT>&& other) = delete;
- const vector<vector<IDENT>>& templates();
- nonterminal<IDENT>& operator+=(vector<IDENT> templates);
- };
- template<class IDENT>
- nonterminal<IDENT>::nonterminal(IDENT id, vector<vector<IDENT>> templates)
- {
- this->id = id;
- this->variants = move(templates);
- }
- template<class IDENT>
- const vector<vector<IDENT>>& nonterminal<IDENT>::templates()
- {
- return variants;
- }
- template<class IDENT>
- nonterminal<IDENT>& nonterminal<IDENT>::operator+=(vector<IDENT> templates)
- {
- variants.emplace_back(move(templates));
- return *this;
- }
- }
- namespace _tree
- {
- using namespace std;
- #define DEFAULT_TREE_SIZE 256
- template<class T>
- class node
- {
- T value;
- vector<node<T>*> relations;
- public:
- int level;
- int span;
- node<T>& run(function<void(int, T&)>& action = function<void(int, T&)>([](int depth, T& t) -> void { return; }));
- node();
- node(T t, int level = 0, int span = 0);
- node(const node<T>&) = delete;
- node(node<T>&&);
- ~node();
- T& val();
- vector<node<T>*>& rel();
- node<T>& operator<<(node<T>* temp);
- node<T>& operator=(node<T>&& temp);
- node<T>& operator=(const node<T>& temp) = delete;
- };
- template<class T>
- node<T>& node<T>::run(function<void(int, T&)>& action)
- {
- action(this->level, this->value);
- for (auto& t : this->relations)
- if (t != nullptr && t != NULL)
- t->run(action);
- return *this;
- }
- template<class T>
- node<T>::node()
- {
- this->value = T();
- this->level = 0;
- this->span = 0;
- }
- template<class T>
- node<T>::node(T t, int level, int span)
- {
- this->value = t;
- this->level = level;
- this->span = span;
- }
- template<class T>
- node<T>::node(node<T>&& other)
- {
- this->value = move(other.value);
- this->relations = move(other.relations);
- this->level = other.level;
- this->span = other.span;
- other.value = T();
- other.level = 0;
- other.span = 0;
- }
- template<class T>
- node<T>::~node()
- {
- }
- template<class T>
- T & node<T>::val()
- {
- return value;
- }
- template<class T>
- vector<node<T>*>& node<T>::rel()
- {
- return relations;
- }
- template<class T>
- node<T>& node<T>::operator<<(node<T>* temp)
- {
- this->span += temp->span;
- this->relations.emplace_back(temp);
- return *this;
- }
- template<class T>
- node<T>& node<T>::operator=(node<T>&& other)
- {
- this->value = move(other.value);
- this->relations = move(other.relations);
- this->level = other.level;
- this->span = other.span;
- other.value = T();
- other.level = 0;
- other.span = 0;
- return *this;
- }
- template<class T, class Allocator = allocator<node<T>>>
- class basic_tree
- {
- Allocator alloc;
- size_t top;
- size_t size;
- vector<pair<size_t, node<T>*>> heap;
- void reserve_some();
- public:
- node<T>* root;
- basic_tree();
- basic_tree(const basic_tree&) = delete;
- basic_tree(basic_tree&&);
- ~basic_tree();
- bool empty();
- template<class... Args> node<T>* new_node(Args&&... args);
- node<T>& run(node<T>* root, function<void(int, T&)>& action);
- basic_tree<T, Allocator>& operator=(basic_tree<T, Allocator>&&);
- basic_tree<T, Allocator>& operator=(const basic_tree<T, Allocator>&) = delete;
- };
- template<class T, class Allocator>
- void basic_tree<T, Allocator>::reserve_some()
- {
- top = 0;
- size = heap.back().first * 2;
- heap.emplace_back(size, alloc.allocate(size));
- }
- template<class T, class Allocator>
- basic_tree<T, Allocator>::basic_tree()
- {
- this->top = 0;
- this->size = DEFAULT_TREE_SIZE;
- this->heap.emplace_back(this->size, this->alloc.allocate(this->size));
- this->root = nullptr;
- }
- template<class T, class Allocator>
- basic_tree<T, Allocator>::basic_tree(basic_tree && other)
- {
- this->alloc = move(other.alloc);
- this->heap = move(other.heap);
- this->top = other.top;
- this->size = other.size;
- this->root = other.root;
- other.top = 0;
- other.size = DEFAULT_TREE_SIZE;
- other.heap.emplace_back(other.size, other.alloc.allocate(other.size));
- other.root = nullptr;
- }
- template<class T, class Allocator>
- basic_tree<T, Allocator>& basic_tree<T, Allocator>::operator=(basic_tree<T, Allocator>&& other)
- {
- this->alloc = move(other.alloc);
- this->heap = move(other.heap);
- this->top = other.top;
- this->size = other.size;
- this->root = other.root;
- other.top = 0;
- other.size = DEFAULT_TREE_SIZE;
- other.heap.emplace_back(other.size, other.alloc.allocate(other.size));
- other.root = nullptr;
- }
- template<class T, class Allocator>
- basic_tree<T, Allocator>::~basic_tree()
- {
- for (int j = 0; j < heap.size() - 1; j++)
- {
- for (size_t i = 0; i < heap[j].first; i++)
- alloc.destroy(heap[j].second + i);
- alloc.deallocate(heap[j].second, heap[j].first);
- }
- for (int i = 0; i < top; i++)
- alloc.destroy(heap.back().second + i);
- alloc.deallocate(heap.back().second, size);
- }
- template<class T, class Allocator>
- bool basic_tree<T, Allocator>::empty()
- {
- return this->root == nullptr;
- }
- template<class T, class Allocator>
- node<T>& basic_tree<T, Allocator>::run(node<T>* root, function<void(int, T&)>& action)
- {
- action(root->level, root->value);
- for (auto& t : root->relations)
- if (t != nullptr && t != NULL)
- run(action, t);
- return *root;
- }
- template<class T, class Allocator>
- template<class ... Args>
- node<T>* basic_tree<T, Allocator>::new_node(Args && ...args)
- {
- if (top >= size)
- reserve_some();
- auto temp = heap.back().second + top++;
- alloc.construct(temp, forward<Args>(args)...);
- return temp;
- }
- }
- namespace _parser
- {
- using namespace std;
- using namespace _terminal;
- using namespace _nonterminal;
- using namespace _tree;
- template<class IDENT = string, class VAL = int>
- class parser
- {
- terminal<IDENT, VAL>* epsilon_symbol;
- map<IDENT, terminal<IDENT, VAL>*> terminals;
- map<IDENT, nonterminal<IDENT>*> nonterminals;
- public:
- parser(terminal<IDENT, VAL>*);
- ~parser();
- vector<token<IDENT, VAL>> lexify(const string& str);
- node<token<IDENT, VAL>>* analize(basic_tree<token<IDENT, VAL>>& parse_tree, IDENT id, typename vector<token<IDENT, VAL>>::iterator iter, int lvl);
- basic_tree<token<IDENT, VAL>> parse(const string& str, const nonterminal<IDENT>& axiome);
- parser<IDENT, VAL>& operator<<(terminal<IDENT, VAL>* temp);
- parser<IDENT, VAL>& operator<<(nonterminal<IDENT>* temp);
- };
- template<class IDENT, class VAL>
- parser<IDENT, VAL>::parser(terminal<IDENT, VAL>* epsilon_symbol)
- {
- if (epsilon_symbol == NULL || epsilon_symbol == nullptr)
- throw string("Nope");
- this->epsilon_symbol = epsilon_symbol;
- }
- template<class IDENT, class VAL>
- parser<IDENT, VAL>::~parser()
- {
- }
- template<class IDENT, class VAL>
- node<token<IDENT, VAL>>* parser<IDENT, VAL>::analize(basic_tree<token<IDENT, VAL>>& parse_tree, IDENT id, typename vector<token<IDENT, VAL>>::iterator iter, int lvl)
- {
- if (id == epsilon_symbol->id)
- return parse_tree.new_node(token<IDENT, VAL>(epsilon_symbol->id, "", -1, iter->row, iter->col), lvl, 0);
- if (terminals.count(id) != 0)
- {
- if (id == iter->id)
- return parse_tree.new_node(*iter, lvl, 1);
- else
- return nullptr;
- }
- else if (nonterminals.count(id) != 0)
- {
- nonterminal<IDENT>* templates = nonterminals[id];
- for (auto& j : templates->templates())
- {
- bool f = false;
- token<IDENT, VAL> tok = token<IDENT, VAL>(id);
- node<token<IDENT, VAL>>* res = parse_tree.new_node(tok, lvl, 0),
- *temp = nullptr;
- for (auto& t : j)
- {
- temp = analize(parse_tree, t, iter + res->span, lvl + 1);
- f |= temp == nullptr;
- if (temp == nullptr)
- break;
- else
- *res << temp;
- }
- if (!f)
- return res;
- }
- return nullptr;
- }
- else
- {
- stringstream out;
- out << "syntax analysis failed at: " << iter->id << endl << iter->to_string();
- throw out.str();
- }
- }
- template<class IDENT, class VAL>
- vector<token<IDENT, VAL>> parser<IDENT, VAL>::lexify(const string& str)
- {
- vector<token<IDENT, VAL>> tokens;
- int pos = 0, col = 0, row = 0;
- bool f = false;
- for (; pos < str.size(); f = false)
- {
- if (str[pos] == ' ')
- {
- pos++;
- col++;
- continue;
- }
- if (str[pos] == '\n')
- {
- col = 0;
- row++;
- continue;
- }
- for (const auto& t : terminals)
- {
- token<IDENT, VAL> temp = t.second->compare(str, pos);
- f |= !temp.empty;
- if (f)
- {
- temp.col = col;
- temp.row = row;
- tokens.push_back(temp);
- pos += temp.lexeme.size();
- col += temp.lexeme.size();
- break;
- }
- }
- if (!f)
- {
- stringstream out;
- out << "lexical analysis failed at " << row << ":" << col;
- throw out.str();
- }
- }
- token<IDENT, VAL> temp = epsilon_symbol->compare(str, pos);
- if (!temp.empty)
- {
- temp.col = col;
- temp.row = row;
- tokens.push_back(temp);
- pos += temp.lexeme.size();
- col += temp.lexeme.size();
- }
- else
- {
- stringstream out;
- out << "lexical analysis failed at " << row << ":" << col << endl << "epsylon symbol not found";
- throw out.str();
- }
- return move(tokens);
- }
- template<class IDENT, class VAL>
- basic_tree<token<IDENT, VAL>> parser<IDENT, VAL>::parse(const string& str, const nonterminal<IDENT>& axiome)
- {
- vector<token<IDENT, VAL>> tokens;
- basic_tree<token<IDENT, VAL>> parse_tree;
- tokens = move(lexify(str));
- typename vector<token<IDENT, VAL>>::iterator iter = tokens.begin();
- parse_tree.root = analize(parse_tree, axiome.id, iter, 0);
- if (parse_tree.empty())
- throw string("syntax analisys failed at: tree is empty");
- if (iter + parse_tree.root->span + 1 != tokens.end())
- throw string("syntax analisys failed at:\n\n" + iter[parse_tree.root->span].to_string() + "\nexpected:\n\n" + tokens.back().to_string());
- return move(parse_tree);
- }
- template<class IDENT, class VAL>
- parser<IDENT, VAL>& parser<IDENT, VAL>::operator<<(terminal<IDENT, VAL>* temp)
- {
- terminals[temp->id] = temp;
- return *this;
- }
- template<class IDENT, class VAL>
- parser<IDENT, VAL>& parser<IDENT, VAL>::operator<<(nonterminal<IDENT>* temp)
- {
- nonterminals[temp->id] = temp;
- return *this;
- }
- }
- }
- using namespace std;
- using namespace parser_package;
- using namespace _token;
- using namespace _terminal;
- using namespace _nonterminal;
- using namespace _parser;
- /*
- <function> ::= <ident> ( <formal-args-list> ) := <expr> ;
- <formal-args-list> ::= <ident-list> | e
- <ident-list> ::= <ident> <ident-list'>
- <ident-list'> ::= , <ident-list> | e
- <expr> ::= <comparison_expr> <expr'>
- <expr'> ::= ? <comparison_expr> : <expr> | e
- <comparison_expr> ::= <arith_expr> <comparison_expr'>
- <comparison_expr'> ::= <comparison_op> <arith_expr> | e
- <comparison_op> ::= = | <> | < | > | <= | >=
- <arith_expr> ::= <term> <arith_expr'>
- <arith_expr'> ::= + <term> <arith_expr''> | - <term> <arith_expr''> | e
- <arith_expr''> := <arith_expr'> | e
- <term> ::= <factor> <term'>
- <term'> ::= * <factor> <term''> | / <factor> <term''> | e
- <term''> ::= <term'> | e
- <factor> ::= <number> | <ident> <factor'> | ( <expr> ) | - <factor>
- <factor'> ::= ( <actual_args_list> ) | e
- <actual_args_list> ::= <expr-list> | e
- <expr-list> ::= <expr> <expr-list'>
- <expr-list'> ::= , <expr-list> | e
- */
- bool is_alphabetic(char c)
- {
- return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
- }
- bool is_numeral(char c)
- {
- return c >= '0' && c <= '9';
- }
- class Func
- {
- public:
- set<string> incident;
- int argc;
- set<string>* argv;
- vector<pair<string, int>>* inc_calls;
- Func();
- ~Func();
- void dispose();
- Func& operator<<(string str);
- };
- Func::Func()
- {
- this->argv = new set<string>();
- this->inc_calls = new vector<pair<string, int>>();
- }
- Func::~Func()
- {
- this->dispose();
- }
- void Func::dispose()
- {
- if (this->argv != nullptr && this->argv != NULL)
- delete this->argv, this->argv = nullptr;
- if (this->inc_calls != nullptr && this->inc_calls != NULL)
- delete this->inc_calls, this->inc_calls = nullptr;
- }
- Func & Func::operator<<(string str)
- {
- this->argv->insert(str);
- return *this;
- }
- int count_args(node<token<string, int>>* t)
- {
- if (t->val().id == "ident-list" || t->val().id == "expr-list")
- return 1 + count_args(t->rel()[1]);
- if ((t->val().id == "ident-list'" || t->val().id == "expr-list'") && t->rel()[0]->val().id != "epsilon")
- return count_args(t->rel()[1]);
- return 0;
- }
- void _run(node<token<string, int>>* t, Func* func)
- {
- auto inc = t->rel();
- if (t->val().id == "factor" && inc[0]->val().id == "ident")
- {
- if (inc[1]->rel()[0]->val().id == "epsilon")
- {
- if (func->argv->count(inc[0]->val().lexeme) == 0)
- throw string("unidentified identificator");
- }
- else if (inc[1]->rel()[1]->val().id == "actual_args_list")
- {
- func->incident.insert(inc[0]->val().lexeme);
- func->inc_calls->emplace_back(inc[0]->val().lexeme, count_args(inc[1]->rel()[1]->rel()[0]));
- for (auto& i : inc[1]->rel()[1]->rel())
- if (i != nullptr && i != NULL)
- _run(i, func);
- }
- }
- else
- for (auto& i : t->rel())
- if (i != nullptr && i != NULL)
- _run(i, func);
- }
- void analize(node<token<string, int>>* root, map<string, Func*>& matr)
- {
- auto func = root->rel()[0]->val().lexeme;
- auto args = root->rel()[2];
- auto body = root->rel()[5];
- matr[func] = new Func();
- matr[func]->argc = count_args(args->rel()[0]);
- auto action = function<void(int, token<string, int>&)>([&matr, &func](int depth, token<string, int>& t) -> void
- {
- if (t.id == "ident")
- *matr[func] << t.lexeme;
- });
- args->run(action);
- _run(body, matr[func]);
- }
- void check_calls(map<string, Func*>& matr)
- {
- for (auto& p : matr)
- for (auto& t : *p.second->inc_calls)
- {
- if (matr.count(t.first) == 0)
- throw string("usage of undeclared function");
- if (matr[t.first]->argc != t.second)
- throw string("argument quantity mismatch");
- }
- }
- void parse(istream& fin, vector<vector<int>>& vertices)
- {
- terminal<>
- num("number", [](const string & str, int pos) -> token<string, int>
- {
- int i = pos;
- if (!is_numeral(str[i++]))
- return token<>();
- for (; i < str.size() && is_numeral(str[i]); i++);
- string t = str.substr(pos, i - pos);
- return token<>("number", t, stoi(t), -1, -1);
- }),
- ident("ident", [](const string & str, int pos) -> token<string, int>
- {
- int i = pos;
- if (!is_alphabetic(str[i++]))
- return token<>();
- for (; i < str.size() && (is_alphabetic(str[i]) || is_numeral(str[i])); i++);
- string t = str.substr(pos, i - pos);
- return token<>("ident", t, -1, -1, -1);
- }),
- eps("epsilon", [](const string & str, int pos) -> token<string, int>
- {
- return token<>("epsilon", "", 1, pos, -1);
- }),
- cln(":", [](const string & str, int pos) -> token<string, int>
- {
- if (pos < str.size() && str[pos] == ':' && (pos + 1 >= str.size() || str[pos + 1] != '='))
- return token<>(":", ":", -1, -1, -1);
- else
- return token<>();
- }),
- sless("<", [](const string & str, int pos) -> token<string, int>
- {
- if (pos < str.size() && str[pos] == '<' && (pos + 1 >= str.size() || (str[pos + 1] != '=' && str[pos + 1] != '>')))
- return token<>("<", "<", -1, -1, -1);
- else
- return token<>();
- }),
- snless(">", [](const string & str, int pos) -> token<string, int>
- {
- if (pos < str.size() && str[pos] == '>' && (pos + 1 >= str.size() || str[pos + 1] != '='))
- return token<>(">", ">", -1, -1, -1);
- else
- return token<>();
- }),
- plus("+", { "+" }),
- minus("-", { "-" }),
- mul("*", { "*" }),
- div("/", { "/" }),
- less("<=", { "<=" }),
- nless(">=", { ">=" }),
- eq("=", { "=" }),
- neq("<>", { "<>" }),
- ceq(":=", { ":=" }),
- qs("?", { "?" }),
- com(",", { "," }),
- sclm(";", { ";" }),
- lbr("(", { "(" }),
- rbr(")", { ")" });
- nonterminal<>
- func("function"),
- fal("formal-args-list"),
- idls("ident-list"),
- idlsm("ident-list'"),
- expr("expr"),
- exprm("expr'"),
- cexpr("comparison_expr"),
- cexprm("comparison_expr'"),
- cop("comparison_op"),
- aexpr("arith_expr"),
- aexprm("arith_expr'"),
- aexprmm("arith_expr''"),
- term("term"),
- termm("term'"),
- termmm("term''"),
- fact("factor"),
- factm("factor'"),
- acargls("actual_args_list"),
- exprls("expr-list"),
- exprlsm("expr-list'");
- func += { "ident", "(", "formal-args-list", ")", ":=", "expr", ";" };
- fal += { "ident-list" };
- fal += { "epsilon" };
- idls += { "ident", "ident-list'" };
- idlsm += { ",", "ident-list" };
- idlsm += { "epsilon" };
- expr += { "comparison_expr", "expr'" };
- exprm += { "?", "comparison_expr", ":", "expr" };
- exprm += { "epsilon" };
- cexpr += { "arith_expr", "comparison_expr'" };
- cexprm += { "comparison_op", "arith_expr" };
- cexprm += { "epsilon" };
- cop += { "=" };
- cop += { "<>" };
- cop += { "<" };
- cop += { ">" };
- cop += { "<=" };
- cop += { ">=" };
- aexpr += { "term", "arith_expr'" };
- aexprm += { "+", "term", "arith_expr''" };
- aexprm += { "-", "term", "arith_expr''" };
- aexprm += { "epsilon" };
- aexprmm += { "arith_expr'" };
- aexprmm += { "epsilon" };
- term += { "factor", "term'" };
- termm += { "*", "factor", "term''" };
- termm += { "/", "factor", "term''" };
- termm += { "epsilon" };
- termmm += { "term'" };
- termmm += { "epsilon" };
- fact += { "number" };
- fact += { "ident", "factor'" };
- fact += { "(", "expr", ")" };
- fact += { "-", "factor" };
- factm += { "(", "actual_args_list", ")" };
- factm += { "epsilon" };
- acargls += { "expr-list" };
- acargls += { "epsilon" };
- exprls += { "expr", "expr-list'" };
- exprlsm += { ",", "expr-list" };
- exprlsm += { "epsilon" };
- parser<string, int> p(&eps);
- p << &num << &ident << &cln;
- p << &plus << &minus << &mul << &div << &sless << &less << &snless << &nless << &eq << &neq << &ceq << &qs << &com << &sclm << &lbr << &rbr;
- p << &func << &fal << &idls << &idlsm << &expr << &exprm << &cexpr << &cexprm << &cop << &aexpr << &aexprm << &aexprmm << &term << &termm << &termmm << &fact << &factm << &acargls << &exprls << &exprlsm;
- map<string, Func*> matr;
- string temp;
- try
- {
- for (; !fin.eof(); )
- {
- getline(fin, temp);
- if (temp == "" || temp == "\n" || temp == "\0")
- continue;
- auto result = p.parse(temp, func);
- analize(result.root, matr);
- }
- check_calls(matr);
- }
- catch (string str)
- {
- for (auto& p : matr)
- delete p.second;
- throw str;
- }
- int i = 0;
- for (auto& p : matr)
- {
- p.second->dispose();
- p.second->argc = i++;
- }
- vertices.reserve(matr.size());
- for (auto& p : matr)
- {
- vertices.emplace_back();
- vertices[p.second->argc].reserve(p.second->incident.size());
- for (auto& t : p.second->incident)
- vertices[p.second->argc].emplace_back(matr[t]->argc);
- }
- for (auto& p : matr)
- delete p.second;
- }
- int timer = 1;
- int counter = 1;
- struct vertex
- {
- int t1;
- int comp;
- int low;
- vertex(int t1 = 0, int comp = 0, int low = 0);
- };
- vertex::vertex(int t1, int comp, int low)
- {
- this->t1 = t1;
- this->comp = comp;
- this->low = low;
- }
- void visit_vertex(vector<vector<int>>& matr, vector<vertex>& data, int v, stack<int>& s)
- {
- data[v].t1 = data[v].low = timer++;
- s.push(v);
- for (auto& u : matr[v])
- {
- if (data[u].t1 == 0)
- visit_vertex(matr, data, u, s);
- if (data[u].comp == 0 && data[v].low > data[u].low)
- data[v].low = data[u].low;
- }
- if (data[v].t1 == data[v].low)
- {
- int u;
- do
- {
- u = s.top();
- s.pop();
- data[u].comp = counter;
- } while (u != v);
- counter++;
- }
- }
- int tarjan(vector<vector<int>>& matr)
- {
- stack<int> s;
- vector<vertex> data(matr.size(), vertex());
- for (int t = 0; t < matr.size(); t++)
- if (data[t].t1 == 0)
- visit_vertex(matr, data, t, s);
- return counter - 1;
- }
- int main(int argc, char** argv)
- {
- time_t timer = clock();
- ifstream fin("input.txt");
- //auto& fin = cin;
- vector<vector<int>> matr;
- try
- {
- parse(fin, matr);
- }
- catch (string str)
- {
- if (DEBUG) cout << str << endl;
- cout << "error" << endl;
- if (DEBUG) system("PAUSE");
- return 0;
- }
- cout << tarjan(matr) << endl;
- cout << (clock() - timer) / CLOCKS_PER_SEC << "s " << (clock() - timer) % CLOCKS_PER_SEC << "ms " << endl;
- fin.close();
- if (DEBUG) system("PAUSE");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement