Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/1283: Рейтинг темы: голосов - 1283, средняя оценка - 4.69
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
1

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

20.06.2009, 20:03. Показов 242567. Ответов 464
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Благодаря форуму и Evg в частности интерпретатор развивается, потихоньку превращаясь в простенький интерпретатор QBASIC.
Некоторые из самых старых версий сохранились в теме и ссылки на них будут добавлены в это сообщение,а также ссылки на другие темы,связанные с этой.

Репозиторий с проектом находится тут, там же есть возможность в браузере посмотреть историю ревизий (английский в логах весьма примитивен,комментарии и рекомендации можете писать в личку),а также скачать самый последний архив репозитория в формате .tar.gz
Если кто-то пользуется Subversion,скачать исходники можно так:
Код
svn co https://basin.svn.sourceforge.net/svnroot/basin basin
Эти темы возникли в результате моих вопросов по ходу написания:
Технический приём для формирования согласованных данных
https://www.cyberforum.ru/c-linux/thread46096.html
Вопрос по svn (Subversion)
Создание системы тестирования ПО.
Вопрос про разные реализации бэйсиков
Можно ли выразить порядковый номер элемента массива через индексы?
[C++] Какие флаги указать линкеру для компиляции программы?
Как можно определить переменную в файле configure.in,чтобы её можно было использовать в Makefile?
Странный SIGSEGV, или что зависит от порядка написания интерфейса класса
https://www.cyberforum.ru/c-linux/thread61324.html
Альтернативная версия интерпретатора от 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;
31
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.06.2009, 20:03
Ответы с готовыми решениями:

Пишем свой интерпретатор языка BASIC
Добрый день. Я смотрю, тут на форуме была тема коллективного написания интерпретатора BASIC на...

Пишем свой strlen
Всем привет, вырвал часть задание из общего задание по написанию своего string. На данном этапе...

Пишем свой чекер
Я хочу написать свой чекер, но не знаю с чего начать? Кто знает основные принцип работы чекеров...

пишем свой троян с нуля
Всем привет)))соглашусь, что изобретаю велосипед, но хочется сделать все своими ручками не прибегая...

464
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
21.03.2010, 22:38  [ТС] 341
Author24 — интернет-сервис помощи студентам
Bash
1
2
3
qmake -v
QMake version 2.01a
Using Qt version 4.4.0 in /usr/lib
1
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 22:40 342
с этой версией не соберется.
а дистр у тебя какой?

Добавлено через 28 секунд
с оф. сайта качай исходники или SDK.
1
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
21.03.2010, 22:42  [ТС] 343
Понял.
Пользуюсь Ubuntu 8.04 64-битной
Для порядка тогда надо мне в configure.in добавить какую-то проверку на версию Qt для этого интерфейса.Т.е. если этой версии нет,то выдаём предупреждение и собираем что можно)
1
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 22:50 344
Цитата Сообщение от #pragma Посмотреть сообщение
Для порядка тогда надо мне в configure.in добавить какую-то проверку на версию Qt для этого интерфейса
я знаю как это реализуется в .pro файле. а вот по поводу configure я ничего не знаю
1
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
22.03.2010, 15:32 345
Цитата Сообщение от niXman Посмотреть сообщение
с этой версией не соберется.
а дистр у тебя какой?

Добавлено через 28 секунд
с оф. сайта качай исходники или SDK.
Вообще говоря, когда для простенького редактора нужна самая последняя версия Qt, а на чуть более ранних оно уже не собирается - помоему в топку такие оладушки
3
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
22.03.2010, 15:38 346
Цитата Сообщение от Evg Посмотреть сообщение
Вообще говоря, когда для простенького редактора нужна самая последняя версия Qt, а на чуть более ранних оно уже не собирается - помоему в топку такие оладушки
Версия 4.5.2 нужна только лишь из-за кнопочек на вкладках. Так что можно этот код не включать если версия ниже. Функциональность сохраняется
2
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
22.03.2010, 21:36  [ТС] 347
Цитата Сообщение от RazorQ Посмотреть сообщение
Версия 4.5.2 нужна только лишь из-за кнопочек на вкладках. Так что можно этот код не включать если версия ниже. Функциональность сохраняется
Я так сразу не вьеду,что там выбрасывать из кода именно,собери,если можно,рабочую версию,чтобы компилилось.

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

Добавлено через 8 минут
О! а лучше сделай #define QT_4.5.2 или похожий,и пусть этот код аккуратно выбрасывается с помощю этого define-а,тогда я смогу у себя в configure сделать опцию по которой идет проверка версии Qt (по крайней мере,я могу попробовать),и тогда всё это можно будет делать автоматом.
1
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
22.03.2010, 21:59 348
Цитата Сообщение от #pragma Посмотреть сообщение
а лучше сделай #define QT_4.5.2 или похожий
В Qt, как и любой другой уважающей себя библиотеке, должны быть встроенные макросы версии
2
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
22.03.2010, 22:34 349
Цитата Сообщение от Evg Посмотреть сообщение
В Qt, как и любой другой уважающей себя библиотеке, должны быть встроенные макросы версии
Qt очень бурно развивается. И тролли, честно говоря, не особо беспокоятся по поводу обратной совместимости.
1
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
22.03.2010, 23:21 350
Совместимость - это одно, а макрос текущей версии - другое, с совместимостью мало связанное. Есть же макросы __GNUC__, __GNUC_MINOR__. Вот может и у Qt есть что-то подобное
1
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
22.03.2010, 23:26 351
Evg, ты спрашиваешь макрос, который содержит текущую версию?
1
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
22.03.2010, 23:35 352
Ну да. А под этим макросом ты просто включаешь или не включаешь фичу, которая есть в одной версии и нет в другой
1
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
22.03.2010, 23:43 353
вот теперь понял.
QT_VERSION
QT_VERSION_STR
QT_VERSION_CHECK()
1
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
23.03.2010, 13:25 354
Цитата Сообщение от #pragma Посмотреть сообщение
Так .ts это файлы переводов? А что такое .qm?
Да, .ts это файлы перевода, но в формате XML. .qm это скомпилированные файлы перевода, которые и используются в программе. В первые можно вносить изменения по ходу разработки программы, вторые создаются только на конечном этапе.
Я поставил условие на номер версии. Теперь программа должна скомпилироваться с версией 4.4.
Вложения
Тип файла: zip Basin-IDEv01.zip (137.9 Кб, 19 просмотров)
1
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
23.03.2010, 13:32 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
0
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
23.03.2010, 13:42 356
версия -
qmake -v
Добавлено через 29 секунд
дистрибутив какой?
1
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
23.03.2010, 13:45 357
Evg, qplaintextedit ввели в 4.4. Я понял что проблема более глобальна. Сейчас подправлю все что смогу
1
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
23.03.2010, 13:51 358
Цитата Сообщение от niXman Посмотреть сообщение
дистрибутив какой?
Без понятия. Что админы поставили два года назад, то и стоит
1
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
23.03.2010, 13:53 359
Цитата Сообщение от Evg Посмотреть сообщение
Без понятия.
шутка наверное
uname -a
0
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
23.03.2010, 13:57 360
Я думал ты имел в виду дистрибутив Qt
У нас gentoo самопальной админской сборки. Выдача по uname тебе ничего не скажет
1
23.03.2010, 13:57
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.03.2010, 13:57
Помогаю со студенческими работами здесь

Пишем свой класс, спецификатор доступа protected
Всем привет! Из книги Р. Лафоре относительно спецификатора доступа protected: Далее пишется...

Интерпретатор небольшого языка программирования на С++
Здравствуйте, уважаемые форумчане! Я тут где-то год назад прочитал тему Evg и #pragma о создании...

Не удается откомпилировать интерпретатор М-языка
Задача: взять интерпретатор М-языка на сайте...

Интерпретатор музыки стандарта BASIC PLAY на С++
У кого нибудь есть функция или класс, который сможет воспроизводить в С++ напрямую музыкальные...

Написать интерпретатор программного языка -помощь
Здраствуйте! Ребят, кто хорошо разбирается в C++ помогите пожалуйста с реализацией данного задания...

Интерпретатор/компилятор ассемблер-подобного языка
Привет! Чую, что изобрёл велисипед, даже скорее велопарк, но всё же, поделюсь: Некоторое время...


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

Или воспользуйтесь поиском по форуму:
360
Закрытая тема Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru