Prolog 中的 DCG ߞ字符串
我正在使用 Prolog 的内置 DCG 功能编写一个 Lisp 到 C 的翻译器。这就是我处理算术的方式:
expr(Z) --> "(", "+", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%d + %d", [M, N])}.
expr(Z) --> "(", "-", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%d - %d", [M, N])}.
expr(Z) --> "(", "*", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%d * %d", [M, N])}.
expr(Z) --> "(", "/", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%d / %d", [M, N])}.
expr(E) --> number(E).
number(C) --> "-", digits(X), {C is -X}.
number(C) --> digits(C).
digits(D) --> digit(D);digit(A),digits(B), {number_codes(B,Cs),length(Cs,L), D is A*(10^L)+B}.
digit(D) --> [C], {"0"=<C, C=<"9", D is C - "0"}.
就像现在一样,它不处理嵌套表达式。这是我认为可行的:
expr(Z) --> "(", "+", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%s + %s", [M, N])}.
expr(E) --> number(N), {swritef(E, "%d", [N])}.
但我得到了这个:
?- expr(E, "42", []).
E = "42" %all OK
?- expr(E, "(+ 3 (* 2 2))", []).
E = "%s + %s" %not OK
我如何让它发挥作用?
I'm writing a Lisp-to-C translator using Prolog's built-in DCG capabilities. This is how I handle arithmetic:
expr(Z) --> "(", "+", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%d + %d", [M, N])}.
expr(Z) --> "(", "-", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%d - %d", [M, N])}.
expr(Z) --> "(", "*", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%d * %d", [M, N])}.
expr(Z) --> "(", "/", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%d / %d", [M, N])}.
expr(E) --> number(E).
number(C) --> "-", digits(X), {C is -X}.
number(C) --> digits(C).
digits(D) --> digit(D);digit(A),digits(B), {number_codes(B,Cs),length(Cs,L), D is A*(10^L)+B}.
digit(D) --> [C], {"0"=<C, C=<"9", D is C - "0"}.
As it is now, it doesn't handle nested expressions. Here is what I thought would work:
expr(Z) --> "(", "+", spaces, expr(M), spaces, expr(N), ")", {swritef(Z, "%s + %s", [M, N])}.
expr(E) --> number(N), {swritef(E, "%d", [N])}.
But I'm getting this:
?- expr(E, "42", []).
E = "42" %all OK
?- expr(E, "(+ 3 (* 2 2))", []).
E = "%s + %s" %not OK
How do I make it work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题在于 %s 格式说明符需要参数是字符列表。
所以你可以用这样的方法来做到这一点:
谓词 lexpr 只是将解析的表达式转换为字符列表。
编辑:03/07/2016:从 SWI 版本 7.0 开始,双引号内的文本不再被解释为字符代码列表。
您可以将双引号更改为反引号 (`) 或添加指令 ;
:-set_prolog_flag(double_quotes,codes).
在代码的开头。
The problem is that the %s format specifier needs the argument to be a list of characters.
So you can do it with something like this:
The predicate lexpr just converts the parsed expression to a list of chars.
Edit: 03/07/2016: As of SWI version 7.0, text enclosed in double quotes are not interpreted as a list of character codes anymore.
You can either change double quotes with back quotes (`) or add a directive ;
:-set_prolog_flag(double_quotes, codes).
at the beginning of the code.
在 < 中使用 %t 或 %w,而不是 %d代码>swritef。注意,%d 与 C 的 printf 格式不同。
如果您只是将 lisp-like 翻译成 C-like,那么您实际上不需要转换字符串
数字到数字的表示。只需将其保留为字符串即可。 (当然这取决于
取决于任务的复杂性)。否则,上层规则会在他们期望的字符串中找到一个数字。
将生成的 C 代码放入括号中,以便结果中的优先级和关联性正确。
这就是它的工作原理。
Use %t or %w, not %d in your
swritef
. Note, %d is not what it is in C's printf formats.If you just translating lisp-like to C-like you don't really need to convert the string
representation of numbers to a number. Just leave it as string. (Of course it dependes
on the complexity of your task). Otherwise the upper level rules foound a number where they expect a string.
Put the resultant C code into parentheses so that the priority and associativity are correct in the result.
and this is how it works.