Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Создание компиляторов связкой lex&yacc

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2

Открыть новую тему     Написать ответ в эту тему

DV



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Крик души!!! Помогите кто чем сможет!
Я создал генератором лексических анализаторов lex распознаватель lex.yy.c и yacc-ом y.tab.c (синтаксический анализатор + генератор кода):
1) Как корректно передавать значения констант из lex.yy.c в y.tab.c для дальнейшего использования в генераторе кода?
2) Как скомпилировать всё это добро в исполняемый код?
Заранее благодарен за любую предоставленную информацию!

Всего записей: 56 | Зарегистр. 19-11-2002 | Отправлено: 18:02 23-03-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Я давно уже не использую "чистые" 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 и получаешь исполняемый файл.
Для более подробной информации - пиши по крайней мере ОС и компилятор, которые используешь.

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 08:34 24-03-2003
DV



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Mickey_from_nsk
Спасибо огромное за информацию. Мне всё равно на какой ОС писать, но желательно под Windows. Вообще моя задача заключается в том, чтоб написать компилятор Си-программы с упрощённой грамматикой в ассемблерный код. Насчёт генераторов анализаторов у меня тут руки развязаны, я волен выбирать любые (послушаюсь совета и попробую всё-таки flex-ом и bison-ом). По дороге возникли ещё такие вопросы:
1) Возможно ли flex-ом и bison-ом (или lex-ом и yacc-ом) создавать исходники, которые можно скомпиллировать обычным Borland C++ 3.1 в Windows-е?
2) Каким образом передаётся исходник на моём модифицированном языке для компиляции (через параметр? [вроде: compiler.exe source.c ?])
3) Поподробнее про описание семантики в yacc-спецификации (не обязательно).
Ещё раз огромное спасибо и за эту информацию!

Всего записей: 56 | Зарегистр. 19-11-2002 | Отправлено: 00:49 30-03-2003
aarrtteemm



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
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 для чтения из любого другого места - файла или строки.

Всего записей: 130 | Зарегистр. 17-01-2003 | Отправлено: 12:47 30-03-2003
DV



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
aarrtteemm

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

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

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

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

Всего записей: 56 | Зарегистр. 19-11-2002 | Отправлено: 00:23 31-03-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
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
 


Цитата:
Спасибо за то, что меня ещё терпите  

А зачем же еще этот форум?

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 08:16 31-03-2003
DV



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Так будет проще: Я сейчас напишу лекс и якк спецификации для очень простенького компилятора, а Вы скажите, в чём я не прав и где ошибка? Потому что я ломаю голову и никак не могу понять, почему у меня никак не выходит написать хоть что-то простое, не говоря уже о си-компиляторе:
simple.l

Код:
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);
}

simple.y

Код:
%token TSTART TEND TID TIS TINT
%start root
 
%%
root: TSTART  
{
printf("<старт>\n");
}
expr_lst
TEND
{
printf("<конец>\n");
};
expr_lst: expr
| expr ';' expr_lst;
expr: TID
{
printf("<идентификатору %s> ",yylval);
}
TIS
{
printf("<присвоить> ");
}
TINT
{
printf("<значение %s>;\n",yylval);
};
%%

Кстати, ешё: при компиляции в UNIX cc говорит о том, что не может найти библиотеки -ly и -ll. В чём может быть проблема (lex flex yacc byacc установлены).

Всего записей: 56 | Зарегистр. 19-11-2002 | Отправлено: 23:20 03-04-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
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);
}
 
 

bison-файл

Код:
 
%{
extern char* yytext;
%}
%token TSTART TEND TID TIS TINT SEMICOLON
%start root  
 
%%  
root: TSTART  
{  
printf("<start>\n");  
}  
expr_lst  
TEND  
{  
printf("<end>\n");  
};  
expr_lst: expr  
| expr_list SEMICOLON expr; <<-- У тебя левосторонняя грамматика, лучше разбирать именно в таком порядке, а не наоборот
expr: TID  
{  
printf("<identifier %s> ",yytext);  
}  
TIS  
{  
printf("<assume> ");  
}  
TINT  
{  
printf("<value %s>;\n",yytext);  
};
 

 
в printf я написал по английски только ради собственного удобства. Компилировал и запускал под Windows.

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 07:53 04-04-2003
DV



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

Код:
%union {
int ival;
char* cval;
}

и корректирую lex-спецификацию:

Код:
%%
[ \t\n]+ ;
"start" return(TSTART);
"end" return(TEND);
{ID} {return(TID); yylval.cval=yytext;}
":=" return(TIS);
{DDEC}+ {return(TINT); yylval.cval=yytext;}
\; return SEMICOLON;
%%

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

Всего записей: 56 | Зарегистр. 19-11-2002 | Отправлено: 04:27 05-04-2003
aarrtteemm



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
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.

Всего записей: 130 | Зарегистр. 17-01-2003 | Отправлено: 22:35 05-04-2003
DV



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
aarrtteemm
Всё равно на этапе линкования выдаёт, что продублированы переменные в файлах ytab.c и ytab.c... (вроде один и тот же файл).
А может и мне на VC++ скомпилить? В общем, видимо я чайник ещё в этом деле... спасибо за всё! Я не знаю, какие вопросы ещё задавать.

Всего записей: 56 | Зарегистр. 19-11-2002 | Отправлено: 23:59 07-04-2003
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ты случаем ytab.c не включаешь в другой файл includeом?

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 07:12 08-04-2003
amnick

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
DV

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

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

Всего записей: 130 | Зарегистр. 16-12-2001 | Отправлено: 20:58 08-04-2003
DV



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
amnick
Спасибо за ссылку! Буду разбираться...
 

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

Нет, не включаю, хотя уже и так пробовал Может у меня такая глючная версия Турбо Си, потому что F7 и F8 не работают, асмовский код глючно создаёт, я уже серьёзно подумываю насчёт VC++. Если есть где в Инете ссылка на BC5, то пожалуйста напишите (я перерыл практически всё...)
 
Добавлено
amnick
А есть где-нибудь инфо о Coco/R и пару примерчиков?..
 
Добавлено
Так-с, примерчики нашёл. Ещё такой вопросик по ходу дела: Как производить генерацию кода? Можно ли вставлять (как в Якке) в спецификацию код на Си, который формирует асмовский исходник, например?

Всего записей: 56 | Зарегистр. 19-11-2002 | Отправлено: 22:16 08-04-2003
DV



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
amnick
Кстати говоря, позволю себе спросить о передаче папрметров: а именно < > . Как это осуществляется?

Всего записей: 56 | Зарегистр. 19-11-2002 | Отправлено: 01:27 10-04-2003
amnick

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
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, а затем подправил ручками, соответственно, сгенерированный код. Так проще, чтобы не перегружать пример излишними деталями.)

Всего записей: 130 | Зарегистр. 16-12-2001 | Отправлено: 23:18 10-04-2003
DV



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
amnick
Спасибо за помощь, я в принципе, и сам уже разобрался Пришась по духу Coco/R for Delphi... Я о такой программке и мечтать не смел, компиллятор пишется пока что на УРА!!!
Ещё раз спасибо огромное!

Всего записей: 56 | Зарегистр. 19-11-2002 | Отправлено: 00:01 12-04-2003
SKYNET3000

BANNED
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Уважаемые господа разработчики компиляторов и систем искусственного разума! Посоветуйте программу, которая бы генерила текст по заданной мной грамматике и дереву вывода.
 
Я хочу задавать дерево вывода. А потом меняя грамматику (алфавиты терминалов и нетерминалов и правилы вывода) АВТОМАТИЧЕСКИ менять текст, который определяется данным деревов вывода.
 
Т.е. моя задача отличается от задачи компилятора.
Компилятор по известной грамматике пытается построить дерево разбора для заданного текста.
 
А мне нужно по уже известному дереву разбора и тексту найти грамматику

Всего записей: 687 | Зарегистр. 14-12-2013 | Отправлено: 17:17 01-02-2014
YuriyRR



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
А что можно почитать по этим программам?

Всего записей: 516 | Зарегистр. 07-06-2007 | Отправлено: 16:59 02-02-2014
SKYNET3000

BANNED
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
YuriyRR

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

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

Всего записей: 687 | Зарегистр. 14-12-2013 | Отправлено: 19:06 02-02-2014
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Создание компиляторов связкой lex&yacc


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru