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

Пишем свой интерпретатор языка BASIC - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 1509, средняя оценка - 4.80
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
20.06.2009, 20:03     Пишем свой интерпретатор языка BASIC #1
*****************
Благодаря форуму и Evg в частности интерпретатор развивается, потихоньку превращаясь в простенький интерпретатор QBASIC.
Некоторые из самых старых версий сохранились в теме и ссылки на них будут добавлены в это сообщение,а также ссылки на другие темы,связанные с этой.

Репозиторий с проектом находится тут, там же есть возможность в браузере посмотреть историю ревизий (английский в логах весьма примитивен,комментарии и рекомендации можете писать в личку),а также скачать самый последний архив репозитория в формате .tar.gz
Если кто-то пользуется Subversion,скачать исходники можно так:
Код
svn co https://basin.svn.sourceforge.net/svnroot/basin basin
Эти темы возникли в результате моих вопросов по ходу написания:
Технический приём для формирования согласованных данных
Makefile: как с использованием gcc строить автоматические зависимости от .h файлов?
Вопрос по svn (Subversion)
Создание системы тестирования ПО.
Вопрос про разные реализации бэйсиков
[C/C++] Можно ли выразить порядковый номер элемента массива через индексы?
[C++] Какие флаги указать линкеру для компиляции программы?
Как можно определить переменную в файле configure.in,чтобы её можно было использовать в Makefile?
Странный SIGSEGV, или что зависит от порядка написания интерфейса класса
[C++]Можно ли как-то указать в Makefile,чтобы часть файлов компилировал компилятор C?
Альтернативная версия интерпретатора от Evg на C
Это простая реализация разбора выражений, написанная Evg на C:
Представление выражения в двоичном дереве
*****************
Первое сообщение:
*****************
Задание(Страуструп,из книги,по готовому коду): Введите программу калькулятора и заставьте её работать.Например,при вводе
C++
1
2
r = 2.5
area = pi*r*r
Программа калькулятора выведет:
C++
1
2
2.5
19.635
Получили такой код:
LexicalAnalyzer.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
// LexicalAnalyzer.h
#ifndef LEXICALANALYZER_H_INCLUDED
#define LEXICALANALYZER_H_INCLUDED
 
#include <cctype>
#include <string>
#include <map>
#include <iostream>
 
enum Token_value {
    NAME,       NUMBER,      END,
    PLUS = '+', MINUS = '-', MUL = '*', DIV = '/',
    PRINT = ';',ASSIGN = '=',LP = '(',  RP = ')'
};
extern Token_value curr_tok;
extern std::map<std::string,double>table;
extern int no_of_errors;
 
Token_value get_token();
 
double expr(bool);
double term (bool);
double prim (bool);
int error(const std::string&);
 
#endif // LEXICALANALYZER_H_INCLUDED

LexicalAnalyzer.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
// LexicalAnalyzer.cpp
#include "LexicalAnalyzer.h"
 
 
std::map<std::string,double>table;
Token_value curr_tok=PRINT;
 
double expr (bool get)
{
    double left = term(get);
 
    for (;;)
        switch (curr_tok) {
            case PLUS:
                 left += term(true);
            break;
            case MINUS:
                 left-= term(true);
            break;
            default:
                 return left;
        }
}
 
double term (bool get)
{
    double left = prim (get);
 
    for (;;)
        switch (curr_tok) {
            case MUL:
                 left*=prim(true);
            break;
            case DIV:
                 if (double d = prim (true)) {
                     left /= prim (true);
                     break;
                 }
                 return error("Деление на ноль");
            default:
                 return left;
        }
}
 
double number_value;
std::string string_value;
 
double prim (bool get)
{
    if (get) get_token();
    switch (curr_tok){
        case NUMBER:{
            double& v = number_value;
            get_token();
            return v;
        }
        case NAME:{
            double& v = table[string_value];
            if (get_token()==ASSIGN) v = expr(true);
            return v;
        }
        case MINUS:
            return -prim(true);
        case LP:{
            double e = expr(true);
            if (curr_tok!=RP) return error("Ожидалась )");
            get_token();
            return e;
        }
        default:
            return error("Ожидалось первичное выражение");
    }
}
 
Token_value get_token()
{
    char ch = 0;
 
    do {
        if (!std::cin.get(ch)) return curr_tok = END;
    } while (ch!='\n'&&isspace(ch));
 
    switch (ch) {
        case 0:
             return curr_tok = END;
        case ';':case '\n':
             return curr_tok = PRINT;
        case '*':case'/':case '+':case '-':case '(':case ')':case '=':
             return Token_value(ch);
        case '0':case '1':case '2':case '3':case '4' :
        case '5':case '6':case '7':case '8':case '9':case '.':
             std::cin.putback(ch);
             std::cin>>number_value;
             return curr_tok=NUMBER;
        default:
             if (isalpha(ch)) {
                 string_value = ch;
                 while (std::cin.get(ch)&&isalnum(ch)) string_value.push_back(ch);
                 std::cin.putback(ch);
                 return curr_tok = NAME;
             }
             error ("Неправильная лексема");
             return curr_tok = PRINT;
    }
}
int no_of_errors=0;
int error (const std::string& s)
{
    no_of_errors++;
    std::cerr<<"Ошибка: "<<s<<'\n';
    return no_of_errors;
}

main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// main.cpp
#include "LexicalAnalyzer.h"
 
 
int main()
{
    table["pi"]=3.1415926535897932385;
    table["e"]=2.7182818284590452354;
    while (std::cin) {
        get_token();
        if (curr_tok==END) break;
        if (curr_tok==PRINT) continue;
        std::cout<<expr(false)<<'\n';
    }
    return no_of_errors;
}

Анализатор-то работает,но конечное значение не вычисляется.Более того,если вводим
C++
1
a = 3 + 6
,то получаем "a", равное первому элементу в выражении,то есть 3.В чём логическая ошибка данной программы?С этими каскадными вызовами она слегка запутана.Уверен,что кто-то уже делал это задание.

Добавлено через 2 часа 5 минут 30 секунд
Пришлось решать влоб с дебаггером.У Страуструпа опечатка (или намеренная ошибка,что более вероятно ) Вот в этом куске кода в функции get_token():
C++
1
2
        case '*':case'/':case '+':case '-':case '(':case ')':case '=':
             return Token_value(ch);
Нехватает смены значения curr_tok,что и приводит к ошибочной работе.
C++
1
2
        case '*':case'/':case '+':case '-':case '(':case ')':case '=':
             return curr_tok=Token_value(ch);
Теперь всё пашет,всем спасибо,вопрос можно считать закрытым,но есть вопрос поважнее: В функциях prim и term возвращается int при ошибке,но ведь они имеют тип double,как вообще это работает?Происходит неявное преобразование типа,так?Мне интересно,почему Страуструп прибег к такому способу,это распространённая практика?

Добавлено через 16 минут 19 секунд
И ещё опечатка была
C++
1
2
3
                 if (double d = prim (true)) {
                     left /= d;// было left /= prim (true)
                     break;
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
21.03.2010, 22:38  [ТС]     Пишем свой интерпретатор языка BASIC #341
Bash
1
2
3
qmake -v
QMake version 2.01a
Using Qt version 4.4.0 in /usr/lib
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 22:40     Пишем свой интерпретатор языка BASIC #342
с этой версией не соберется.
а дистр у тебя какой?

Добавлено через 28 секунд
с оф. сайта качай исходники или SDK.
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
21.03.2010, 22:42  [ТС]     Пишем свой интерпретатор языка BASIC #343
Понял.
Пользуюсь Ubuntu 8.04 64-битной
Для порядка тогда надо мне в configure.in добавить какую-то проверку на версию Qt для этого интерфейса.Т.е. если этой версии нет,то выдаём предупреждение и собираем что можно)
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 22:50     Пишем свой интерпретатор языка BASIC #344
Цитата Сообщение от #pragma Посмотреть сообщение
Для порядка тогда надо мне в configure.in добавить какую-то проверку на версию Qt для этого интерфейса
я знаю как это реализуется в .pro файле. а вот по поводу configure я ничего не знаю
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
22.03.2010, 15:32     Пишем свой интерпретатор языка BASIC #345
Цитата Сообщение от niXman Посмотреть сообщение
с этой версией не соберется.
а дистр у тебя какой?

Добавлено через 28 секунд
с оф. сайта качай исходники или SDK.
Вообще говоря, когда для простенького редактора нужна самая последняя версия Qt, а на чуть более ранних оно уже не собирается - помоему в топку такие оладушки
RazorQ
 Аватар для RazorQ
574 / 341 / 9
Регистрация: 06.02.2009
Сообщений: 1,386
22.03.2010, 15:38     Пишем свой интерпретатор языка BASIC #346
Цитата Сообщение от Evg Посмотреть сообщение
Вообще говоря, когда для простенького редактора нужна самая последняя версия Qt, а на чуть более ранних оно уже не собирается - помоему в топку такие оладушки
Версия 4.5.2 нужна только лишь из-за кнопочек на вкладках. Так что можно этот код не включать если версия ниже. Функциональность сохраняется
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
22.03.2010, 21:36  [ТС]     Пишем свой интерпретатор языка BASIC #347
Цитата Сообщение от RazorQ Посмотреть сообщение
Версия 4.5.2 нужна только лишь из-за кнопочек на вкладках. Так что можно этот код не включать если версия ниже. Функциональность сохраняется
Я так сразу не вьеду,что там выбрасывать из кода именно,собери,если можно,рабочую версию,чтобы компилилось.

Так .ts это файлы переводов? А что такое .qm?

Добавлено через 8 минут
О! а лучше сделай #define QT_4.5.2 или похожий,и пусть этот код аккуратно выбрасывается с помощю этого define-а,тогда я смогу у себя в configure сделать опцию по которой идет проверка версии Qt (по крайней мере,я могу попробовать),и тогда всё это можно будет делать автоматом.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
22.03.2010, 21:59     Пишем свой интерпретатор языка BASIC #348
Цитата Сообщение от #pragma Посмотреть сообщение
а лучше сделай #define QT_4.5.2 или похожий
В Qt, как и любой другой уважающей себя библиотеке, должны быть встроенные макросы версии
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
22.03.2010, 22:34     Пишем свой интерпретатор языка BASIC #349
Цитата Сообщение от Evg Посмотреть сообщение
В Qt, как и любой другой уважающей себя библиотеке, должны быть встроенные макросы версии
Qt очень бурно развивается. И тролли, честно говоря, не особо беспокоятся по поводу обратной совместимости.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
22.03.2010, 23:21     Пишем свой интерпретатор языка BASIC #350
Совместимость - это одно, а макрос текущей версии - другое, с совместимостью мало связанное. Есть же макросы __GNUC__, __GNUC_MINOR__. Вот может и у Qt есть что-то подобное
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
22.03.2010, 23:26     Пишем свой интерпретатор языка BASIC #351
Evg, ты спрашиваешь макрос, который содержит текущую версию?
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
22.03.2010, 23:35     Пишем свой интерпретатор языка BASIC #352
Ну да. А под этим макросом ты просто включаешь или не включаешь фичу, которая есть в одной версии и нет в другой
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
22.03.2010, 23:43     Пишем свой интерпретатор языка BASIC #353
вот теперь понял.
QT_VERSION
QT_VERSION_STR
QT_VERSION_CHECK()
RazorQ
 Аватар для RazorQ
574 / 341 / 9
Регистрация: 06.02.2009
Сообщений: 1,386
23.03.2010, 13:25     Пишем свой интерпретатор языка BASIC #354
Цитата Сообщение от #pragma Посмотреть сообщение
Так .ts это файлы переводов? А что такое .qm?
Да, .ts это файлы перевода, но в формате XML. .qm это скомпилированные файлы перевода, которые и используются в программе. В первые можно вносить изменения по ходу разработки программы, вторые создаются только на конечном этапе.
Я поставил условие на номер версии. Теперь программа должна скомпилироваться с версией 4.4.
Вложения
Тип файла: zip Basin-IDEv01.zip (137.9 Кб, 17 просмотров)
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
23.03.2010, 13:32     Пишем свой интерпретатор языка BASIC #355
У меня не компилится. Правда я не знаю, как понять, что за версия qt у меня установлена

Код
g++ -c -pipe -O2 -march=pentium3 -mtune=pentium4 -pipe -fno-strict-aliasing -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I.moc -I.ui -o .obj/main.o main.cpp
In file included from basinmainwindow.h:9,
                 from basinapplication.h:6,
                 from main.cpp:4:
textedit.h:4:26: error: QPlainTextEdit: No such file or directory
Добавлено через 2 минуты
В /usr/lib/qt4 лежат файлы с суффиксами 4.3.5
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
23.03.2010, 13:42     Пишем свой интерпретатор языка BASIC #356
версия -
qmake -v
Добавлено через 29 секунд
дистрибутив какой?
RazorQ
 Аватар для RazorQ
574 / 341 / 9
Регистрация: 06.02.2009
Сообщений: 1,386
23.03.2010, 13:45     Пишем свой интерпретатор языка BASIC #357
Evg, qplaintextedit ввели в 4.4. Я понял что проблема более глобальна. Сейчас подправлю все что смогу
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
23.03.2010, 13:51     Пишем свой интерпретатор языка BASIC #358
Цитата Сообщение от niXman Посмотреть сообщение
дистрибутив какой?
Без понятия. Что админы поставили два года назад, то и стоит
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
23.03.2010, 13:53     Пишем свой интерпретатор языка BASIC #359
Цитата Сообщение от Evg Посмотреть сообщение
Без понятия.
шутка наверное
uname -a
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.03.2010, 13:57     Пишем свой интерпретатор языка BASIC
Еще ссылки по теме:

Пишем свой чекер C++
Не удается откомпилировать интерпретатор М-языка C++
Пишем свой класс, спецификатор доступа protected C++

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

Или воспользуйтесь поиском по форуму:
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
23.03.2010, 13:57     Пишем свой интерпретатор языка BASIC #360
Я думал ты имел в виду дистрибутив Qt
У нас gentoo самопальной админской сборки. Выдача по uname тебе ничего не скажет
Yandex
Объявления
23.03.2010, 13:57     Пишем свой интерпретатор языка BASIC
Закрытая тема Создать тему
Опции темы

Текущее время: 16:45. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru