Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/15: Рейтинг темы: голосов - 15, средняя оценка - 4.80
 Аватар для Mozart
39 / 17 / 1
Регистрация: 21.08.2009
Сообщений: 63

Интепретатор №2

01.10.2009, 16:53. Показов 3254. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Прочитав тему [C++]Пишем свой интерпретатор, воодушевился написать свой, с 0.
На данный момент застопорился на арифметике. У меня возникла проблема с порядком вычислений.
Если брать в "лоб" то выражение 2+2*2 будет равно 8.
Если добавить рекурсию - то 2+2*2 будет считатся корректно, но выражение 3-1+2 будет равно 0, т.к. фактически оно считает 3-(1+2) (что необходимо для сохранения приоритета умножений/делений).
Как лучше решить этот вопрос?
Высладываю свою функцию расчета:
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
double TTokenList::Calculate(int i,char ch){
    string s;
    double res=0,tmp;
    s=get_Token();
    while ((s!="end.")&&(s[0]!=ch)){
       switch (s[0]) {
              case '(':
                   res=Calculate(i,')');
                   break;
              case 'a'...'z':
                   break;
              case '0'...'9':
                   res=atof(s.c_str());
                   break;
              case '+':
                   res+=Calculate(i,ch);
                   return res;
                   break;
              case '-':
                   res-=Calculate(i,ch);
                   return res;
                   break;
              case '*':
                   s=get_Token();
                   if (s[0]!='(') res*=atof(s.c_str());
                   else res*=Calculate(i,')');
                   break;
              case '/':
                   s=get_Token();
                   if (s[0]!='(') tmp=atof(s.c_str());
                   else tmp=Calculate(i,')');
                   if(tmp!=0)res/=tmp;
                   else {
                        cout<<"Runtime ERROR in line: "<<i
                        <<" Division by zero."<<endl;
                        Error=i;
                        return 0;
                   }
                   break;
              default:
                      cout<<"ERROR in line: "<<i
                      <<" Rvalue epic fail!"
                      <<s<<endl;
                      Error=i;
                      return 0;
                      break;         
       }          
       s=get_Token();
    }
    return res;
}
ЗЫ: программа пока может работать только с цифрами, переменные еще не предусмотрены.
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.10.2009, 16:53
Ответы с готовыми решениями:

Компилятор или интепретатор.
Здравствуйте! Я начинаю изучать C++ помогите, какое ПО подойдет больше всего для этого, для начинающего. И что конкретно мне нужно для...

Интепретатор case
Народ не подскажите, как можно составить интепретатор оператора case в языке Pascal. Вот условие задачи: &quot;В кач-ве операторов, среди...


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

Или воспользуйтесь поиском по форуму:
17
146 / 146 / 32
Регистрация: 26.10.2008
Сообщений: 782
01.10.2009, 17:04
Можно использовать польскую инверсную запись, например, a+b в этой записи будет ab+. В этом случае отпадает необходимость в скобках.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.10.2009, 17:16
Если тебя интересует просто вычисление выражения, то можно воспользоваться польской записью, про которую на форуме уже писалось много раз. Если реально хочешь сделать что-то наподобие интерпретатора, особенно если в него будет входить промежуточное представление, то тут лучше делать через рекурсивный спуск

Для начала посмотри пример и описание к этому примеру. Если будут какие-то конкретные вопросы - задавай

Формальное описание синтаксиса для этой программы примерно такое:

Code
1
2
3
Expr = Term { ("+"|"-") Term }
Term = Factor { ("*"|"/") Factor }
Factor = CONST | IDENT | "(" Expr ")"
Слова, написанные с заглавной буквы (Expr, Term, Factor) - это имена синтаксических правил. Полностью заглавными буквами (CONST, IDENT) - это лексические единицы (в твоём случае будет только CONST). То, что в кавычках - это соотвественно конкретные символы. В фигурных скобках - означает ноль или более повторений того, что заключено в скобки. То, что написано через "|" - означает либо одно, либо другое. Круглые скобки (без кавычек) - это просто скобки, чтобы отделить набор элементов через "|". Перевод этих теримнов: Expr (expression) - выражение, Term - слагаемое, Factor - множитель

Добавлено через 45 секунд
Ну и чисто для самообразования: интепрЕтатор
1
 Аватар для Mozart
39 / 17 / 1
Регистрация: 21.08.2009
Сообщений: 63
01.10.2009, 17:45  [ТС]
не думаю что это будет понятно простому русскому уму, т.к. нас еще в коле учили что 4ac это 4*а*с

Добавлено через 25 минут
Ну и чисто для самообразования: интепрЕтатор
Упс
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.10.2009, 17:54
Цитата Сообщение от Mozart Посмотреть сообщение
не думаю что это будет понятно простому русскому уму, т.к. нас еще в коле учили что 4ac это 4*а*с
Что именно не понятно русскому уму?
0
 Аватар для Mozart
39 / 17 / 1
Регистрация: 21.08.2009
Сообщений: 63
01.10.2009, 18:13  [ТС]
Цитата Сообщение от qwert Посмотреть сообщение
Можно использовать польскую инверсную запись, например, a+b в этой записи будет ab+.
Это, ab+ скорее всего поймут как а*b+чтото там, или я не правильно понял?
0
146 / 146 / 32
Регистрация: 26.10.2008
Сообщений: 782
01.10.2009, 18:27
Прочитайте про польскую инверсную запись.
ab+ - это представление не будет никуда выводиться, оно для облегчения работы с записью. Разумеется, что сначала нужно выражение к такой записи преобразовать.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.10.2009, 18:50
Цитата Сообщение от Mozart Посмотреть сообщение
Это, ab+ скорее всего поймут как а*b+чтото там, или я не правильно понял?
Когда пишут "ab+", то подразумевают, что есть некий список примитивов "a", "b", "+"
1
 Аватар для Mozart
39 / 17 / 1
Регистрация: 21.08.2009
Сообщений: 63
01.10.2009, 20:03  [ТС]
Evg, Кстати твоя программа заткнулась после вот такого примера:
(2-3+1*3)*2-4*(2-11)
0
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
01.10.2009, 20:47
может быть можно начать с того, что определить что создается, и составить для наглядности набор тестов, который проиллюстрирует задачу и послужит доказательством правильности функционирования.

например:

"2/2" -> "1"
"2.2/2" -> "1.1"
...
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.10.2009, 20:55
Цитата Сообщение от Mozart Посмотреть сообщение
Evg, Кстати твоя программа заткнулась после вот такого примера:
(2-3+1*3)*2-4*(2-11)
Странно, у меня работает

Code
1
2
3
4
5
6
7
8
input expression:
(2-3+1*3)*2-4*(2-11)
stat:
    consts   8
    idetns   0
    arith    7
    brackets 2
result = 40
0
 Аватар для Mozart
39 / 17 / 1
Регистрация: 21.08.2009
Сообщений: 63
01.10.2009, 22:54  [ТС]
может быть, но тогда выход из программы происходит не из main() т.к. я там добавил system("pause");
и получается что при простом примере все нормально, а при таком примере, окно открывается и сразу закрывается.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.10.2009, 23:19
"Там" это где? В конце main? Попробуй перед этим влепить fflush (stdout), может просто вся печать висит в буффере и не выводится на экран? Вообще ты первый, у кого не заработало
0
 Аватар для Mozart
39 / 17 / 1
Регистрация: 21.08.2009
Сообщений: 63
02.10.2009, 21:04  [ТС]
Таки не работает, выдает:
D:\Администраторы\Mozart\Study\programmi ng\projects\expr>expr
input expression:
(2-3+1*3)*2-4*(2-11)
incorrct symbol ! (code = 0x21)
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
02.10.2009, 23:42
что-то странное творится. Может у тебя карма плохая?
0
 Аватар для Mozart
39 / 17 / 1
Регистрация: 21.08.2009
Сообщений: 63
02.10.2009, 23:43  [ТС]
Не знаю, может мне тестером устраиватся? Или прелести Dev C++?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
02.10.2009, 23:46
Самое обидное, если я сяду с тобой удалённо заниматься - на это полгода может уйти
0
 Аватар для Mozart
39 / 17 / 1
Регистрация: 21.08.2009
Сообщений: 63
03.10.2009, 08:27  [ТС]
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
int TParser::Run(){
    double res=0;
    int com;
    Error=0;
    Tokens->Reset();
    string s=Tokens->get_Token();
    while (Tokens->get_Cur_Token()!="end."){
          com=0;
          if (s=="print") com=PRINT_C;
          switch (com){
                 case PRINT_C:
                      Tokens->get_Token();
                      res=Get_Expr();
                      cout<<res<<endl;
                      s=Tokens->get_Token();
                      break;
                 default:
                      res=Get_Expr();
                      s=Tokens->get_Token();
                      break;
          }
    }
    return Error;
}
double TParser::Get_Expr(){
       double res=Get_Term();
       string s;
       while (Tokens->get_Cur_Token()!=";"){
             s=Tokens->get_Cur_Token();
             switch (s[0]){
                    case '+':
                         Tokens->get_Token();
                         res+=Get_Term();
                         break;
                    case '-':
                         Tokens->get_Token();
                         res-=Get_Term();
                         break;
                    default:
                            return res;
                            break;
             }
       }       
       return res;
}
double TParser::Get_Term(){
       double tmp,res=Get_Factor();
       string s;
       while (Tokens->get_Cur_Token()!=";"){
             s=Tokens->get_Cur_Token();
             switch (s[0]){
                    case '*':
                         Tokens->get_Token();
                         res*=Get_Factor();
                         break;
                    case '/':
                         Tokens->get_Token();
                         tmp=Get_Factor();
                         if (tmp) res/=tmp;
                         break;
                    default:
                            return res;
                            break;
             }
       }       
       return res;
}
double TParser::Get_Factor(){
       double res=0;
       string s,n;
       s=Tokens->get_Cur_Token();
       n=Tokens->get_Token();
       switch (s[0]){
              case '0'...'9':
                   res=atof(s.c_str());
                   break;
              case 'a'...'z':
//                   if (n) res/=tmp;
                   break;
              case '(':
                   res=Get_Expr();
                   if (Tokens->get_Cur_Token()==")")
                      Tokens->get_Token(); 
                   else {
                        Error=2;
                        return res;   
                   }
                   break;                   
              default:
                      Error=1;
                      return res;
                      break;
       }       
       return res;
}
Вот что в итоге получилось, вроде как работает, завтра займусь переменными =))
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Ответ Создать тему
Новые блоги и статьи
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20% kYBz3eJf3jQ
Дальние перспективы сервера - слоя сети с космологическим дизайном интефейса карты и логики.
Hrethgir 07.04.2026
Дальнейшее ближайшее планирование вывело к размышлениям над дальними перспективами. И вот тут может быть даже будут нужны оценки специалистов, так как в дальних перспективах всё может очень сильно. . .
Горе от ума
kumehtar 07.04.2026
Эта мне ментальная установка, что вот прямо сейчас, мол, мне для полного счастья не хватает (нужное вписать), и когда я этого достигну - тогда и полный кайф. Одна из самых сильных ловушек на пути. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru