Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Qt и flex/bison или antlr + Visual Studio, работа с Qt и flex/bison or antlr 
:(
    Опции темы
baldina
Дата 26.3.2013, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(Elfenlide @  26.3.2013,  18:32 Найти цитируемый пост)
миллион ифов писать не хочеться потому что это не правильно

простейший парсер сверху вниз - не надо много if, а для поиска ключевых слов используйте std::map

давайте-ка придумайте полностью ваш язык, опишите, дальше подумаем что и как делать

PM MAIL   Вверх
fish9370
Дата 27.3.2013, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 15.4.2007
Где: Москва

Репутация: 1
Всего: 1



может к черту бизон? 

регулярные выражения, парсер, шаблонизатор, пара шаблонов..


--------------------
undefined
PM MAIL WWW ICQ   Вверх
Elfenlide
Дата 27.3.2013, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 8.9.2012
Где: Беларусь

Репутация: нет
Всего: нет



Цитата(baldina @  26.3.2013,  18:45 Найти цитируемый пост)
давайте-ка придумайте полностью ваш язык, опишите, дальше подумаем что и как делать

нужно реализовать возможность:
◦ указывать ссылки на другие страницы;
◦ вставлять изображения в текст;
◦ устанавливать выравнивание текста и его стиль (аналоги тегов <b><i><u><font>).
Я придумал так: $ это будет главное отличие, тоесть если не знак доллара, то свободно читаем как обычный символ и выводим как читаем.
вместо тегов b, i, u, font, ,будут: $Bold() , $Kursiv(), $UnderLine(), $Font() - для простоты я решил изменить его, html эквивалентный имеет 3 параметра: высота символа, тип шрифта, цвет. Следовательно будут отдельные теги: $Color(), $Size(), $TypeText(). Ну и в таком стиле остальные: ссылки, загрузка картики. 
Просто если я буду считывать каждый символ, то это ифы итд...я уже накидал код такой, который по сиволам разбирает, но исключительно из-за того что скоро здавать нужно будет, и не хочу двойку. А вот что-то толковое изучить, какой-то метод которым можно парсер хороший написать я не знаю, поэтому и хотел взять бизон и флекс...
Мой код на данный момент\ я думаю это не очень красивый вариант решения данной задачи. Я пишу на Qt, но тут от Qt только QString, остальное как в стандартном с++.

Код

void KursiveText(QString& KursiveStr, int& i, QString& str, QString& tempStr, int& tempStrInd);
void BoldText(QString& BoldStr,int& i, QString& str, QString& tempStr, int& tempStrInd);
void UnderLineText(QString& UnderLineStr,int& i, QString& str, QString& tempStr, int& tempStrInd);
void SizeText(QString& SizeStr,int& i, QString& str, QString& tempStr, int& tempStrInd);
void Endl(int& tempStrInd, QString& tempStr, int& i);

QString WebBrowser::parsing(QString str)
{
    QString tempStr;
    QString KursiveStr = "";
    QString BoldStr = "";
    QString UnderLineStr = "";
    QString SizeStr = "";
    int tempStrInd = 0;

    for(int i = 0; i < str.size(); i++)
    {
        if(str[i] == '$')
        {
            i++;

            if(str[i] == 'K' && str[i+1] == '(')
            {
                KursiveText(KursiveStr, i, str, tempStr, tempStrInd);
            }
            else if(str[i] == 'e' && str[i+1] == 'n'
                && str[i+2] == 'd' && str[i+3] == 'l'
                && str[i+4] == '(' && str[i+5] == ')')
            {
                Endl(tempStrInd, tempStr, i);
            }
            else if(str[i] == 'B' && str[i+1] == '(')
            {
                BoldText(BoldStr, i, str, tempStr, tempStrInd);
            }
            else if(str[i] == 'U' && str[i+1] == '(')
            {
                UnderLineText(UnderLineStr, i, str, tempStr, tempStrInd);
            }
            else if(str[i] == 'S' && str[i+1] == '(')
            {
                SizeText(SizeStr, i, str, tempStr, tempStrInd);
            }
            
        }
        else
        {
            tempStr[tempStrInd] = str[i];
            tempStrInd++;
        }        

    }

    return tempStr;
}

void KursiveText(QString& KursiveStr, int& i, QString& str, QString& tempStr, int& tempStrInd)
{
    int tempINDEX = 0;
    int KursiveInd = i+2;
    i = KursiveInd;

    while(str[i] != ')')
    {
        KursiveStr[tempINDEX] = str[KursiveInd];
        tempINDEX++; i++; KursiveInd++;
    }

    QString htmlRezult;
    htmlRezult = "<i>";
    htmlRezult += KursiveStr + "</i>";
    KursiveStr = htmlRezult;

    tempStr += KursiveStr;
    tempStrInd += KursiveStr.size();
    KursiveStr = "";
}

void BoldText(QString& BoldStr, int& i, QString& str, QString& tempStr, int& tempStrInd)
{
    int tempINDEX = 0;
    int BoldInd = i+2;
    i = BoldInd;

    while(str[i] != ')')
    {
        BoldStr[tempINDEX] = str[BoldInd];
        tempINDEX++; i++; BoldInd++;
    }

    QString htmlRezult;
    htmlRezult = "<b>";
    htmlRezult += BoldStr + "</b>";
    BoldStr = htmlRezult;

    tempStr += BoldStr;
    tempStrInd += BoldStr.size();
    BoldStr = "";
}

void UnderLineText(QString& UnderLineStr, int& i, QString& str, QString& tempStr, int& tempStrInd)
{
    int tempINDEX = 0;
    int UnderLineInd = i+2;
    i = UnderLineInd;

    while(str[i] != ')')
    {
        UnderLineStr[tempINDEX] = str[UnderLineInd];
        tempINDEX++; i++; UnderLineInd++;
    }

    QString htmlRezult;
    htmlRezult = "<u>";
    htmlRezult += UnderLineStr + "</u>";
    UnderLineStr = htmlRezult;

    tempStr += UnderLineStr;
    tempStrInd += UnderLineStr.size();
    UnderLineStr = "";
}

void SizeText(QString& SizeStr,int& i, QString& str, QString& tempStr, int& tempStrInd)
{
    int tempINDEX = 0;
    int  SizeStrInd = i+2;
    i =  SizeStrInd;

    while(str[i] != ')')
    {
        SizeStr[tempINDEX] = str[ SizeStrInd];
        tempINDEX++; i++;  SizeStrInd++;
    }

    QString htmlRezult;
    htmlRezult = "<font size = 7>";
    htmlRezult += SizeStr + "</font>";
    SizeStr = htmlRezult;

    tempStr += SizeStr;
    tempStrInd += SizeStr.size();
    SizeStr = "";
}

void Endl(int& tempStrInd, QString& tempStr, int& i)
{
    tempStr += "<br/>";
    tempStrInd += 5;
    i += 5;
}


Добавлено через 9 минут и 5 секунд
Да, забыл дописать, то что будет в скобках тега, то и будет обрабатываться им. $Bold(Hello) $UnderLine(World). Обрабатываются Hello и  World соответственно.
PM MAIL Skype   Вверх
math64
Дата 27.3.2013, 15:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



У тебя не $Bold() , а $B() и т. д. 
Не обрабатывается вложенность типа $B($I(Hello) $U(World))
т.е нужно искать не первую ), а парную и внутренность рекурсивно обрабатывать.
Поиск $:
Код

int index = str.indexOf('$', from);


Генерировать html проще так:
Код

QString boldStr = QString("<b>%1</b>").arg(str);

PM   Вверх
Elfenlide
Дата 27.3.2013, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 8.9.2012
Где: Беларусь

Репутация: нет
Всего: нет



Да, у меня $B() а не $Bold(), но это временно, для того чтобы быстрее писать программу, когда будет готова, чутка буду поправлять. Но честно говоря заканчивать её с кучей инструкций а не толковым парсером, желания нет.
baldina с мапом предлагает как-то замутить, вот мне это интересно. Может что-то классное выйдет.

Цитата(math64 @  27.3.2013,  15:39 Найти цитируемый пост)
Не обрабатывается вложенность типа $B($I(Hello) $U(World))

Я её думал сделать вызвав проверку на вложенность внутри методов путём просмотра строки между "()", но чуть позже.
Я считаю что это вообщей самый ущербный метод, которые для "лишь бы сделать и забыть"...ну...я про это выше писал.
Я знаю ещё есть метод конечного автомата со стеком состояний, как-то мне нужно было вводить строку типа {a,b,c,d,g,{u,j,k}} и создавать объекты собственного класса "множества" с элементами, ну и при этом должна быть фишка что множество может быть элементом другого множества.
Но там только {} из символов,а тут нужно кучу разных тегов замутить...
Вот как-то так:
Код

Set Set::parse(stringstream &str)
{
    enum { 
        OPEN,
        ELEMENT,
        NEXT
    } state = OPEN;

    Set theSet;
    while (!str.eof()) {
        switch (state) {
        case OPEN:
            switch (str.get()) {
            case ' ':   continue;

            case '{':  state = ELEMENT;
                continue;
            default:    return Set();
            }
        case ELEMENT:
            switch (str.peek()) {
            case ' ':  
                {
                    str.ignore();
                    continue;
                }

            case ',':  { return Set(); }

            case '}': 
                {
                    str.ignore();
                    return theSet;
                }

            case '{':
                {    
                    theSet.add(parse(str));
                    state = NEXT;
                    continue;
                }

            default:    theSet.add(str.get());
                state = NEXT;
                continue;
            }
        case NEXT:
            switch (str.get()) {
            case ' ':  { continue; }

            case ',':  
                {
                    state = ELEMENT;
                    continue;
                }


            case '}':   return theSet;

            default:    return Set();
            }
        }
    }
    return Set();
}


PM MAIL Skype   Вверх
math64
Дата 27.3.2013, 20:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



QMap можно использовать так:
Код

QMap<QString,QString> map;
map["Bold"]="<b>%1</b>";

Ключи - теги между $ и (
Значения - код html с %1 на месте вставки аргумента.

Добавлено через 13 минут и 7 секунд
А вместо автомата с состояниями - используй рекурсию, при этом код будет более понятным.
В этом случае текущее состояние определяется вызовами на стеке.
PM   Вверх
Elfenlide
Дата 27.3.2013, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 8.9.2012
Где: Беларусь

Репутация: нет
Всего: нет



QMap<QString,QString> map;
map["Bold"]="<b>%1</b>";

Ключи - теги между $ и (
Значения - код html с %1 на месте вставки аргумента.[/quote]
не совсем понял как работает, если я создам map["Bold"] то когда считывание строки будет происходить, он сам определит последовательность символов map?
Если можно с каким-то простеньким примером поясните пожалуйста.

PM MAIL Skype   Вверх
math64
Дата 28.3.2013, 07:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Ищешь $ или ) - что первое встретится. 
Код

QRegExp re("(\\$([A-Za-z]+)\\()|\\)");

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

QString key = re.cap(2);
if (!map.contains(key)) {
  << неверный тег >>
}
QString html = map[key];

далее делаешь рекурсивный вызов parse() - на выходе индекс должен стоять на ')'
Код

QString tmp = parse();
if (index >= str.lengh() || str[index] != ')') {
  << нет парной скобки >>
}
res += html.arg(tmp);

и повторяшь поиск.

Это сообщение отредактировал(а) math64 - 28.3.2013, 07:34
PM   Вверх
Elfenlide
Дата 28.3.2013, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 8.9.2012
Где: Беларусь

Репутация: нет
Всего: нет



Код

QString key = re.cap(2);

эта строка отвечает за то что следующие 2 символа будут считаны из потока я так понял?которые идут после знака $ 
PM MAIL Skype   Вверх
math64
Дата 28.3.2013, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



cap(0) - вся найденная строка $Bold(
cap(1) - первый фрагмент - $Bold( - выделен аргумент | - (\\$([A-Za-z]+)\\()
cap(2) - второй фрагмент - Bold  - специально выделено скобочками - ([A-Za-z]+)
На всякий случай проверь:
Код

qDebug() << "re.cap(0)=" << re.cap(0);
qDebug() << "re.cap(1)=" << re.cap(1);
qDebug() << "re.cap(2)=" << re.cap(2);


Добавлено через 11 минут и 12 секунд
Код

QRegExp re("\\$([A-Za-z]+)\\(|\\)");
...
QString key = re.cap(1);

Аргумент | можно специально не выыделять - скобки нужны когда выриантная не вся строка, пример из документации:
Код

QRegExp rx("(\\d+)(\\s*)(cm|inch(es)?)");
int pos = rx.indexIn("Length: 36 inches");
QStringList list = rx.capturedTexts();
// list is now ("36 inches", "36", " ", "inches", "es")

PM   Вверх
xvr
Дата 28.3.2013, 14:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



А я бы все же посмотрел в сторону bison'а. Ваша грамматика вся умещается в пару строк -
Код

%union {
 char* str;
 ProgItem* prog;
}
%token<str> vCTRL
%token<str> vSTR
%type<prog> prog p_item
$$
top: prog {set_output($1);} ;
prog: p_item | prog p_item {$$=join($1,$2);};
p_item: vSTR {$$=new PIString($1);}
       | vCTRL '(' prog ')' {$$=new PICtrl($1,$3);}
       ;

Где vCTRL - все слова, начинающиеся с $, а vSTR - все остальные символы (кроме скобок)

Если делать это на flex'е, то это будет так
Код

$[a-f]+  { yylval.str = strdup(yytext); return vCTRL;}
[()]        { return yytext[0]; }
[^()$]+ { yylval.str = strdup(yytext); return vSTR;}
Вместо strdup лучше взять что нибудь поближе к С++  smile 

Базовый класс ProgItem представляет кусок текста или фидективу форматирования. Он умеет вязаться в списки (функция ProgItem* join(ProgItem*,ProgItem*) )
Классы PIString и PICtrl - его наследники для чистых строк текста и директив форматирования соотвественно.
Функция set_output передает наружу результат парсинга - дерево, соотвествующее вашему тексту.

bison можно взять обычный С'ный - результат соберется в режиме С++

PM MAIL   Вверх
Elfenlide
Дата 28.3.2013, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 8.9.2012
Где: Беларусь

Репутация: нет
Всего: нет



Цитата(xvr @  28.3.2013,  14:49 Найти цитируемый пост)
Если делать это на flex'е, то это будет так

Я чутка не понял, так можно либо на флексе, либо на бизоне делать? я просто из всего что читал, понял что нужно их вместе использовать, лексер задаёт правила, парсер по ним работает.
И я попробовал написать ваш код флекса, и получил в консоли кучу ошибок, насколько я понял синтаксис, правила должны быть заключены в %% %%, я добавил, вроде нормально сгенерировалось, осталось теперь только понять одно\ как этим делом пользоваться. Радость что теперь понимаю как генерировать это всё дело)Спасибо за это огромное).

math64 и вас спасибо большое за помощь, попробую двумя способами сделать, лишним не будет.
PM MAIL Skype   Вверх
math64
Дата 28.3.2013, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



бизон работает в паре в флексом.
Если планируестя усложнение грамматики, можно воспользоваться бизоном+флексом,
а на теперешнем уровне для разбора достаточно одной рекурсивоной функции - так проще.
В том числе и для отладки - отдаживаться в коде, сгенерированном бизоном неудобно.
PM   Вверх
lexxmark
Дата 8.4.2013, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 8.4.2013

Репутация: нет
Всего: нет



Привет, попробую помоч с flex/bison для Qt.
Прежде всего добавь в начало своего *.pro файла вот этот кусок кода. Тут настраивается qmake, что бы обрабатывать flex/bison файлы. 
Код

# объявляем новый обработчик файлов
flex.name = Flex ${QMAKE_FILE_IN}
# определяем что входными данными будет список файлов FLEX_SOURCES
flex.input = FLEX_SOURCES
# определяем какие будут получаться выходные файлы
flex.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp
# определяем какую команду надо вызвать для каждого входного файла 
win32:flex.commands = win_flex --wincompat -o ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp ${QMAKE_FILE_IN}
# это версия команды для linux
unix:flex.commands = flex -o ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp ${QMAKE_FILE_IN}
# говорим что наш генератор должен выполняться до основной компиляции
flex.CONFIG += target_predeps
# говорим что выходные файлы - исходники на C++, что бы они попали в компиляцию
flex.variable_out = GENERATED_SOURCES
# регистрируем только что настроенный объект flex  как внешний компилятор в qmake
QMAKE_EXTRA_COMPILERS += flex

# аналогично с bison
bison.name = Bison ${QMAKE_FILE_IN}
bison.input = BISON_SOURCES
bison.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.parser.cpp
win32:bison.commands = win_bison -d -o ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.parser.cpp ${QMAKE_FILE_IN}
unix::bison.commands = bison -Wmidrule-value -t -d -o ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.parser.cpp ${QMAKE_FILE_IN}
bison.CONFIG += targets_predeps
bison.variable_out = GENERATED_SOURCES
QMAKE_EXTRA_COMPILERS += bison


Далее ниже в этом же *.pro файле прописываешь свои flex и bison файлы, например так:
Код

FLEX_SOURCES += MyFile.l
BISON_SOURCES += MyFile.y


После этого перестраиваешь проект и у тебя должны генерироваться MyFile.lexer.cpp и MyFile.parser.cpp файлы.
Сами команды генерации (flex.commands/bison.commands) можешь адаптировать под свои нужды - менять параметры запуска.
 Как видишь для windows версии используется win_flex/win_bison. Их можешь взять отсюда: http://sourceforge.net/projects/winflexbison/
Это более компактные версии flex/bisоn.
Как работать с flex/bison - можешь почитать pdf-ки с того же источника.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1502 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.