Advertisement
Guest User

Untitled

a guest
Apr 9th, 2020
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.69 KB | None | 0 0
  1. #include <string>
  2. #include <vector>
  3. #include <fstream>
  4. #include <iostream>
  5. using namespace std;
  6.  
  7.  
  8. const int default_hash = 100;
  9.  
  10.  
  11.  
  12.  
  13. // ТАБЛИЦЫ
  14.  
  15.  
  16. // Пара - индексы элемента в таблице идентификаторов
  17. struct id_pair {
  18.    int hash;
  19.    int id;
  20. };
  21.  
  22.  
  23. // Структура одного элемента переменной таблицы
  24. struct elem {
  25.    string name;
  26.    bool type;
  27.    bool data;
  28. };
  29.  
  30.  
  31. // Структура для подсчета токенов / строк / символов
  32. struct errorposition
  33. {
  34.    int symcount = 0;
  35.    int linecount = 1;
  36. } errpos;
  37.  
  38.  
  39. // Класс постоянных таблиц
  40. class constantTable {
  41. public:
  42.    vector<string> table;
  43.    int find(string name) { // возвращает id ключевого слова либо -1
  44.       if (name.length() > 0)
  45.          for (int i = 0; i < table.size(); i++)
  46.             if (table[i] == name)
  47.                return i;
  48.       return -1;
  49.    }
  50.    constantTable(vector<string> tab) {
  51.       table = tab;
  52.    }
  53. private:
  54.    /*vector<string> table;*/
  55. } words({ "if", "else", "int" }), sep({ ";", ",", "(", ")" }), ops({ "=", "+", "-", "*", "<", "==", "!=" });
  56.  
  57.  
  58. // Класс констант
  59. class Constants {
  60. public:
  61.    vector<int> consts;
  62.    int find_add(int constant) { // поиск или добавление, возвращает ИД
  63.       int i = 0;
  64.       for (; i < consts.size(); i++)
  65.          if (constant == consts[i])
  66.             return i;
  67.       consts.push_back(constant);
  68.       return i;
  69.    }
  70. private:
  71.    /*vector<int> consts;*/
  72. } cs;
  73.  
  74.  
  75. // Класс идентификаторов
  76. class Identificators {
  77. public:
  78.    vector<vector<elem>> table{ default_hash, vector<elem>() };
  79.    id_pair find_add(string ident) { // поиск или добавление, возвращает пару
  80.       id_pair p;
  81.       p.hash = hashFun(ident);
  82.       if (ident.length() > 0) {
  83.          for (int i = 0; i < table[p.hash].size(); i++)
  84.             if (ident == table[p.hash][i].name) {
  85.                p.id = i;
  86.                return p;
  87.             }
  88.          elem el;
  89.          el.name = ident;
  90.          el.data = 0;
  91.          el.type = 0;
  92.          table[p.hash].push_back(el);
  93.          p.id = table[p.hash].size() - 1;
  94.          return p;
  95.       }
  96.    }
  97.    string find(id_pair p) { // поиск названия по ИД
  98.       for (int i = 0; i < table[p.hash].size(); i++)
  99.          if (i == p.id)
  100.             return table[p.hash][i].name;
  101.       return "";
  102.    }
  103.    bool set_type(id_pair p, int state = 1) {  // вернет 0, если установка типа прошла успешно, в противном случае вернет 1
  104.       if (p.id >= table[p.hash].size()) {
  105.          table[p.hash][p.id].type = state;
  106.          return 0;
  107.       }
  108.       return 1;
  109.    }
  110.    int get_type(id_pair p) {  // вернет состояние типа или -1
  111.       if (p.id >= table[p.hash].size())
  112.          return table[p.hash][p.id].type;
  113.       return -1;
  114.    }
  115.    bool set_data(id_pair p, int state = 1) {
  116.       if (p.id >= table[p.hash].size()) {
  117.          table[p.hash][p.id].data = state;
  118.          return 0;
  119.       }
  120.       return 1;
  121.    }
  122.    int get_data(id_pair p) {
  123.       if (p.id >= table[p.hash].size())
  124.          return table[p.hash][p.id].data;
  125.       return -1;
  126.    }
  127. private:
  128.    /*vector<vector<elem>> table{ default_hash, vector<elem>() };*/
  129.    int hashFun(string str) {
  130.       int hash = 0;
  131.       for (int i = 0; i < str.size(); i++)
  132.          hash += str[i];
  133.       return hash % default_hash;
  134.    }
  135. } id;
  136.  
  137.  
  138.  
  139.  
  140. // ПОДПРОГРАММЫ ЛЕКСИЧЕСКОГО АНАЛИЗАТОРА
  141.  
  142.  
  143. // Проверка на букву
  144. bool isletter(char sym)
  145. {
  146.    if (sym >= 65 && sym <= 90 || sym >= 97 && sym <= 122)
  147.       return true;
  148.    return false;
  149. }
  150.  
  151.  
  152. // Проверка на цифру
  153. bool isdigit(char sym, char& pastsym)
  154. {
  155.    if (sym >= 48 && sym <= 57)
  156.       return true;
  157.    return false;
  158. }
  159.  
  160.  
  161. // Проверка на знак
  162. bool issign(char sym, char& pastsym)
  163. {
  164.    if (sym == '-')
  165.    {
  166.       pastsym = '-';
  167.       return true;
  168.    }
  169.    return false;
  170. }
  171.  
  172.  
  173. // Обработка разделителей. Односимвольный токен, либо слово
  174. void sepwork(vector<vector<int>>& mas, char sym, char& pastsym, ofstream& errors, int& commentstatus, int& state, string& token)
  175. {
  176.    token = "";
  177.    string tmp(1, sym);
  178.    switch (sym)
  179.    {
  180.    case '\n':
  181.       errpos.linecount++;
  182.       errpos.symcount = 0;
  183.       state = 0;
  184.       break;
  185.    case '-':
  186.       if (mas.size() > 0 && (mas[mas.size() - 1][0] == 3 || mas[mas.size() - 1][0] == 4))
  187.       {
  188.          mas.push_back({ 2, ops.find("-"), 0 });
  189.          state = 0;
  190.       }
  191.       else
  192.       {
  193.          token = sym;
  194.          state = 2;
  195.       }
  196.       break;
  197.    case '=':
  198.    case '!':
  199.    case '/':
  200.    case '*':
  201.       pastsym = sym;
  202.       state = 0;
  203.       break;
  204.    case '\t':
  205.    case ' ':
  206.       state = 0;
  207.       break;
  208.    default:
  209.       int sepid = sep.find(tmp), opsid = ops.find(tmp);
  210.       if (sepid != -1)  // Если символ в таблице разделителей
  211.          mas.push_back({ 1, sepid, 0 });
  212.       else if (opsid != -1)  // Если символ в таблице операторов / операций
  213.          mas.push_back({ 2, opsid, 0 });
  214.       else
  215.          errors << "Indefined symbol " << sym << " after " << mas.size() << " token in "
  216.          << errpos.linecount << " line, in " << errpos.symcount << " position" << endl;
  217.       state = 0;
  218.    }
  219. }
  220.  
  221.  
  222. // Обработка двухсимвольных токенов
  223. void pastsymwork(vector<vector<int>>& mas, char sym, char& pastsym, ofstream& errors, int& commentstatus, int& state, int& flag, int& commentline)
  224. {
  225.    string tmp(1, pastsym);
  226.    switch (pastsym)
  227.    {
  228.    case '=':
  229.       if (sym == '=')
  230.       {
  231.          flag = 0;
  232.          tmp += sym;
  233.          mas.push_back({ 2, ops.find(tmp), 0 });
  234.       }
  235.       else
  236.          mas.push_back({ 2, ops.find(tmp), 0 });
  237.       break;
  238.    case '!':
  239.       if (sym == '=')
  240.       {
  241.          flag = 0;
  242.          tmp += sym;
  243.          mas.push_back({ 2, ops.find(tmp), 0 });
  244.       }
  245.       else
  246.          errors << "Indefined symbol " << pastsym << " after " << mas.size() << " token in "
  247.             << errpos.linecount << " line, in " << errpos.symcount - 1 << " position" << endl;
  248.       break;
  249.    case '/':
  250.       if (sym == '*' || sym == '/')
  251.          if (sym == '*')
  252.          {
  253.             commentstatus = 2;
  254.             commentline = errpos.linecount;
  255.          }
  256.          else
  257.             commentstatus = 1;
  258.       else
  259.          errors << "Indefined symbol " << pastsym << " after " << mas.size() << " token in "
  260.             << errpos.linecount << " line, in " << errpos.symcount - 1 << " position" << endl;
  261.       break;
  262.    }
  263.    pastsym = 0;
  264. }
  265.  
  266.  
  267. // Обработка комментариев
  268. void com(char sym, char& pastsym, int& commentstatus)
  269. {
  270.    switch (sym)
  271.    {
  272.    case '\n':
  273.       if (commentstatus == 1)
  274.          commentstatus = 0;
  275.       errpos.linecount++;
  276.       errpos.symcount = 0;
  277.       pastsym = 0;
  278.       break;
  279.    case '*':
  280.       pastsym = sym;
  281.       break;
  282.    case '/':
  283.       if (pastsym == '*')
  284.       {
  285.          commentstatus = 0;
  286.          pastsym = 0;
  287.       }
  288.       break;
  289.    default:
  290.       pastsym = 0;
  291.    }
  292. }
  293.  
  294.  
  295. // Проверка последнего токена перед EOF + обработка незакрытого комментария
  296. void lastcheck(vector<vector<int>>& mas, string token, int state, int commenstatus, ofstream& errors, int commentline)
  297. {
  298.    if (state == 1)
  299.    {
  300.       id_pair p = id.find_add(token);
  301.       mas.push_back({ 4, p.hash, p.id });
  302.    }
  303.    else if (state == 2)
  304.    {
  305.       int tableid = cs.find_add(stoi(token));
  306.       mas.push_back({ 3, tableid, 0 });
  307.    }
  308.    if (commenstatus == 2)
  309.       errors << "Comment was open in " << commentline << " line and was not closed" << endl;
  310. }
  311.  
  312.  
  313.  
  314.  
  315. // ПОДПРОГРАММЫ СИНТАКСИЧЕСКОГО АНАЛИЗАТОРА
  316.  
  317.  
  318. int main()
  319. {
  320.    int state = 0, tableid, commentstatus = 0, flag, commentline = 0;
  321.    // state: 0 - start, 1 - identificators, 2 - constants
  322.    // commentstatus: 0 - откл, 1 - однострочный, 2 - многострочный
  323.    // commentline будет содержать номер строки, в который открыт многострочный комментарий
  324.    char sym, pastsym = 0;
  325.    string token;
  326.    vector<vector<int>> mas(0, vector<int>(3));
  327.  
  328.    ifstream input("input1.txt");
  329.    ofstream errors("errors.txt");
  330.    while (input.get(sym))
  331.    {
  332.       errpos.symcount++;
  333.       if (commentstatus != 0)  // Если комментирование включенно
  334.          com(sym, pastsym, commentstatus);
  335.       else
  336.       {
  337.          flag = 1;  // Для корректной обработки == и !=
  338.          //  Без flag после вывода == обрабатывается второе равенство как отдельный символ
  339.          if (pastsym != 0)
  340.             pastsymwork(mas, sym, pastsym, errors, commentstatus, state, flag, commentline);
  341.          switch (state)
  342.          {
  343.             // Начальная позиция
  344.          case 0:
  345.             if (isletter(sym))
  346.             {
  347.                token += sym;
  348.                state = 1;
  349.             }
  350.             else if (isdigit(sym))
  351.             {
  352.                token += sym;
  353.                state = 2;
  354.             }
  355.             else if(flag)
  356.                sepwork(mas, sym, pastsym, errors, commentstatus, state, token);
  357.             break;
  358.  
  359.             // Идентификаторы
  360.          case 1:
  361.             if (isletter(sym) || isdigit(sym))
  362.                token += sym;
  363.             else
  364.             {
  365.                vector<int> vec(3);
  366.                tableid = words.find(token);
  367.                if (tableid != -1)
  368.                   vec = { 0, tableid, 0 };
  369.                else
  370.                {
  371.                   id_pair p = id.find_add(token);
  372.                   vec = { 4, p.hash, p.id };
  373.                }
  374.                mas.push_back(vec);
  375.                sepwork(mas, sym, pastsym, errors, commentstatus, state, token);
  376.             }
  377.             break;
  378.  
  379.             // Константы
  380.          case 2:
  381.             if (isdigit(sym))
  382.                token += sym;
  383.             else
  384.             {
  385.                if (token == "-")
  386.                {
  387.                   mas.push_back({ 2, ops.find(token), 0 });
  388.                   sepwork(mas, sym, pastsym, errors, commentstatus, state, token);
  389.                }
  390.                else
  391.                {
  392.                   tableid = cs.find_add(stoi(token));
  393.                   mas.push_back({ 3, tableid, 0 });
  394.                   sepwork(mas, sym, pastsym, errors, commentstatus, state, token);
  395.                }
  396.             }
  397.             break;
  398.          }
  399.       }
  400.    }
  401.    lastcheck(mas, token, state, commentstatus, errors, commentline);
  402.    input.close();
  403.    errors.close();
  404.    for (int i = 0; i < mas.size(); i++)
  405.    {
  406.       switch (mas[i][0])
  407.       {
  408.       case 0:
  409.          cout << words.table[mas[i][1]];
  410.          break;
  411.       case 1:
  412.          cout << sep.table[mas[i][1]];
  413.          break;
  414.       case 2:
  415.          cout << ops.table[mas[i][1]];
  416.          break;
  417.       case 3:
  418.          cout << cs.consts[mas[i][1]];
  419.          break;
  420.       case 4:
  421.          cout << id.table[mas[i][1]][mas[i][2]].name;
  422.       }
  423.       cout << " ";
  424.    }
  425.    cout << endl;
  426.  
  427.    // На данном этапе лексический и синтаксический анализаторы работают последовательно
  428.  
  429.    return 0;
  430. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement