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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 1509, средняя оценка - 4.80
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
#1

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

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

*****************
Благодаря форуму и 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)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.06.2009, 20:03     Пишем свой интерпретатор языка BASIC
Посмотрите здесь:

C++ Написать интерпретатор программного языка -помощь
Написать Интерпретатор Программного Языка(собственного) C++
C++ пишем свой троян с нуля
C++ Интерпретатор небольшого языка программирования на С++
C++ Интерпретатор музыки стандарта BASIC PLAY на С++
Интерпретатор/компилятор ассемблер-подобного языка C++
Пишем свой чекер C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
RazorQ
576 / 343 / 9
Регистрация: 06.02.2009
Сообщений: 1,386
28.12.2009, 16:55     Пишем свой интерпретатор языка BASIC #321
Ещё, я хочу сделать так: программист набирает ключевое слово, ставит пробел, а слово преобразовывается к одному стилю. Допустим, я набираю PrInT, а IDE меняет на Print. Всё это сделать, само собой, опционально. Как такая идея? И по поводу стиля: лично мне нравиться набирать зарезервированные слова с большой буквы, а здесь я вижу, что всё в верхнем регистре. Наверное, тоже надо вводить опцию.
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
28.12.2009, 17:02  [ТС]     Пишем свой интерпретатор языка BASIC #322
Интерпретатор переводит все символы в верхний регистр перед использованием. Можно подражать той IDE что была для QBASIC - там текст переводился в верхний регистр,что бы пользователь не писал. Да,можно сделать опционально с разными стилями.
Evg
Эксперт CАвтор FAQ
17297 / 5545 / 347
Регистрация: 30.03.2009
Сообщений: 15,095
Записей в блоге: 26
28.12.2009, 22:50     Пишем свой интерпретатор языка BASIC #323
По поводу синтаксической подсветки. Чтобы интерпретатор знал поменьше о языке программирования, я бы в интерпретое завл специальную опцию, по которой он распечатывает в stdout все regexp'ы. Я толком не знаю, как это выглядит, то наверное в текстовом виде это представимо. И IDE бы дёргала интерпретатор и подхватывала этот набор.

Второй вариант - в процессе сборки интерпретатора генерить некий конфиг-файл (файл *.h или в любой другой форме, в которой это можно вкомпилить в исходник), в котором были бы описаны regexp'ы, а при сборке IDE этот файл подцеплять. Этот вариант хорош тем, что в код придётся затаскивать меньше всякого гавна. Но, если делать всё по-хорошему (когда мы формально имеем отдельно исходники интерпретатора, а отдельно исходники IDE), то в комплект поставки интерпреатора должен входить этот конфиг файл. Чтобы теоретические (гипотетические) IDE от других разработчиков лучше состыковывались с интерпретатором. Да и вообще описание всего интерфейса (с какими опциями запускать интерпретатор, как фильтровать выдачу и т.п.) можно построить на базе этих файлов, генерируемых в процессе сборки интерпретатора. Это сильно облегчит жизнь, когда надо будет в интерпреатторе что-то менять.

Добавлено через 26 минут
Цитата Сообщение от RazorQ Посмотреть сообщение
Я тут на коленке подправил
Заведи себе привычку архивировать проект вместе с головным каталогом. Потому как все, кто скачиывает твой файл, вынуждены каталог создавать ручками

Добавлено через 5 минут
При печати ошибки внизу у тебя пишется только текст ошибки. Хотя для порядку надо бы печатать имя файла и номер строки. Или на худой конец слово Error, а то нифига не понятно, что это за окошко внизу такое. Для порядку по опции можно печатать строку запуска интерпретатора (чтобы пользователь знал, как это повторить без IDE).

Сделал код с ошибкой. Запустил. Оно сломалось и строка подсветилось - тут всё нормально. Ошибку исправил, запустил, но текст ошибки в нижнем окне остался. Перед каждым запуском нижнее окно надо чистить

Добавлено через 2 минуты
Когда после ошибочного запуска интерпретатора редактор позиционируется на строке с ошибкой, то строку было бы лучше выделать красным вместо синего (у людей врде что-то похожее сделано, только не помню точно, как именно)
RazorQ
576 / 343 / 9
Регистрация: 06.02.2009
Сообщений: 1,386
03.01.2010, 18:34     Пишем свой интерпретатор языка BASIC #324
Позволю себе несколько замечаний по языку. К следующим заключениям я пришел после непосредственного использования языка и они (заключения) только лишь ИМХО:
  • У цикла while должно быть завершение аналогичное остальным конструкциям, т.е. end while. Я понимаю, что это связано с определенными трудностями, но тем не менее минус одно ключевое слово. Язык ведь для начинающих.
  • Названия типов. Вроде всё в порядке, но обрубки (извиняюсь, если что) никуда не годятся. Сейчас язык удобен для интерпретатора, но я считаю что в последствии его будут использовать. Так вот, "INT" "LNG" "SNG" "DBL" "STR" "VOID" - не подходят, это ж Basic, а не C++. Особенно void - его вообще нет в basic'е. Все остальные назвать полными именами: Integer, Long, Short, Double, String
  • Помойму, вместо func лучше использовать sub или function. Но первое предпочтительнее.
  • Что такое UNTIL? Или оно не поддерживается?
  • Объявлять переменные мне нравиться в стиле Microsoft: Dim varName As Integer = 20
    Слово Dim уже есть, добавить только As и будет очень элегантно смотреться.
Честно, я не смотрел документацию по Q-Basic - было интересно проверить интерпретатор на дружелюбность и интуитивность.
но я считаю что в последствии его будут использовать
Я буду первый на очереди Честно. Мне племянника надо подтягивать, сам люблю Basic - с ним можно расслабиться.
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
04.01.2010, 09:49  [ТС]     Пишем свой интерпретатор языка BASIC #325
>У цикла while должно быть завершение аналогичное остальным конструкциям, т.е. end while. Я понимаю, что это связано с определенными трудностями, но тем не менее минус одно ключевое слово. Язык ведь для начинающих.
Я делал по тому,что написано тут и тут,там сказано,что окончание для while - это WEND.
Про типы :сами названия в строковом представлении в интерпретаторе не используются.Это что-то древнее,которое придётся править.Тип VOID только для внутреннего представления,я его сделал как некий костыль,и значения этого типа могут принимать любой другой тип.Это по идее всего лишь флажок,обозначающий только что созданный объект Value.
Слово FUNC тоже пережиток прошлых попыток с функциями,их было много.
UNTIL: По идее цикл с DO должен выглядеть как
PureBasic
1
2
3
DO
  ...
LOOP UNTIL
А у меня пока так
PureBasic
1
2
3
DO
  ...
WHILE
Не помню,то ли я прочитал где-то об этом варианте,то ли сам выдумал,но это одно из TODO которые надо доделывать.Ключевые слова у меня добавляются просто,поэтому это одно из древних.
Для DIM тоже надо доделывать тот вариант,про который ты пишешь.
Пока я пытаюсь перевести всю программу на классы,там такая каша,ещё поиск по стекам добавился,приходится делать правки вслепую,без компиляции.Потом,когда всё заработает,надо будет,конечно,исправить мелочи выше.
RazorQ
576 / 343 / 9
Регистрация: 06.02.2009
Сообщений: 1,386
04.01.2010, 11:01     Пишем свой интерпретатор языка BASIC #326
Всё. Вопросов нет. Спасибо.
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
18.03.2010, 23:18  [ТС]     Пишем свой интерпретатор языка BASIC #327
Меняю построение синтаксиса DIM всвязи с запланированным добавлением функций (нужно добавить SHARED и[ AS type]),возник вопрос:
DIM ведь по сути ничего не делает,все части этой инструкции или имена переменных,или константы (в случае с измерениями массивов).
С другой стороны,в DIM у меня присутствует некий элемент runtime - именно в этот момент во время интерпретации представления придаются свойства массиву и его элементы обнуляются. Вот я не знаю,стоит ли убрать DIM как часть представления вообще и во время построения содавать все переменные и массивы,часть из этих функций возложив на конструкторы? Или создание переменных следует считать runtime частью ? Моя туманная логика подсказывает,что переменные стоит создавать по мере их встречи в программе.
Evg
Эксперт CАвтор FAQ
17297 / 5545 / 347
Регистрация: 30.03.2009
Сообщений: 15,095
Записей в блоге: 26
18.03.2010, 23:40     Пишем свой интерпретатор языка BASIC #328
Как оно устроено в реальных бэйскиах - я даже не знаю. Я у себя делал так, что DIM - это НЕ statement, а declaration. Т.е. на этапе синтаксического разбора сразу строился тип и переменная этого типа. Но насколько помню, на старых "продвинутых" версиях бэйсиков типа Yamaha в качестве размерности можно было задавать НЕ константу. Но я не помню, насколько это было свободным. Т.е. обязана ли была переменная (выражение) выступающая в качестве размерности массива на момент определения DIM иметь вычислимое значение. По факту во многих программах было что-то типа "LET N=10 ; DIM A(N)" и всё это объявлялось в начале программы. Так что тут надо курить документацию по бэйсику

Что такое SHARED и AS я тоже не знаю. Но из всего описания этого барахла в принципе можно будет понять, массив появляется в runtime или статически (на этапе трансляции)
RazorQ
576 / 343 / 9
Регистрация: 06.02.2009
Сообщений: 1,386
21.03.2010, 11:06     Пишем свой интерпретатор языка BASIC #329
Извиняюсь, за столь долгую отлучку, но всё как-то не получалось. По сравнению с предыдущей версией эта много нового не внесла. Цель которую я преследовал: вытрясти максимально много ошибок. Так сказать, сделать базу на основе которой можно будет развивать программу. И я считаю, что можно присвоит этой программе версию 0.1
Вложения
Тип файла: zip Basin-IDEv01.zip (138.0 Кб, 15 просмотров)
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 12:26     Пишем свой интерпретатор языка BASIC #330
Пересмотрел код Basin-IDE.
Обнаружил лишний new в BasinApplication::newMainWindow()
глянул далее, а там их полно) остальные оставил так.
- "нафига столько new ?"
Вложения
Тип файла: zip Basin-IDE.zip (114.0 Кб, 15 просмотров)
RazorQ
576 / 343 / 9
Регистрация: 06.02.2009
Сообщений: 1,386
21.03.2010, 13:37     Пишем свой интерпретатор языка BASIC #331
niXman, спасибо. В BasinApplication::newMainWindow() действительно не нужно ещё раз выделять память. А вот где ещё нужно убрать new я так и не понял.
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 13:39     Пишем свой интерпретатор языка BASIC #332
Цитата Сообщение от RazorQ Посмотреть сообщение
действительно не нужно ещё раз выделять память
почему "еще раз" ? там вообще ее выделять при помощи new не нужно.

Цитата Сообщение от RazorQ Посмотреть сообщение
где ещё нужно убрать new я так и не понял.
больше половины new можно удалить.
RazorQ
576 / 343 / 9
Регистрация: 06.02.2009
Сообщений: 1,386
21.03.2010, 13:41     Пишем свой интерпретатор языка BASIC #333
Цитата Сообщение от niXman Посмотреть сообщение
больше половины new можно удалить.
Ты имеешь в виду QAction, QMenu и т.д.?
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 13:43     Пишем свой интерпретатор языка BASIC #334
RazorQ, я крайне редко использую new в коде.
в твоем коде, их большую часть можно удалить. автоматические переменные тоже работают
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
21.03.2010, 21:45  [ТС]     Пишем свой интерпретатор языка BASIC #335
Скачиваю версию от niXman,пытаюсь разархивировать,пишет:
Код
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
unzip:  cannot find zipfile directory in one of /media/src/Basin-IDE.zip or
        /media/src/Basin-IDE.zip.zip, and cannot find /media/src/Basin-IDE.zip.ZIP, period.
Можно как-то ещё другим способом выложить? А то Линуксовый архиватор не разархивирует
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 21:48     Пишем свой интерпретатор языка BASIC #336
#pragma, сорри, забыл упомянуть, это .tar.bz2 архив.
просто форум не позволяет заливать .tar.bz2 архивы, вот я и сменил расширение
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
21.03.2010, 21:49  [ТС]     Пишем свой интерпретатор языка BASIC #337
мм,хитро ты придумал) спасибо за идею
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 21:50     Пишем свой интерпретатор языка BASIC #338
ну жить то как-то надо
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
21.03.2010, 22:25  [ТС]     Пишем свой интерпретатор языка BASIC #339
Забавно,буду собирать )
У меня сразу возник вопрос: можно ли максимально упростить структуру файлов?
Я имею в виду то,что мой интерпретатор собирается вместе с GUI по одной команде make (надо только доделать отмену сборки,если есть #define WITHOUT_GUI или подобное)
Мой Makefile выглядит так:
Makefile
Код
#
#
# basin makefile
#
#


# Принятые обозначения: CC - компилятор Си, CXX - компилятор Си++
CXX = g++
CXXFLAGS = -ansi -pedantic -pedantic-errors -Wall -O2 -Os
DFLAGS = -MD
LD = $(CXX)
LDFLAGS = -lSDL
OFILES = Interpreter/debug/error_handler.o \
         Interpreter/main.o \
         Interpreter/lib/lib.o \
         Interpreter/cmd/options.o \
         Interpreter/memory/memory.o \
         \
         Interpreter/frontend/parser.o  \
         Interpreter/frontend/syntax.o \
         \
         Interpreter/intermediate/value.o \
         Interpreter/intermediate/variable.o \
         Interpreter/intermediate/expression.o \
         Interpreter/intermediate/statement.o \
         Interpreter/intermediate/array.o \
         Interpreter/intermediate/label.o \
         \
         Interpreter/runtime/interp.o \
         Interpreter/runtime/function.o \
         Interpreter/runtime/graphics/graphics.o \
         Interpreter/runtime/tracer/tracer.o \
         Interpreter/runtime/pool.o
         
CXXFLAGS += -I. -IInterpreter/runtime -IInterpreter/runtime/graphics  \
-IInterpreter/runtime/tracer -IInterpreter/cmd -IInterpreter/config   \
-IInterpreter/debug -IInterpreter/frontend -IInterpreter/intermediate \
-IInterpreter/lib -IInterpreter/include -IInterpreter/memory          \
-IInterpreter

RM         = rm -f
TARGET     = basin
SUBTARGET  = Basin-IDE
INSTALLDIR = ./compiled
MV         = /bin/mv
LS         = /bin/ls
CURRDIR    = `pwd`
OPT        = *.h *.cpp */*.h */*.cpp
LSFLAGS    = -R $(OPT)
PROGDIR    = ./Interpreter
GUIDIR     = ./GUI/Qt/Basin-IDE
MAKE       = /usr/bin/make
QMAKE      = /usr/bin/qmake
QMKFLAGS   = -project

#`ls -R 'pwd'| sed -r /*.h/*.cpp/`

# По умолчанию прика "make" собирает самую первую цель.
# Обычно её обзывают "all" и уже расписывают, что там должно быть
all: $(TARGET)  $(GUIDIR)/$(SUBTARGET) 

# Линковка из объектников
$(TARGET): $(OFILES)
	$(LD) $(LDFLAGS) $(OFILES) -o $(TARGET) \
	&& $(MV) ./$(TARGET) $(INSTALLDIR)/$(TARGET)
	
$(GUIDIR)/$(SUBTARGET):
	 cd $(GUIDIR) && $(QMAKE) $(QMKFLAGS) $($(LS) $(LSFLAGS)) \
	 && $(QMAKE) && $(MAKE) && cd .. && cd .. && cd .. \
	 && $(MV) $(GUIDIR)/$(SUBTARGET) $(INSTALLDIR)/$(SUBTARGET)

# Подключаем файлы зависимостей
# Заумное выражение справа означает взять переменную OFILES и заменить ".o"
# на ".d"  Т.е. здесь по сути написано "-include debugger.d error_handler.d ..."
# Директива include работает точно так же, как и препроцессорная #include
-include $(OFILES:.o=.d)

# Общее правило формирования объектника. $< означает левую часть зависимости,
# $@ - правую
%.o : %.cpp
	$(CXX) -c $(DFLAGS) $(CXXFLAGS) $< -o $@

clean:
	$(RM) $(GUIDIR)/Makefile */*.pro *.o *.d *.bak *~*  *.log *.status \
   */*.o */*.d */*.bak *.dat */moc_* */qrc_* */qrc_* */*.dat    \
	*/*/*/*.o */*/*/*.d */*/*/*.bak */*/*/moc_* */*/*/qrc_* */*/*/*.dat \
	*/*/*/*.log */*/*/*.pro */*/*.o */*/*.d
distclean:
	$(RM) $(INSTALLDIR)/$(TARGET) \
	$(INSTALLDIR)/$(SUBTARGET)   \
	$(GUIDIR)/Makefile */*.pro *.o *.d *.bak *~*  *.log *.status \
   */*.o */*.d */*.bak *.dat */moc_* */qrc_* */qrc_* */*.dat    \
	*/*/*/*.o */*/*/*.d */*/*/*.bak */*/*/moc_* */*/*/qrc_* */*/*/*.dat \
	*/*/*/*.log */*/*/*.pro */*/*.o */*/*.d

а configure.in так
configure.in
Код
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.61])
AC_INIT([basin], [0.46], [pragma.develop(собачка)gmail.com], [],\
                                       [http://sourceforge.net/projects/basin/])

AC_CONFIG_HEADERS([Interpreter/config/config.h:Interpreter/config/config.h.in])

################################################################################
#
#                      COMMAND LINE ARGUMENTS CHECKS
#
################################################################################

########################### SDL library ############################

AC_ARG_ENABLE(sdl-graphics,
AS_HELP_STRING([--disable-sdl-graphics],[Disable SDL library
 (default: enabled)]),enable_sdl="$enableval",enable_sdl="yes")

AS_IF([(test "${enable_sdl}" != "yes")],
      [AC_DEFINE([DISABLE_SDL_GRAPHICS], [], [Disabling SDL library])])

AC_MSG_NOTICE([Checking for --disable-sdl-graphics option])

# SDL protection from crashes (drawing pixels outside the screen)
AC_ARG_ENABLE(sdl-protection,
AS_HELP_STRING([--disable-sdl-protection],[Disable SDL protection for drawing
 outside the screen (default: enabled)]),enable_protection="$enableval",
 enable_protection="yes")

AS_IF([(test "${enable_protection}" != "yes")],
      [AC_DEFINE([DISABLE_SDL_PROTECTION], [], [Disabling SDL protection for
drawing outside the screen])])

AC_MSG_NOTICE([Checking for --disable-sdl-protection option])

########################## Command line options ###################

# Disable/enable tracing options for interpreter:
#      --trace-act
#      --trace-tree
#      --trace-silent
#      --debug
AC_ARG_ENABLE(tracing,
AS_HELP_STRING([--disable-tracing],[Disable all tracing for interpreting \
program(default: enabled)]),enable_tracing="$enableval",enable_tracing="yes")

AS_IF([(test "${enable_tracing}" != "yes")],
      [AC_DEFINE([DISABLE_TRACING], [], [Disabling tracing])])

AC_MSG_NOTICE([Checking for --disable-tracing option])

################################################################################
#
#                            PROGRAM CHECKS
#
################################################################################
AC_PROG_CXX
AC_PROG_CC

#Checking for cp
AC_CHECK_PROG(having_cp,cp,found,not found)

AS_IF([(test "${having_cp}" != "found")],
      [AC_MSG_FAILURE([cp program not found.May be you are using non standart \
environment.Please view configure.in file,"PROGRAM CHECKS" part to fix the \
problem.])])

################################################################################
#
#                            LIBRARIES CHECKS
#
################################################################################
# Checking for availability of #include <QtGui>
AC_CHECK_FILE([/usr/include/qt4/QtGui/QtGui],[],
              [AC_MSG_FAILURE([Qt 4 development files not found.\
Please install them and try again.On some Debian-based systems simply type \
in terminal: sudo apt-get install libqt4-dev .If you are using non-standart \
system environment,please review configure.in file,"LIBRARIES CHECKS" part,\
fix the path manually,use autoconf and then again configure.])])

AC_CHECK_LIB([QtGui], [connect], [],
             [AC_MSG_FAILURE([Qt 4 Gui library not found.\
Please install it and try again.On some Debian-based systems simply type \
in terminal: sudo apt-get install libqt4-gui.I don't know how it can be\
since you have /usr/include/qt4/QtGui/QtGui file in your system :O ])])

AC_CHECK_LIB([SDL], [SDL_Init], [],
              [AC_MSG_FAILURE([SDL library development files not found.\
Please install them and try again.On some Debian-based systems simply type \
in terminal: sudo apt-get install libsdl-dev])])

AC_CHECK_LIB([pthread], [pthread_create], [],
              [AC_MSG_FAILURE([You dont have POSIX threads library installed on\
 your system.Please install this library and try again.])])

################################################################################

# Checks for typedefs, structures, headers and compiler characteristics.
AC_HEADER_STDBOOL
AC_C_INLINE
AC_TYPE_SIZE_T
AC_CHECK_FUNCS([sqrt])
AC_OUTPUT

################################################################################

# This project using same config file for all interfaces(command-line and gui)
# FIXME

AC_MSG_NOTICE([Copying ./Interpreter/config/config.h to
./GUI/Qt/Basin-IDE/config.h])

cp ./Interpreter/config/config.h ./GUI/Qt/Basin-IDE/config.h

################################################################################

И в конце configure.in есть строчка копирования config.h из директории интерпретатора (autoheader принимает только один путь к config.h как я понял) в папку с GUI.То есть они используют один и тот же config.h,надо это как-то учесть(или придумать какой-то способ с одного конфигуратора генерировать все нужные файлы конфигов). А также то,что .pro файлы и все файлы,генерируемые автоматически лучше,наверное,исключить?
Просто пользователю,скорее всего,удобнее один раз запустить configure ,и один раз make,чтобы всё собралось и все нужные файлы сгенерировались. Или принято,чтобы все эти файлы были в проекте?
Что такое файлы .ts? они у меня не открываются ничем.А также файлы .qm, Doxyfile, .pro.user, .qrc (этот можно сгенерировать).
Конечно,я могу сам "причёсывать" GUI,это не проблема,но просто было бы интереснее договориться,по крайней мере какое-то подобие соглашения должно быть насчёт сборки. Ведь лучше,чтобы всё собиралось просто,или может я тут неправ?

Добавлено через 10 минут
Что-то у меня не компилится,что подправить?
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/media/src/Basin-IDE$ qmake
/media/src/Basin-IDE$ make
/usr/bin/uic-qt4 finddialog.ui -o .ui/ui_finddialog.h
Warning: name layoutWidget is already used
Warning: name layoutWidget is already used
g++ -c -pipe -O2 -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/highlighter.o highlighter.cpp
g++ -c -pipe -O2 -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
g++ -c -pipe -O2 -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/basinmainwindow.o basinmainwindow.cpp
basinmainwindow.cpp: In member function ‘void BasinMainWindow::init()’:
basinmainwindow.cpp:19: error: ‘class TabWidget’ has no member named ‘setTabsClosable’
basinmainwindow.cpp:20: error: ‘class TabWidget’ has no member named ‘setMovable’
basinmainwindow.cpp: In member function ‘void BasinMainWindow::createActions()’:
basinmainwindow.cpp:174: error: ‘Quit’ is not a member of ‘QKeySequence’
make: *** [.obj/basinmainwindow.o] Error 1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.03.2010, 22:34     Пишем свой интерпретатор языка BASIC
Еще ссылки по теме:

Задание: разработать "Интерпретатор языка". С чего начать? C++
По русскому названию языка программирования определить английское название этого языка C++
C++ Перепишите пожалуйста код программы с языка Visual Basic в C++
Не удается откомпилировать интерпретатор М-языка C++
Пишем свой класс, спецификатор доступа protected C++

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

Или воспользуйтесь поиском по форуму:
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.03.2010, 22:34     Пишем свой интерпретатор языка BASIC #340
Цитата Сообщение от #pragma Посмотреть сообщение
Что-то у меня не компилится
версия Qt какая?

Добавлено через 1 минуту
наверное 4.5.2

Добавлено через 31 секунду
проверить так:
qmake -v
Yandex
Объявления
21.03.2010, 22:34     Пишем свой интерпретатор языка BASIC
Закрытая тема Создать тему
Опции темы

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