Интерпретатор на основе Prolog

Я уже намочил ноги функциональным программированием; я знаком (хотя и не опытен) в схеме Haskell и PLT. Я использовал схему PLT для создания маленьких интерпретаторов для игрушечных языков (ссылаясь на PLAI) - я лучше с императивными языками.

может ли кто-нибудь направить меня к ресурсам, которые я мог бы использовать для создания небольшого интерпретатора игрушечного языка по моему выбору с Prolog?

3 ответов


Я в основном использую swi-prolog, поэтому большая часть того, что я говорю, будет связана с swi-prolog. Однако другие реализации prolog могут иметь похожие предикаты / библиотеки (возможно, с немного другим именем), поэтому вы можете искать их руководства и находить их. Кроме того, я пишу компилятор, а не интерпретатор, в prolog, поэтому, возможно, некоторые части не так связаны с интерпретатором.

сайт документации SWI-Prolog действительно хорошо для поиска вещей: используйте поле поиска, чтобы найти любой предикат или же обычный поиск. Существует множество библиотек, но вы можете реализовать некоторые вещи самостоятельно, чтобы получить опыт. Вы можете в конечном итоге заново изобрести колесо, но это было бы полезно.

в книге" Искусство пролога " (Стерлинг,Шапиро) есть глава, посвященная созданию компилятора в прологе (и это хорошая книга для пролога).

возможно, есть некоторые инструменты, эквивалентные lex / bison для prolog; я никогда не искал.
Имхо, лексер довольно прост в простом прологе; естественно, он будет в значительной степени основан на сопоставлении шаблонов.

для парсера я предлагаю использовать DCG: определенные грамматики предложения:swi-Prolog doc, google для получения более подробной информации.
Проблема в том, что вам придется парсить весь файл (или, по крайней мере я не нашел способ сделать это иначе). Кстати, лексер также может быть сделан с DCGs, но я не думаю, что это действительно лучше.

Если вы хотите иметь промежуточный код, абстрактное дерево синтаксиса легко производить из парсера (вы также можете оценить много вещей во время синтаксического анализа).
О семантических проверках: в моем компиляторе для игрушечного языка я делаю большую часть семантических проверок (связанных с областью,вызовов функций) во время синтаксического анализа и остальное на отдельном шаге. Это немного грязно

другие полезные вещи: проверьте assert/1, глобальные переменные,мета-предикаты (maplist/[2-6]).
не чистый пролог, и вы можете сделать свой код слишком императивным, злоупотребляя ими (и тогда у вас могут быть очень неприятные побочные эффекты)

для таблицы символов (если вам это нужно) вы можете просто использовать assert/1 для добавления предикатов: swi-prolog использует динамические хэш-таблицы для динамических предикатов. предупреждение: динамические предикаты медленнее статических, поэтому, когда вы завершаете таблицу и не собираетесь вносить какие-либо изменения, используйте compile_predicates/1, чтобы сделать их статическими. Например, когда я заканчиваю разбор, мой ST готов, поэтому я компилирую его. Другое решение для ST-использовать


Маркус Тріска (здесь своей странице) показать несколько вещей, которые могут быть вам интересны: например,toy LISP, или некоторые toughts к мета переводчиков.


Я написал простой интерпретатор для функционального языка программирования в Prolog. Полная реализация показана здесь с примером ее использования:

:- initialization(main).
:- set_prolog_flag('double_quotes','chars').

main :- functional_syntax((
            writeln(factorial(3)+factorial(4)),
            Concatenated_string = "hello" + " " + "world",
            writeln(Concatenated_string),
            writeln(length(Concatenated_string)),
            writeln(type(Concatenated_string)),
            writeln(nth0(0,Concatenated_string)),
            writeln(msort([1,3,2,15,-1]))
        ),true).

factorial(N,Output) :-
    functional_syntax((
        (N=1 -> Output = 1);
        Output = N*factorial(N-1)
    )).

type(A,B) :-
    functional_syntax(A,A1),
    (number(A),B='number';
    is_list(A),B='list';
    atom(A),B='atom').

functional_syntax(A) :- functional_syntax(A,true).
functional_syntax(A,A) :- number(A);var(A);atom(A).
functional_syntax(not(X),Output) :-
    functional_syntax((X = false),Output).
functional_syntax(writeln(A),true) :-
    functional_syntax(A,A1),writeln(A1).
functional_syntax(A+B,C) :-
    functional_syntax([A,B],[A1,B1]),
    ((number(A1),number(B1)) ->
        C is A1+B1;
    (is_list(A1),is_list(B1)) ->
        append(A1,B1,C)).
functional_syntax(A-B,C) :-
    functional_syntax([A,B],[A1,B1]),C is A1-B1.
functional_syntax(A*B,C) :-
    functional_syntax([A,B],[A1,B1]),C is A1*B1.
functional_syntax(A/B,C) :-
    functional_syntax([A,B],[A1,B1]),C is A1/B1.
functional_syntax(A=B,Result) :-
    functional_syntax(B,B1),
    (A=B1,Result=true;dif(A,B1),Result=false).
functional_syntax(A->B,Result) :-
    (functional_syntax(A,A1),A1=true) -> (functional_syntax(B,B1),Result=true,B1=true);
    Result=false.
functional_syntax([],[]).
functional_syntax([A|B],[A1|B1]) :-
    functional_syntax(A,A1),functional_syntax(B,B1).
functional_syntax((A,B),Result) :-
    functional_syntax([A,B],[A1,B1]),
    (A1,B1,Result=true;([A1,B1]=[true,false];[A1,B1]=[false,true]),Result=false).
functional_syntax((A;B),Result) :-
    (functional_syntax(A,A1),call(A1);
    functional_syntax(B,B1),call(B1)) -> (Result = true);
    (functional_syntax(A,A1),A1=false,Result=false).
functional_syntax(Input,Output1) :-
    not(number(Input)),
    Input =.. [Name|Params],
    \+member(Name,['=','->',not,'[|]',',',';',+,-,*,/]),
    length(Params,Params_length),
    Params_length > 0,
    functional_syntax(Params,Params1),
    append([Name|Params1],[Output1],Input0),
    Input1 =.. Input0,
    call(Input1).