Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Kael Morhen
0 / 0 / 0
Регистрация: 14.06.2016
Сообщений: 10
#1

Написать анализатор кода, определяющий тип лексем - C++

18.07.2016, 10:37. Просмотров 550. Ответов 13
Метки нет (Все метки)

Допустим есть строка и мне нужно её поделить на точки, запятые, else и так далее, как это сделать на c++

Добавлено через 1 минуту
if True then A(D) else A(B); вот пример цепочки
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.07.2016, 10:37     Написать анализатор кода, определяющий тип лексем
Посмотрите здесь:
C++ Анализатор кода
Создайте класс, определяющий некоторый тип вещественых чисел, имеющий конструктор, операторы +,-, *,/ функцию вывода на экран – print. C++
Vim и статический анализатор кода C++
C++ Подскажите статический анализатор кода C++
Написать программу, определяющий рост учеников, которых больше среднего роста по классу C++
C++ Как написать анализатор команд?
Выделение лексем C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nefassa
0 / 0 / 0
Регистрация: 18.07.2016
Сообщений: 2
18.07.2016, 10:39     Написать анализатор кода, определяющий тип лексем #2
Нелогичный и некорректно заданный вопрос. При каких условиях это нужно сделать, где примитивная задача?
Kael Morhen
0 / 0 / 0
Регистрация: 14.06.2016
Сообщений: 10
18.07.2016, 10:52  [ТС]     Написать анализатор кода, определяющий тип лексем #3
Цепочка разбивается на символы. И проверяется на наличие ТОЛЬКО допустимых символов

Добавлено через 10 минут
Вот так должно выглядеть можно под этот пример программу?
Блок транслитерации – подпрограмма, преобразующая исходную символьную цепоч-

ку в цепочку лексем вида ("символ цепочки", "класс символа цепочки ").

Например, символьную цепочку

const N=10;

5

блок транслитерации должен преобразовать в цепочку лексем

(c,буква), (o,буква), (n,буква), (s,буква), (t,буква),

(' ',пробел), (N,буква), (=,равно), (1,цифра), (0,цифра),

(;,тчкзпт)

Лексический блок – подпрограмма, преобразующая цепочку лексем, полученную от

транслитератора, в цепочку лексем вида ("символ входного языка", "класс символа

входного языка").

В рассматриваемом примере лексический блок должен выдать следующую цепочку

лексем:

(const,ИДЕНТИФИКАТОР), (N,ИДЕНТИФИКАТОР), (=,РАВНО),

(10,ЦЕЛОЕ), (;,ТЧКЗПТ)

Блок идентификации ключевых слов – подпрограмма, которая устанавливает, какое из

ключевых слов языка Pascal соответствует заданному идентификатору, либо сообщает,

что заданный идентификатор не является ключевым словом языка Pascal. Идентифи-

кация ключевых слов может быть выделена в отдельный проход распознавателя сим-

вольной цепочки, то есть идентифицирующий блок будет запускаться после того, как

лексический блок полностью подготовит всю цепочку лексем. Другим подходом явля-

ется объединение в один проход распознавателя символьной цепочки лексического

блока и блока идентификации. В этом случае идентификация ключевого слова осуще-

ствляется каждый раз, когда лексический блок выдал одну лексему класса "идентифи-

катор" (без ожидания полной подготовки всей цепочки лексем).

В рассматриваемом примере после распознавания слов цепочка лексем, полученная в

результате работы лексического блока, примет следующий вид:

(const,КЛСЛОВО_CONST), (N,ИДЕНТИФИКАТОР), (=,РАВНО),

(10,ЦЕЛОЕ), (;,ТЧКЗПТ)

Синтаксический блок – подпрограмма, которая получает цепочку лексем вида ("сим-

вол входного языка", "класс символа входного языка") и устанавливает, соответствует

ли она заданным формулам Бэкуса-Наура. Поскольку задание предполагает только

распознавание исходной цепочки, фактически данный блок использует для работы

только классы символов входного языка.

В рассматриваемом примере синтаксический блок, рассматривая цепочку вида

КЛСЛОВО_CONST, ИДЕНТИФИКАТОР, РАВНО, ЦЕЛОЕ, ТЧКЗПТ

должен сообщить, что она синтаксически правильна.
Kael Morhen
0 / 0 / 0
Регистрация: 14.06.2016
Сообщений: 10
18.07.2016, 18:21  [ТС]     Написать анализатор кода, определяющий тип лексем #4
Блок транслитерации – подпрограмма, преобразующая исходную символьную цепочку

в цепочку лексем вида ("символ цепочки", "класс символа цепочки ").

Например, символьную цепочку

const N=10;

блок транслитерации должен преобразовать в цепочку лексем

(c,буква), (o,буква), (n,буква), (s,буква), (t,буква),

(' ',пробел), (N,буква), (=,равно), (1,цифра), (0,цифра),

(;,тчкзпт)

То есть у меня есть код ввода из файла
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
 
int main () 
{
  string line;
  ifstream myfile ("input.txt");
  if (myfile.is_open())
  {
    while ( myfile.good() )
    {
      getline (myfile,line);
      cout << line << endl;
    }
    myfile.close();
  }
 
 
  return 0;
}
и теперь мне вот эту строчку: if Cond then A1:=Func(id); нужно переделать по верхнему описанию
daniilorain
👻👻👻
18 / 25 / 11
Регистрация: 22.04.2016
Сообщений: 166
18.07.2016, 18:43     Написать анализатор кода, определяющий тип лексем #5
В таблице ASCII символы от A до Z занимают места с 65 до 90(a-z с 97 до 122), так что преобразуете полученный символ в int и проверяете номер, так же с цифрами. А для всего остального есть контейнер map, ну или switch case, но это плохой вариант в данном случае
Kael Morhen
0 / 0 / 0
Регистрация: 14.06.2016
Сообщений: 10
18.07.2016, 19:22  [ТС]     Написать анализатор кода, определяющий тип лексем #6
Я не понимаю как это записать из файла к сожалению
gazlan
3130 / 1905 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
19.07.2016, 02:26     Написать анализатор кода, определяющий тип лексем #7
Провести лексический анализ заданного фрагмента и составить кодировочную таблицу

Не по теме:

Цитата Сообщение от daniilorain Посмотреть сообщение
А для всего остального есть контейнер map, ну или switch case
Вас обманули.

daniilorain
👻👻👻
18 / 25 / 11
Регистрация: 22.04.2016
Сообщений: 166
19.07.2016, 12:35     Написать анализатор кода, определяющий тип лексем #8
gazlan, ТС нужно составить небольшой блок транслитерации, так что можно вполне обойтись простыми if
gazlan
3130 / 1905 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
19.07.2016, 13:04     Написать анализатор кода, определяющий тип лексем #9
Цитата Сообщение от daniilorain Посмотреть сообщение
ТС нужно составить небольшой блок транслитерации, так что можно вполне обойтись простыми if
Если верить самому TS (#1 & #3), то ему нужен, как минимум, лексический анализатор:
Цитата Сообщение от Kael Morhen Посмотреть сообщение
Допустим, есть строка и мне нужно её поделить на точки, запятые, else и так далее, как это сделать на c++
Kael Morhen
0 / 0 / 0
Регистрация: 14.06.2016
Сообщений: 10
19.07.2016, 15:59  [ТС]     Написать анализатор кода, определяющий тип лексем #10
Нужно преобразовать цепочку лексем, полученную от
транслитератора, в цепочку лексем вида ("символ входного языка", "класс символа
входного языка").
В рассматриваемом примере лексический блок должен выдать следующую цепочку
лексем:
(const,ИДЕНТИФИКАТОР), (N,ИДЕНТИФИКАТОР), (=,РАВНО),
(10,ЦЕЛОЕ), (;,ТЧКЗПТ)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <fstream>
 
using namespace std;
 
int main()
{
    setlocale(0,"");
    ifstream io("input.txt");
    ofstream oo("output.txt");
 
        if (!io.is_open() || !oo.is_open())
    {
        cout << "Невозможно открыть файл!";
    }
 
char buf = '\0';
while(!io.eof())
    {
    if (buf != '\0') oo << ", \n";
        io.get(buf);
        oo << "(" << buf << ",";
    if ((int(buf) >= 65 && int(buf) <= 90) || (int(buf) >= 97 && int(buf) <= 122))
        {
        oo << "буква)";
        }
    else if (int(buf) >= 48 && int(buf) <= 57)
        {
        oo << "цифра)";
        }
    else if(int(buf) == 45 || int(buf) == 43 || int(buf) == 40 || int(buf) == 41)
        {
        oo << "знак)";
        }
    else if(int(buf) == 32)
        {
        oo << "пробел)";
        }
    else if(int(buf) == 61)
        {
        oo << "равно)";
        }
    else if(int(buf) == 59)
        {
        oo << "тчкзпт)";
        }
    else
        oo << "ошибка)";
    }
}
Вот пример строки: if Cond then A1:=Func(id);
EVP
321 / 243 / 43
Регистрация: 14.12.2010
Сообщений: 464
19.07.2016, 17:41     Написать анализатор кода, определяющий тип лексем #11
Цитата Сообщение от Kael Morhen Посмотреть сообщение
В рассматриваемом примере лексический блок должен выдать следующую цепочку
лексем
На примере генератора Сосо/R.
Kael Morhen
0 / 0 / 0
Регистрация: 14.06.2016
Сообщений: 10
19.07.2016, 21:37  [ТС]     Написать анализатор кода, определяющий тип лексем #12
Нужно к этому написать подпрограмму преобразующую цепочку лексем, полученную от
транслитератора, в цепочку лексем вида ("символ входного языка", "класс символа
входного языка").
В рассматриваемом примере лексический блок должен выдать следующую цепочку
лексем:
(const,ИДЕНТИФИКАТОР), (N,ИДЕНТИФИКАТОР), (=,РАВНО),
(10,ЦЕЛОЕ), (;,ТЧКЗПТ)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <string>
#include "translitter.h"
using namespace std;
 
string translitter(char c)
{
        if ((c > 64 && c < 91) || (c > 96 && c < 123))
            return "буква";
        else if ((c > 47 && c < 58))
            return "цифра";
        else if (c == 32)
            return "пробел";
        else if (c == 58)
            return "двоеточ";
        else if (c == 59)
            return "тчкзпт";
        else if (c == 61)
            return "равно";
        else if (c == 40)
            return "знак";
        else if (c == 41)
            return "знак";
        else if (c == 43 || c == 45)
            return "знак";
        else
            return "ERROR";
}
Вот пример строки: if Cond then A1:=Func(id);
То есть должно получится примерно так (if,идентификатор) (cond, идентификатор) (then, идентификатор) (A1, идентификатор) (: двоеточие) (=, равно) (Func, идентификатор) ( (, левая скобка) ( ), правая скобка) ( id идентификатор) (; тчкзпт)
nonedark2008
889 / 628 / 126
Регистрация: 28.07.2012
Сообщений: 1,697
19.07.2016, 23:29     Написать анализатор кода, определяющий тип лексем #13
Kael Morhen, могу только дать пример того, как это все может выглядеть.
h-файл:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <string>
#include <istream>
#include <iostream>
#include <map>
#include <unordered_set>
 
 
enum Token {
  // Конец файла
  T_EOF,
  // Виды констант
  T_STRING,
  T_UNUMBER,
  T_ID,
  // Простой тип
  T_VARTYPE,
  //Служебные слова
  T_CONST,
  T_PROGRAM,
  T_LABEL,
  T_VAR,
  T_FUNC,
  T_PROC,
  T_BEGIN,
  T_END,
  T_TRUE,
  T_FALSE,
  // Различные операции
  T_FACTOROP,
  T_TERMOP,
  T_COND,
  // Условный оператор IF
  T_IF,
  T_THEN,
  T_ELSE,
  // Операторы цикла
  T_FOR,
  T_TO,
  T_DOWNTO,
  T_DO,
  T_WHILE,
  T_REPEAT,
  T_UNTIL,
  //;
  T_SEMICOLON,
  //:
  T_COLON,
  //,
  T_COMMA,
  //:=
  T_ASSIGN,
  //~
  T_NEG,
  //(
  T_LBR,
  //)
  T_RBR,
  //nil
  T_NIL
};
 
static std::unordered_set<std::string> NAMES = {
    "nil", "in", "if", "then", "else", "case", 
    "of", "repeat", "until", "while", 
    "do", "for", "to", "downto", 
    "begin", "end", "with", "goto",
    "const", "var", "array", "record", 
    "set", "file", "function", "procedure", 
    "label", "packed", "program", "true", "false"
    
};
static std::unordered_set<std::string> TYPE_NAMES = {
    "integer", "char", "boolean", "real"
};
static std::unordered_set<std::string> COND_NAMES = {
    "=", "<>", ">", ">=", 
    "<", "<=", "in"
};
static std::unordered_set<std::string> FACTOR_NAMES = {
    "*", "/", "div", 
    "mod", "and", "^"
};
 
static std::unordered_set<std::string> TERM_NAMES = {
    "+", "-", "or",
};
 
 
// Лексический анализатор
class Lexer {
  std::istream &_input;
  int _lastChar;
 
  unsigned _curLine;
 
public:
  Lexer(std::istream &input)
      : _input(input), _lastChar(' '), _IDName(""), _stringValue(""), _curLine(0) { }
 
  ~Lexer() {}
 
  // Получение очередной лексемы из потока
  Token GetToken();
  unsigned GetLine() { return _curLine; }
 
  std::string _IDName;
  std::string _stringValue;
};


cpp-файл
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
static int isNewline(int c) { return (c == '\n' || c == '\r'); }
static int isSpace(int c) { return (c == ' ' || c == '\t'); }
 
Token Lexer::GetToken()
{
    //Пропускаем ненужные гадости
    while (isNewline(_lastChar) || isSpace(_lastChar))
    {
        if (isNewline(_lastChar))
            _curLine++;
        _lastChar = _input.get();
    }
    // Проверка на наличие ключевого слова или идентификатора
    if (isalpha(_lastChar)) {
        _stringValue = _lastChar;
        while (isalnum((_lastChar = _input.get())))
            _stringValue += _lastChar;
        if (TYPE_NAMES.find(_stringValue) != TYPE_NAMES.end())
            return T_VARTYPE;
        else if (COND_NAMES.find(_stringValue) != COND_NAMES.end())
            return T_COND;
        else if (FACTOR_NAMES.find(_stringValue) != FACTOR_NAMES.end())
            return T_FACTOROP;
        else if (TERM_NAMES.find(_stringValue) != TERM_NAMES.end())
            return T_TERMOP;
        else if (NAMES.find(_stringValue) == NAMES.end())
            return T_ID;
        else if (_stringValue == "if")
            return T_IF;
        else if (_stringValue == "else")
            return T_ELSE;
        else if (_stringValue == "then")
            return T_THEN;
        else if (_stringValue == "begin")
            return T_BEGIN;
        else if (_stringValue == "end")
            return T_END;
        else if (_stringValue == "nil")
            return T_NIL;
        else if (_stringValue == "const")
            return T_CONST;
        else if (_stringValue == "function")
            return T_FUNC;
        else if (_stringValue == "procedure")
            return T_PROC;
        else if (_stringValue == "var")
            return T_VAR;
        else if (_stringValue == "program")
            return T_PROGRAM;
        else if (_stringValue == "label")
            return T_LABEL;
        else if (_stringValue == "for")
            return T_FOR;
        else if (_stringValue == "to")
            return T_TO;
        else if (_stringValue == "downto")
            return T_DOWNTO;
        else if (_stringValue == "do")
            return T_DO;
        else if (_stringValue == "while")
            return T_WHILE;
        else if (_stringValue == "while")
            return T_WHILE;
        else if (_stringValue == "repeat")
            return T_REPEAT;
        else if (_stringValue == "until")
            return T_UNTIL;
        else if (_stringValue == "true")
            return T_TRUE;
        else if (_stringValue == "false")
            return T_FALSE;
    }
    //Если строка
    else if (_lastChar == '\'')
    {
        _stringValue = "";
        _lastChar = _input.get();
        while (_lastChar != '\'' && !_input.eof())
        {
            if (_lastChar == '\n')
                _curLine++;
            _stringValue += _lastChar;
            _lastChar = _input.get();
        }
        if (_lastChar != '\'')
            throw std::exception();
        _lastChar = _input.get();
        return T_STRING;
    }
    //Если число
    else if (isdigit(_lastChar)) {
        _stringValue = _lastChar;
        while (isdigit((_lastChar = _input.get())))
            _stringValue += _lastChar;
        if (_lastChar == '.')
        {
            _stringValue += _lastChar;
            while (isdigit((_lastChar = _input.get())))
                _stringValue += _lastChar;
        }
        if (_lastChar == 'E')
        {
            _stringValue += _lastChar;
            _lastChar = _input.get();
            if (_lastChar == '+' || _lastChar == '-')
            {
                _stringValue += _lastChar;
                _lastChar = _input.get();
            }
            if (isdigit(_lastChar))
            {
                do
                {
                    _stringValue += _lastChar;
                    _lastChar = _input.get();
 
                } while (isdigit(_lastChar));
            }
            else
                throw std::exception();
        }
 
        return T_UNUMBER;
    }
    else if (_lastChar == '(')
    {
        _stringValue = _lastChar;
        _lastChar = _input.get();
        return T_LBR;
    }
    else if (_lastChar == ')')
    {
        _stringValue = _lastChar;
        _lastChar = _input.get();
        return T_RBR;
    }
    else if (_lastChar == ';')
    {
        _stringValue = _lastChar;
        _lastChar = _input.get();
        return T_SEMICOLON;
    }
    else if (_lastChar == ':')
    {
        _stringValue = _lastChar;
        _lastChar = _input.get();
        if (_lastChar == '=')
        {
            _stringValue += _lastChar;
            _lastChar = _input.get();
            return T_ASSIGN;
        }
        else
            return T_COLON;
    }
    else if (_lastChar == ',')
    {
        _stringValue = _lastChar;
        _lastChar = _input.get();
        return T_COMMA;
    }
    else if (_lastChar == '~')
    {
        _stringValue = _lastChar;
        _lastChar = _input.get();
        return T_NEG;
    }
    else if (TERM_NAMES.find((_stringValue = _lastChar)) != TERM_NAMES.end())
    {
        _stringValue = _lastChar;
        _lastChar = _input.get();
        return T_TERMOP;
    }
    else if (FACTOR_NAMES.find((_stringValue = _lastChar)) != FACTOR_NAMES.end())
    {
        _stringValue = _lastChar;
        _lastChar = _input.get();
        return T_FACTOROP;
    }
    else if (COND_NAMES.find((_stringValue = _lastChar)) != COND_NAMES.end())
    {
        _stringValue = _lastChar;
        if ((_lastChar == '>' || _lastChar == '<') && ((_lastChar = _input.get()) == '='))
            _stringValue += _lastChar;
        _lastChar = _input.get();
        return T_COND;
    }
    // Проверим, не дошли ли мы до конца файла.
    if (_input.eof())
        return T_EOF;
 
    throw std::exception();
}


Выдрал из какого-то своего старого проекта (кто-то может даже угадать язык ). Оно в чистом виде скорее всего не заработает, но идея понятна быть должна.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.07.2016, 00:34     Написать анализатор кода, определяющий тип лексем
Еще ссылки по теме:
Класс лексем, разбить числа C++
объединение лексем в единое целое C++
Разбивка на лексемы и состовление из лексем строк C++
Сохранение всех входящих лексем(строк) в порядке поступления C++
Культура оформления кода: что такое enum? Где, когда и для чего уместно применять этот тип? C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
EVP
321 / 243 / 43
Регистрация: 14.12.2010
Сообщений: 464
20.07.2016, 00:34     Написать анализатор кода, определяющий тип лексем #14
Цитата Сообщение от Kael Morhen Посмотреть сообщение
Вот пример строки: if Cond then A1:=Func(id);
То есть должно получится примерно так (if,идентификатор) (cond, идентификатор) (then, идентификатор) (A1, идентификатор) (: двоеточие) (=, равно) (Func, идентификатор) ( (, левая скобка) ( ), правая скобка) ( id идентификатор) (; тчкзпт)
Должно получится "примерно" или "так"?
Например, для грамматики Pascal "if" и "then" являются операторами, а не идентификаторами.
Присваивание ":=" является оператором, а не двумя операторами ":" и "=",
которые в Pascal'е также существуют, но отличаются от присваивания .

Понятно что разбивка на лексемы зависит от грамматики анализируемого языка.
Цитата Сообщение от Kael Morhen Посмотреть сообщение
string translitter(char c)
Поскольку лексема может содержать более одного текстового символа,
то и в твоём случае анализ нужно вести по лексемам, а не по символам.

Так что разберись с грамматикой языка, который парсишь.
По грамматике делаешь парсер, например, с помощью Coco/R для LL1 грамматик (пример выше смотри).
Или пишешь парсер вручную, если их изучаешь.

Если я написал чего-то сильно страшное для тебя,
то начинаешь читать Компиляторы. Принципы, технологии и инструментарий до просветления.

Успехов!
Yandex
Объявления
20.07.2016, 00:34     Написать анализатор кода, определяющий тип лексем
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru