基于 Prolog 的解释器

发布于 2024-12-13 22:30:06 字数 137 浏览 0 评论 0原文

我已经开始接触函数式编程了;我熟悉(虽然不精通)Haskell 和 PLT 方案。我使用 PLT 方案为玩具语言构建了小型解释器(参考 PLAI)——我更擅长命令式语言。

谁能指导我使用 Prolog 来构建我选择的玩具语言的小型解释器的资源?

I've already gotten my feet wet with functional programming; I am familiar (though not proficient) in Haskell and PLT Scheme. I've used PLT Scheme to build little interpreters for toy languages (referencing PLAI)--I'm better with imperative languages.

Could anyone direct me to resources I could use to build a small interpreter of a toy language of my choosing with Prolog?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

天涯沦落人 2024-12-20 22:30:06

我主要使用 SWI-Prolog,所以我所说的大部分内容都与 SWI-Prolog 相关。然而,其他 Prolog 实现可能有类似的谓词/库(可能名称略有不同),因此您可以搜索他们的手册并找到它们。另外,我正在序言中编写编译器,而不是解释器,所以也许某些部分与解释器不太相关。

SWI-Prolog 的文档站点 非常适合查找内容:使用搜索框查找任何谓词或进行典型搜索。有大量的库,但您可能想自己实现一些东西来获得经验。你可能最终会重新发明轮子,但这会很有用。

《The Art of Prolog》(Sterling、Shapiro)一书有一章专门讨论在 Prolog 中构建编译器(这也是一本关于 Prolog 的好书)。

也许有一些类似于 lex/bison for Prolog 的工具;我从来没有真正搜索过。
恕我直言,词法分析器在普通 Prolog 中非常简单;当然,它将很大程度上基于模式匹配。

对于解析器,我建议使用 DCG:定语子句语法: SWI-Prolog 文档,谷歌了解更多详细信息。
问题是您必须解析整个文件(或者至少我还没有找到其他方法)。
顺便说一句,词法分析器也可以用 DCG 来完成,但我不认为它真的更好。

如果您选择使用中间代码,则很容易从解析器生成抽象语法树(您也可以在解析期间评估很多内容)。
关于语义检查:在我的玩具语言编译器中,我在解析期间进行了大部分语义检查(范围相关、函数调用),其余的则在单独的步骤中进行。 其他有用的东西有点混乱

:检查 assert/1、全局变量、元谓词(maplist/\[2-6\])。
不是纯粹的 Prolog,你可能会通过滥用它们使你的代码变得过于命令式(然后你可能会产生一些非常讨厌的副作用)

对于符号表(如果你需要它)你可以只使用 assert/1添加谓词:SWI-Prolog 对动态谓词使用动态哈希表。警告:动态谓词比静态谓词慢,因此,当您完成表并且不打算进行任何更改时,请使用compile_predicates/1 使其静态。例如,当我完成解析时,我的 ST 就准备好了,所以我编译它。
ST 的另一个解决方案是使用 关联列表。它们是用AVL树实现的,所以成本是O(log(N))。

I mainly use SWI-Prolog so most of what I say will be SWI-Prolog related. However, other Prolog implementations may have similar predicates/libraries (perhaps with a bit different name) so you may search their manuals and find them. Also, I am writing a compiler, not an interpreter, in prolog so maybe some parts are not so interpreter-related.

SWI-Prolog's documentation site is really good for finding stuff: use the search box to find any predicate or do a typical search. There is a plethora of libraries but you might want to implement some stuff yourself to gain experience. You might end up re-inventing the wheel but it would be useful.

The book "The Art of Prolog" (Sterling, Shapiro) has a chapter dedicated to building a compiler in Prolog (and it's a nice book on Prolog too).

Maybe there are some tools equivalent to lex/bison for Prolog; I never really searched.
Imho, the lexer is quite easy in plain Prolog; naturally, it will be based heavily on pattern matching.

For the parser I suggest using DCG: definite clause grammars: SWI-Prolog doc, google for more details.
The problem is that you will have to parse the whole file (or at least I haven’t found a way to do it otherwise).
Btw, the lexer could also be done with DCGs but I don’t think it's really better.

If you choose to have intermediate code, an abstract syntax tree is easy to produce from the parser (you could evaluate a lot of stuff during the parsing too).
About semantic checks: in my compiler for a toy language I do most of the semantic checks (scope related, function calls) during the parsing and the rest at a separate step. It's a bit messy

other useful stuff: check assert/1, global variables, meta predicates (maplist/\[2-6\]).
not pure Prolog and you might make your code too imperative by abusing them (and then you could have some really nasty side-effects)

For symbol table (if you need it) you could just use assert/1 to add predicates: SWI-Prolog uses dynamic hash tables for dynamic predicates. Warning: dynamic predicates are slower than static so, when you complete the table and are not going to make any changes use compile_predicates/1 to make them static. For example, when I finish parsing my ST is ready so I compile it.
Another solution for the ST is to use association lists. they are implemented with AVL trees so the cost is O(log(N)).

邮友 2024-12-20 22:30:06

Markus Triska(此处他的主页)展示了一些您可能感兴趣的内容:例如 玩具 LISP,或一些元解释器

Markus Triska (here his homepage) show several things could be interesting to you: for instance a toy LISP, or some toughts to meta interpreters.

梦魇绽荼蘼 2024-12-20 22:30:06

我用 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).

同样,可以编写命令式编程语言的解释器序言。

I wrote a simple interpreter for a functional programming language in Prolog. The full implementation is shown here with an example of its usage:

:- 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).

Similarly, it is possible to write interpreters for imperative programming languages in Prolog.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文