Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Создание компиляторов связкой lex&yacc

Автор: DV
Дата сообщения: 23.03.2003 17:02
Крик души!!! Помогите кто чем сможет!
Я создал генератором лексических анализаторов lex распознаватель lex.yy.c и yacc-ом y.tab.c (синтаксический анализатор + генератор кода):
1) Как корректно передавать значения констант из lex.yy.c в y.tab.c для дальнейшего использования в генераторе кода?
2) Как скомпилировать всё это добро в исполняемый код?
Заранее благодарен за любую предоставленную информацию!
Автор: Mickey_from_nsk
Дата сообщения: 24.03.2003 07:34
Я давно уже не использую "чистые" lex и yacc, а вместо них использую их GNU-тые аналоги - flex и bison соответственно. IMHO они помощнее будут и в то же время - полностью совместимы с этими инструментами(обратно - нет). Расскажу все на этом инструментарии.

Цитата:
Как корректно передавать значения констант из lex.yy.c в y.tab.c для дальнейшего использования в генераторе кода?

Вот что пишется в документации по этому поводу. To use flex with yacc, one specifies the -d option to yacc to instruct it to generate the file y.tab.h containing definitions of all the %tokens appearing in the yacc input. То есть, при компиляции .y файла используешь ключ -d, в результате создается файл y.tab.h с определениями констант, соответствующих лексемам. Затем включаешь этот файл в .l и компилируешь этот файл lex-ом (или flex-ом).

Цитата:
Как скомпилировать всё это добро в исполняемый код?

Здесть - просто берешь сгенерированные файлы, суешь их на вход компилятора C вместе с файлами, обслуживающими компилятор и библиотеками lex и yacc и получаешь исполняемый файл.
Для более подробной информации - пиши по крайней мере ОС и компилятор, которые используешь.
Автор: DV
Дата сообщения: 29.03.2003 23:49
Mickey_from_nsk
Спасибо огромное за информацию. Мне всё равно на какой ОС писать, но желательно под Windows. Вообще моя задача заключается в том, чтоб написать компилятор Си-программы с упрощённой грамматикой в ассемблерный код. Насчёт генераторов анализаторов у меня тут руки развязаны, я волен выбирать любые (послушаюсь совета и попробую всё-таки flex-ом и bison-ом). По дороге возникли ещё такие вопросы:
1) Возможно ли flex-ом и bison-ом (или lex-ом и yacc-ом) создавать исходники, которые можно скомпиллировать обычным Borland C++ 3.1 в Windows-е?
2) Каким образом передаётся исходник на моём модифицированном языке для компиляции (через параметр? [вроде: compiler.exe source.c ?])
3) Поподробнее про описание семантики в yacc-спецификации (не обязательно).
Ещё раз огромное спасибо и за эту информацию!
Автор: aarrtteemm
Дата сообщения: 30.03.2003 10:47
DV


Цитата:
1) Возможно ли flex-ом и bison-ом (или lex-ом и yacc-ом) создавать исходники, которые можно скомпиллировать обычным Borland C++ 3.1 в Windows-е?


Я компилировал даже в Turbo C 1.0. Генерируемый код компилируется практически любым ANSI-совместимым компилятором.


Цитата:
2) Каким образом передаётся исходник на моём модифицированном языке для компиляции (через параметр? [вроде: compiler.exe source.c ?])


Это смотря как ты организуешь. По умолчанию, чтение идет со стандартного потока ввода stdio. Но можно переопределить функцию input() и макрос YY_INPUT для чтения из любого другого места - файла или строки.
Автор: DV
Дата сообщения: 30.03.2003 22:23
aarrtteemm

Цитата:
Я компилировал даже в Turbo C 1.0. Генерируемый код компилируется практически любым ANSI-совместимым компилятором.

#include <unistd.h> - подключается хедер в файле lex.yy.c, но такого хедера нет в BC31, так что я не смог скомпиллировать, можете подсказать, каким образом это сделать?

Цитата:
Но можно переопределить функцию input() и макрос YY_INPUT для чтения из любого другого места

А как выглядит эта стандартная функция?
Спасибо за то, что меня ещё терпите
Автор: Mickey_from_nsk
Дата сообщения: 31.03.2003 06:16
DV

Цитата:
#include <unistd.h> - подключается хедер в файле lex.yy.c, но такого хедера нет в BC31, так что я не смог скомпиллировать, можете подсказать, каким образом это сделать?

Это стандартный header для UNIX. В нем перечислены прототипы для функций типа open, read, write и т.д. Для обхода этого есть два варианта (я такие нашел, их может быть и больше).
1. Создать такой файл, в него включить, если не ошибаюсь, io.h, скопировать его в стандартный каталог для header-файлов. Ну в смысле, где всякие stdio.h лежат.
2. Отредактировать файл-skeleton для flex и подключить его при компиляции flexом. там есть ключик, например, у меня это выглядит как "-Sc:\local\share\flex.skl"

Цитата:
А как выглядит эта стандартная функция?


Код:
#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput YY_PROTO(( void ));
#else
static int input YY_PROTO(( void ));
#endif
#endif
Автор: DV
Дата сообщения: 03.04.2003 21:20
Так будет проще: Я сейчас напишу лекс и якк спецификации для очень простенького компилятора, а Вы скажите, в чём я не прав и где ошибка? Потому что я ломаю голову и никак не могу понять, почему у меня никак не выходит написать хоть что-то простое, не говоря уже о си-компиляторе:
simple.l

Код: [no]DDEC [0-9]
DHEX [0-9A-Fa-f]
ID [_A-Za-z][_A-Za-z0-9]*
%{
#include "y.tab.h"
extern char* yylval;
%}
%%
[ \t] ;
"start" return(TSTART);
"end" return(TEND);
{ID} {return(TID); yylval=yytext;}
":=" return(TIS);
{DDEC}+ {return(TINT); yylval=yytext;}
%%
int main() { yylex(); return 0; }

yywrap()
{
printf("OK!");
return(1);
}[/no]
Автор: Mickey_from_nsk
Дата сообщения: 04.04.2003 05:53
DV
Я немного переделал, вобщем получается так.
flex-файл

Код:
DDEC [0-9]
DHEX [0-9A-Fa-f]
ID [_A-Za-z][_A-Za-z0-9]*
%{
#include "comp.tab.h"
%}
%%
[ \t] ;
"start" return(TSTART);
"end" return(TEND);
{ID} {return(TID); yylval=yytext;}
":=" return(TIS);
{DDEC}+ {return(TINT); yylval=yytext;}
\; return SEMICOLON;
[ \t\n]+ {;} <<-- Правило для игнорирования разных левых символов.
%%
int yyparse(); <<-- Прототип для функции - парсера.
int main()
{
yyparse(); <<-- !!ВЫЗОВ ФУНКЦИИ ПАРСЕРА !!
return 0;
}

int yywrap()
{
printf("OK!");
return(1);
}

void yyerror( char* str )
{
fprintf(stderr, "Error: %s\n", str);
}

Автор: DV
Дата сообщения: 05.04.2003 02:27
Вроде и делаю всё верно. Создаю lex.yy.c, y.tab.c и y.tab.h. Дальше мой Borland C 3.1 не видит файлы y.tab.c и y.tab.h. Я удаляю первую точку в имени (корректирую соотв. образом и содержимое исходников), и вроде всё нормально... Затем компиллирую lex.yy.c, и он мне говорит, что не объявлена переменная yylval. Я добавляю union:

Код: [no]%union {
int ival;
char* cval;
}[/no]
Автор: aarrtteemm
Дата сообщения: 05.04.2003 20:35
DV

Цитата:
После этого линкер выдаёт: Linker error: Undefined symbol yyparse() in module lexyy~1.c. Где же эта функция? По идее она должна быть в ytab.c? Я, наверное, скоро сойду с ума! Помогите чем-нибудь еще!

А ты не забыл включить y.tab.c в проект ? Функция yyparse() объявлена именно в нем. После правки Mickey_from_nsk файлы почти сразу сгенерировались (если не считать, что в одном месте бизоновского описания используется expr_list вместо expr_lst) и скомпилировались без проблем. Правда, я использовал VC++ 6.
Автор: DV
Дата сообщения: 07.04.2003 22:59
aarrtteemm
Всё равно на этапе линкования выдаёт, что продублированы переменные в файлах ytab.c и ytab.c... (вроде один и тот же файл).
А может и мне на VC++ скомпилить? В общем, видимо я чайник ещё в этом деле... спасибо за всё! Я не знаю, какие вопросы ещё задавать.
Автор: Mickey_from_nsk
Дата сообщения: 08.04.2003 06:12
Ты случаем ytab.c не включаешь в другой файл includeом?
Автор: amnick
Дата сообщения: 08.04.2003 19:58
DV

Цитата:
написать компилятор Си-программы с упрощённой грамматикой в ассемблерный код. Насчёт генераторов анализаторов у меня тут руки развязаны, я волен выбирать любые


А почему бы в таком случае не попробовать COCO/R (http://www.scifac.ru.ac.za/coco/)? Это простой в освоении (_намного_ проще связки LEX & YACC) генератор лексических и синтаксических анализаторов. Создаваемый синтаксический анализатор работает по методу рекурсивного спуска. Это не столь мощный метод, как используемый в YACC, но для упрощенной грамматики Си, весьма вероятно, подойдет. Генерируемый анализатор получается очень простым и прозрачным, программу легко отлаживать и сопровождать.В предоставляемом пакете есть примеры. Я использую COCO/R в коммерческом проекте, который сопровождаю уже несколько лет.
Автор: DV
Дата сообщения: 08.04.2003 21:16
amnick
Спасибо за ссылку! Буду разбираться...


Цитата:
Ты случаем ytab.c не включаешь в другой файл includeом?

Нет, не включаю, хотя уже и так пробовал Может у меня такая глючная версия Турбо Си, потому что F7 и F8 не работают, асмовский код глючно создаёт, я уже серьёзно подумываю насчёт VC++. Если есть где в Инете ссылка на BC5, то пожалуйста напишите (я перерыл практически всё...)

Добавлено
amnick
А есть где-нибудь инфо о Coco/R и пару примерчиков?..

Добавлено
Так-с, примерчики нашёл. Ещё такой вопросик по ходу дела: Как производить генерацию кода? Можно ли вставлять (как в Якке) в спецификацию код на Си, который формирует асмовский исходник, например?
Автор: DV
Дата сообщения: 10.04.2003 00:27
amnick
Кстати говоря, позволю себе спросить о передаче папрметров: а именно < > . Как это осуществляется?
Автор: amnick
Дата сообщения: 10.04.2003 22:18
DV

Цитата:
А есть где-нибудь инфо о Coco/R и пару примерчиков?

Заходишь по той ссылке, что я давал, и читаешь. Правда, материал на английском, на русском я не встречал. Есть книга "Compilers and Compiler Generators: An Introduction with C++", by Pat Terry. Она есть и в Интернете, на той же страничке есть ссылка на нее
(http://www.scifac.ru.ac.za/compilers). Примеры, как я уже писал, имеются в распространяемом пакете. Там есть и файл для Си ("An attempt to describe a subset of C").


Цитата:
Кстати говоря, позволю себе спросить о передаче папрметров: а именно < > . Как это осуществляется?


Да очень просто: то, что записано в угловых скобках, в таком точно виде и передается в качестве формальных параметров функции. Например, описание паскале-подобной записи (RECORD) может выглядеть примерно так (это упрощенный вариант, например, в нем ';' перед END обязательно, если хотя бы один член объявлен):

RecordType < t_type* typ, t_id* id >
=
(.
t_struct* s;
t_member* m_last = 0; // pointer to the last declared member
.)
'RECORD'
(.
s = new t_struct();
//s->members = 0; - already 0 because of overridden new
s->id = id;
typ->typ = s;
localEntry( id->name );
.)
{ MemberDecl < s, &m_last > ';' }
'END'
(.
localEnd( id );
.)
.


На С получается такой код:


static void RecordType (t_type* typ, t_id* id )
{

t_struct* s;
t_member* m_last = 0; // pointer to the last declared member
;
Expect(RECORDSym);

s = new t_struct();
//s->members = 0; - already 0 because of overridden new
s->id = id;
typ->typ = s;
localEntry( id->name );

while (Sym == IdentifierSym) {
MemberDecl(s, &m_last );
Expect(SemicolonSym);
}
Expect(ENDSym);

localEnd( id );

}


(На самом деле, я несколько упростил исходный код для COCO/R, а затем подправил ручками, соответственно, сгенерированный код. Так проще, чтобы не перегружать пример излишними деталями.)
Автор: DV
Дата сообщения: 11.04.2003 23:01
amnick
Спасибо за помощь, я в принципе, и сам уже разобрался Пришась по духу Coco/R for Delphi... Я о такой программке и мечтать не смел, компиллятор пишется пока что на УРА!!!
Ещё раз спасибо огромное!
Автор: SKYNET3000
Дата сообщения: 01.02.2014 15:17
Уважаемые господа разработчики компиляторов и систем искусственного разума! Посоветуйте программу, которая бы генерила текст по заданной мной грамматике и дереву вывода.

Я хочу задавать дерево вывода. А потом меняя грамматику (алфавиты терминалов и нетерминалов и правилы вывода) АВТОМАТИЧЕСКИ менять текст, который определяется данным деревов вывода.

Т.е. моя задача отличается от задачи компилятора.
Компилятор по известной грамматике пытается построить дерево разбора для заданного текста.

А мне нужно по уже известному дереву разбора и тексту найти грамматику
Автор: YuriyRR
Дата сообщения: 02.02.2014 14:59
А что можно почитать по этим программам?
Автор: SKYNET3000
Дата сообщения: 02.02.2014 17:06
YuriyRR

Цитата:
А что можно почитать по этим программам?

По каким по "этим"?
Автор: YuriyRR
Дата сообщения: 03.02.2014 00:41
SKYNET3000

Цитата:
По каким по "этим"?

lex flex yacc bison

Страницы: 1

Предыдущая тема: внедрение в *.exe програмного кода


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.