LINUX.ORG.RU

конвертер программы с языка Си на язык Паскаль


0

2

Надо написать конвертер программы с языка Си на язык Паскаль. НА С++. В голове стразу же представилось, какая форма и прочее... а вот представления, что и как делать вообще нет. Немножко разобравшись понял что надо Синтаксический анализ, синтаксическое дерево. За это надо хвататься?? Если да.. как их написать...не имею никакого понятия.. Посоветуйте что нибуть Зарание спасибо!


Ответ на: комментарий от Ss

Если он так говорит, то не понимает всего объёма задачи и требует конвертации на очень примитивном уровне. Тогда делай простой поиск и замену ключевых слов, плюс поменять местами в объявлении тип переменной и её имя. ну и в теле основной программы сделать вызов main.

KivApple ★★★★★
()
Ответ на: комментарий от Ss

Да, книжки читать не нужно. И время на изучение рабочих проектов тоже не стоит, не поможет. Задача понятная, из теории требуется только прочитать, что такое AST и знать синтаксис Си и паскаля. Для реализации понадобятся только гугл и википедия.

note173 ★★★★★
()
Ответ на: комментарий от KivApple

Если он так говорит, то не понимает всего объёма задачи и требует конвертации на очень примитивном уровне. Тогда делай простой поиск и замену ключевых слов, плюс поменять местами в объявлении тип переменной и её имя. ну и в теле основной программы сделать вызов main.

Не, лучше упороться материалом и сделать правильно. И потом, на сдаче, смотреть на пятикопеечные глаза препода :) Если тот адекватен - поудивляется немного и примет с отметкой «отлично».

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Быстрей будет так: он высмеет меня перед всеми=)..Он так всегда делает, если не знает чего то. А знаний и уровень преподования низкий. ВОт такие преподы в универах)

Всем спасибо за ответы

Ss
() автор топика
Ответ на: комментарий от Ss

не, я на полном серьёзе. Судя по всему, ты и так достаточно хорошо знаешь русский (что неудивительно, не знаю как везде, но за три дня в Минске белорусский слышал только в транспорте при объявлении остановок).

lazyklimm ★★★★★
()
Ответ на: комментарий от lazyklimm

Увы но этот язык уже «мёртвый». И очень жаль( Не русский как видимо я не очень хорошо знаю).

Ss
() автор топика
Ответ на: комментарий от Ss

Быстрей будет так: он высмеет меня перед всеми=)..Он так всегда делает, если не знает чего то. А знаний и уровень преподования низкий. ВОт такие преподы в универах)

Бывает. У меня, помню, как-то подобная история была, но преподавателем был молодой недавний аспирант, так что особых проблем при сдаче не было.

Вообще, если есть ещё время, спроси какого рода разбор он хочет - ручной (конечный автомат (на что намекают if / switch, но так как бы и вложенных выражений разобрать не получится), recursive ascent parser (для LR-грамматик), recursive descent parser (для LL-грамматик), table-driven LR parser, table-driven LL parser) или с использованием существующих генераторов парсеров.

В любом случае, идея в том, что из текста программы на си путём разбора получаем AST (в С++ это будут структуры и объединения) из которого путём обхода генерируется текст программы на паскале. Так что можешь ещё спросить, предполагается ли построение AST (какую-то хоть сколько-нибудь серьёзную трансляцию напрямую и в один проход сделать ведь не получится).

Кстати, http://gnuu.org/2009/09/18/writing-your-own-toy-compiler/ - С++, Flex, Bison. Части 1-5 - разбор си-подобного языка и построение AST, 6 - генерация кода для LLVM из построенного AST (то же самое нужно проделать для паскаля).

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Думаю что если я спрошу он не поймёт, и будет мне опять же твердить про if, switch(ибо такая ситуация уже была). Наверное хочет показать администрации что задаёт крутые курсовые, а сделаны они примитивно)) Можно было бы сделать аля простой поиск и замену ключевых слов, плюс поменять местами в объявлении тип переменной и её имя. ну и в теле основной программы сделать вызов main.(с.KivApple). Но мне не очень хочется так делать. Это уже если ничего не получится прибегну к такому)

Значит по идее надо изучить что такое AST ? и что еще? Я впервые сталкиваюсь с такой разработкай. ибо на парах лабы только аля решение математических уровнений)

Ss
() автор топика
Ответ на: комментарий от Ss

Значит по идее надо изучить что такое AST ?

AST (для достаточно сложного языка) это рекурсивная структура данных в памяти (дерево или граф). Например, для текста

    while (b != 0)
        if (a > b)
            a = a − b;
        else
            b = b − a;

    return a;

нужно построить в памяти такое дерево - http://upload.wikimedia.org/wikipedia/commons/c/c7/Abstract_syntax_tree_for_E.... Это нужно за тем, что доступ к узлам константный (а не линейный поиск в тексте), преобразовывать и сворачивать дерево просто (сама структура дерева отражает грамматическую структуру языка, поэтому то что Кнут называл семантическими атрибутами реализуется как код выполняемый для узлов дерева разного типа).

и что еще?

Текст --|лексический анализ|--> Список лексем --|синтаксический разбор|--> AST --|pretty printer|--> Текст

Структуры данных:

  • Как будешь представлять текст?
  • Списки?
  • Есть опыт работы с рекурсивными структурами данных и рекурсивными функциями?

Алгоритмы:

  • Лексического анализа.
  • Синтаксического разбора.
  • Отображения и свёртки деревьев.

Можешь форкнуть github.com/lsegal/my_toy_compiler, загуглить BNF для C, дописать грамматику и написать генератор в паскаль (точнее, pretty printer, BNF и AST паксаля тут не нужны). И да, у C++ больной подход к декомпозиции :) Тут это можно наблюдать в виде зависимости кода для AST от LLVM.

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Структуры данных:

1. Текст будет в файле.. блокнот или сразу на си написанная простенькая программа(если правильно понял) 2. Составлю тхт файл где допустим справа будет Си ({}), слева Паскаль(begin, end) (если я правильно понял) 3. Опыта нет.

Ss
() автор топика
Ответ на: комментарий от slackwarrior

(Когда из медициской внезапно приехала тян - расслаблять, с пузырем(они там девушки без комплексов нащод Russian Reversal) - и кровать в общаге сломалась (закон Мерфи, да), ножку подперли драгонбуком. ЧСХ, конструкция выдержала!

Вот это я понимаю история, есть чем гордиться!

anonymous_sama ★★★★★
()
Ответ на: комментарий от Ss

Под текстом (для *.c, *.pas и лексем) и списками (для выхлопа лексера) имелись ввиду char*, string, FILE, iostream и list, vector - на выбор.

После того как example.c был прочитан в память, или открыт как поток, и до того как нужно записать example.pas, операций с диском делать не нужно - только манипулировать структурами данных в памяти (то что имелось ввиду под «структуры данных», т.е. примитивные / struct / union / class) с помощью алгоритмов (функций / методов). По крайней мере, если делать через -> список лексем -> AST ->, т.е. на синтаксическом уровне (на лексическом уровне мы просто линейно проходим по потоку знаков, выполняя нужные преобразования, так, например, можно лексер написать, на синтаксическом уровне мы обрабатывем вход (лексем) с помощью рекурсивных процедур, возможно с lookahead, возможно с backtracing, возможно опираясь на таблицу переходов, возможно строя нелинейный и рекурсивный AST или _сразу_ выполняя emit).

Опыта нет

Как дерево реализовать с помощью struct или разобрать / вычислить выражение вида «1 + 3 * (4 + (5 - 8) / 9)» не давали? Просто если курс был по синтаксическому разбору это же the must.

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Эм... есть ли у вас ася? Надоедать каждыми днями неочень «умными» вопросами я не буду)

Ss
() автор топика
Ответ на: комментарий от Ss

Эм... есть ли у вас ася?

Нету, есть почта в профиле, но кучку-другую вопросов можно задать прямо тут - не отвечу я, кто-нибудь другой подскажет.

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

=) «Под текстом (для *.c, *.pas и лексем) и списками (для выхлопа лексера) имелись ввиду char*, string, FILE, iostream и list, vector - на выбор.» Если на выбор..брать char. И на второй впорос, насчёт Списки. правильно мыслел или нет

Странно как то что здесь еще не предложили сделать работу за деньги

Ss
() автор топика
Ответ на: комментарий от Ss

Если на выбор..брать char. И на второй впорос, насчёт Списки. правильно мыслел или нет

iostream для чтения/записи в файлы, string для токенов/идентификаторов, vector для разного рода списков, свои классы для AST - как-то так, наверное.

Нужно ещё надеяться, что, с точки зрения препода, C++ != C :)

Странно как то что здесь еще не предложили сделать работу за деньги

Попроси перенести в www.linux.org.ru/forum/job/, озвучь условия, хотя тут выше вроде была ссылка на похожий курсач (курсачи имеют свойство утекать в интернеты).

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Начал читать, разбираться.. Каша, просто каша в голове. Воощем надо написать алгоритмы. Самое первое начать с синтаксического анализа?. Если да, можно больше информации про него? В гугле много пишется про него, и примеров много, но что и как не понять.Пока что)

Ss
() автор топика
Ответ на: комментарий от Ss

вот, кстати, по поводу парсера, лексера и AST, посмотри туториал llvm'ный, там, конечно всё примитивненько и ручками, но зато просто и доступно: http://llvm.org/docs/tutorial/

shty ★★★★★
()
Ответ на: комментарий от quasimoto

дерево

«1 + 3 * (4 + (5 - 8) / 9)»

Это можно сделать за один проход, руля стеком в соответствии со скобками и операциями.

Поскольку си и паскаль - языки одного типа, также можно сконвертить, пройдясь линейно.

alfix
()
Ответ на: комментарий от alfix

Поскольку си и паскаль - языки одного типа, также можно сконвертить, пройдясь линейно.

Я плохо помню паскаль, если не будет тонкостей требующих source-to-source, то почему бы нет.

quasimoto ★★★★
()
Ответ на: комментарий от Ss

Самое первое начать с синтаксического анализа?

Лексический и синтаксический, да.

Грубо говоря, из текста (iostream)

int add(int a, int b) {
  return a + b; // foo
}

путём лексического анализа получается список (vector) лексем:

"int", "add", "(", "int", "a", ",", "int", "b", "(", "{", "return", "a", "+", "b", ";", "}"

или

TYPE_INT, FUN_ID "add", FUN_ARGS_START, TYPE_INT, NAME_ID "a", FUN_ARGS_COMMA, TYPE_INT, NAME_ID "b", FUN_ARGS_END, FUN_START, SPEC_RETURN, NAME_ID "a", OP_PLUS, NAME_ID "b", OP_SEMI, FUN_END

который потом обходится рекурсивными процедурами - строится AST, либо сразу пишется выхлоп в *.pas (если так получится).

Нужно определиться для начала - парсить вручную (как тут - http://llvm.org/docs/tutorial/) или с использованием генератора парсеров (compiler-compiler, как тут - http://gnuu.org/2009/09/18/writing-your-own-toy-compiler/), ни и читать и писать какой-нибудь релевантный код - от простого к сложному, либо сразу пытаясь решить эту задачу, параллельно с этим читать какую-нибудь книжку по теме (список некоторых - http://stackoverflow.com/tags/compiler/info).

quasimoto ★★★★
()
Ответ на: комментарий от anonymous

Чем строить АСТ прежде правила вывода приведи - Вот тогда уже и можно будет говорить предметно: КЗ-ли Си либо КС :)

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

malbolge ★★
()
Ответ на: комментарий от invy

А чего в тайпдефе контекстного-то?
Там же правило разбора примерно такого вида:
typedefClause ::= typedef Type NewType | typedef PtrType

malbolge ★★
()
Ответ на: комментарий от malbolge

Проблема не в самом тайпдефе, а в том, что имена типов синтаксически неразличимы с именами переменных. И когда у тебя написано «x*y;», то это или умножение или объявление указателя на х (если был объявлен тип х).

anonymous
()
Ответ на: комментарий от invy

Язык Си - контекстно-зависимый, в то время как паскаль относится к контекстно-свободным.

Паскаль тоже контекстно-зависим. Чистых КСГ практически нет среди языков программирования.

ram
()
Ответ на: комментарий от anonymous

А ещё неизвестен тип переменных и разрешен ли для них оператор *. Если x, y — оба массивы какие-нибудь, то это выражение неверное. Даже без тайпдефов контекстная зависимость есть.

ram
()
Ответ на: комментарий от ram

А ещё неизвестен тип переменных и разрешен ли для них оператор *.

А это к синтаксическому анализу не имеет отношения. Тайпчек мы производим _уже_ имея синтаксическое дерево. То есть на этапе синтаксического разбора все ок.

anonymous
()
Ответ на: комментарий от ram

Паскаль тоже контекстно-зависим.

Пример?

Чистых КСГ практически нет среди языков программирования.

А по-моему верно как раз обратное - чуть менее чем все ЯП имеют КС-грамматику.

anonymous
()
Ответ на: комментарий от quasimoto

Собственно вот то самое правило, которое дает неоднозначность еще для лексера:

{L}({L}|{D})* { count(); return(check_type()); }

Нам надо знать является ли ИД именем переменной или типа. Но они неразличимы. проблемы была бы решена если бы в стиле того же хаскеля переменные начинались с маленькой буквЫ, а типы - с большой. Обратно - грамматика хаскеля стала бы КЗ, если бы в нем не было такой фичи :)

anonymous
()
Ответ на: комментарий от quasimoto

Обьясни мне это: Вообщем в этой статье http://gnuu.org/2009/09/18/writing-your-own-toy-compiler/5/ как потом это всё собирается, и вообще как запустить полученное?

Так же на этой же странице есть такая строчка: You can then compile your source files: $ g++ -o parser parser.cpp tokens.cpp main.cpp «Вы можете скомпилировать исходные файлы: $ g++ -o parser parser.cpp tokens.cpp main.cpp»

Как их скомпилировать.?

Ss
() автор топика
Ответ на: комментарий от Ss

Как их скомпилировать.?

Вот так: $ g++ -o parser parser.cpp tokens.cpp main.cpp

anonymous
()
Ответ на: комментарий от Ss

Как их скомпилировать.?

git clone git://github.com/lsegal/my_toy_compiler.git
cd my_toy_compiler
# maybe some changes
make
quasimoto ★★★★
()
Ответ на: комментарий от anonymous

А это к синтаксическому анализу не имеет отношения. Тайпчек мы производим _уже_ имея синтаксическое дерево. То есть на этапе синтаксического разбора все ок.

КС-грамматика должна отвечать на вопрос, принадлежит ли данная строка (такст программы) ко множеству строк данного языка (Си или Паскаль или ещё что) или нет ещё на этапе разбора.

Если после этапа разбора нужна ещё какая-то проверка на корректность типов, то это говорит о том, что заданная в компиляторе грамматика успешно разбирает множество строк, которое является более широким, чем множество строк нужного языка. Это и есть контекстная зависимость грамматики, просто вынесенная с этапа разбора, т.к. описать правила разбора, которые будут верно определять принадлежность строки ко множеству строк языка сложная задача.

ram
()
Ответ на: комментарий от anonymous

Пример?

1) var a: real; begin sin(a); end. 2) var a: string; begin sin(a); end.

Задание: описать КС правила вывода, с помощью которых можно будет определить, что первая программа верна, а вторая — нет. Без использования всяких синтаксических деревьев, таблиц идентификаторов и прочей шелухи. Чисто правилами вывода.

ram
()
Ответ на: комментарий от anonymous

А по-моему верно как раз обратное - чуть менее чем все ЯП имеют КС-грамматику.

Три «ха». Кроме brainfuck-а языки встречал какие-нибудь?

ram
()
Ответ на: комментарий от ram

КС-грамматика должна отвечать на вопрос, принадлежит ли данная строка (такст программы) ко множеству строк данного языка (Си или Паскаль или ещё что) или нет ещё на этапе разбора.

Именно так.

Если после этапа разбора нужна ещё какая-то проверка на корректность типов, то это говорит о том, что заданная в компиляторе грамматика успешно разбирает множество строк, которое является более широким, чем множество строк нужного языка.

И, значит, данный ЯП не разбирает. В самом деле - легко написать регулярную грамматику, которая разбирает _любую_ строку. Отсюда ведь не следует, что любая грамматика является регулярной, на самом деле?

Это и есть контекстная зависимость грамматики, просто вынесенная с этапа разбора

Никто никуда ничего не выносит.

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

Почему же сложная? Для нормальных ЯП просто пишем КС-грамматику и спокойн оразбираем.

anonymous
()
Ответ на: комментарий от ram

Задание: описать КС правила вывода, с помощью которых можно будет определить, что первая программа верна, а вторая — нет.

А зачем нам писать грамматику, с точки зрения которой вторая строка не верна, если эта строка по факту верна?

Еще раз - результат работы синтаксического анализатора некое конкретное синтаксическое дерево. То есть работа парсера заканчивается тогда, когда мы получили синтаксическое дерево. Если перед нами синтаксического дерева нет - то значит работа парсера не закончена. В случае примера:

1) var a: real; begin sin(a); end. 2) var a: string; begin sin(a); end.

КС-парсер паскаля и в первом и во втором случае построит вполне однозначное синтаксическое дерево. И потом это дерево мы сможем передать на какие-то другие этапы - на этап тайпчека, например. Но это однозначное дерево у нас уже будет после обработки КС-парсера. Значит грамматика КС.

Или вот в сишке, есть у нас «struct x{...};» и все прекрасно разберется - ведь ясно, что x - это имя типа. Будет построено однозначное дерево, потом передача на тайпчек и т.п. С другой стороны, выражение «x*y;» мы не сможем распарсить КС-парсером. Т.к. это выражение задает два дерева: Mult(Id, Id) и Declare(id, TypeId). И до тайпчека мы просто _не можем_ получить синтаксическое дерево. В отличии от паскаля и других КС-языков. Раз мы не можем получить АСТ до тайпчека, то алгоритм тайпчека - часть АСТ. Точнее, не весь алгоритм тайпчека, а только уче ттакого какие типы мы имеем на данный момент. В результате мы не можем, например, распарсить файлы независимо - то есть для парсинга файла х нам надо обязательно распарсить все его инклуды. Конечно же, никакого эффективного парсинга тогда ждать не приходится - и это не единственная проблема.

anonymous
()

Боже, убей их всех

Как обычно, Development состоит практически полностью из тупака.

geekless ★★
()

Могу взяться и написать в короткие сроки (объяснение прилагается). Напишите мне на email, если хотите обсудить условия =)
car-cdr,at,inbox,dot,ru

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.