如何在Prolog中创建与另一个规则相反的DCG规则? [英] How do I create a DCG rule inverse to another in Prolog?

查看:61
本文介绍了如何在Prolog中创建与另一个规则相反的DCG规则?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Prolog中编写Commodore BASIC解释器,并且正在编写一些DCG进行解析.我已经验证了以下DCG可以正常工作,除了 variable 变量.我的目标是:对于不是布尔值,整数,浮点数或字符串的任何内容,它都是一个变量.但是,我通过 phrase 给出的任何内容只会导致 no .

I am writing a Commodore BASIC interpreter in Prolog, and I am writing some DCGs to parse it. I have verified the DCGs below to work except for the variable one. My goal is this: for anything which isn't a boolean, integer, float, or a string, it's a variable. However, anything that I give it via phrase just results in no.

bool --> [true].
bool --> [false].
integer --> [1]. % how to match nums?
float --> [0.1].
string --> [Str], {atom_chars(Str, ['"' | Chars]), last(Chars, '"')}.
literal --> bool; integer; float; string.

variable --> \+ literal.

我这样运行了堆栈跟踪(使用 gprolog )

I ran a stack trace like this (with gprolog)

main :- trace, phrase(variable, [bar]).

鉴于此,我无法弄清楚为什么 variable 失败了,因为在 literal 中每种情况下它都失败了.我猜错误很简单,但我仍然很困惑,所以擅长Prolog的人对我做错的事情有想法吗?

Looking at this, I cannot figure out why variable fails, given that it fails for each case in literal. I'm guessing that the error is pretty simple, but I'm still stumped, so does anyone who's good at Prolog have an idea of what I'm doing wrong?

| ?- main.
The debugger will first creep -- showing everything (trace)
      1    1  Call: phrase(variable,[bar]) ? 
      2    2  Call: variable([bar],_321) ? 
      3    3  Call: \+literal([bar],_348) ? 
      4    4  Call: literal([bar],_348) ? 
      5    5  Call: bool([bar],_348) ? 
      5    5  Fail: bool([bar],_348) ? 
      5    5  Call: integer([bar],_348) ? 
      5    5  Fail: integer([bar],_348) ? 
      5    5  Call: float([bar],_348) ? 
      5    5  Fail: float([bar],_348) ? 
      5    5  Call: string([bar],_348) ? 
      6    6  Call: atom_chars(bar,['"'|_418]) ? 
      6    6  Fail: atom_chars(bar,['"'|_418]) ? 
      5    5  Fail: string([bar],_348) ? 
      4    4  Fail: literal([bar],_348) ? 
      3    3  Exit: \+literal([bar],_348) ? 
      2    2  Exit: variable([bar],[bar]) ? 
      1    1  Fail: phrase(variable,[bar]) ? 

(2 ms) no
{trace}

推荐答案

要扩展另一个答案,关键问题是DCG规则(如 \ + literal )不会消耗来自输入.仅检查下一项(如果有的话)不是文字.

To expand a bit on the other answer, the key problem is that a DCG rule like \+ literal does not consume items from the input. It only checks that the next item, if any, is not a literal.

要实际消耗商品,您需要使用列表目标,类似于使用目标 [1] 来消耗 1 元素的方式.所以:

To actually consume an item, you need to use a list goal, similarly to how you use a goal [1] to consume a 1 element. So:

variable -->
    \+ literal,  % if there is a next element, it's not a literal
    [_Variable]. % consume this next element, which is a variable

例如:

?- phrase(variable, [bar]).
true.

?- phrase((integer, variable, float), [I, bar, F]).
I = 1,
F = 0.1.

具有单例变量 _Variable 有点奇怪-像这样解析时,您会丢失变量的名称.解析器稍作扩展后,您将需要使用DCG规则的参数来传达规则外的信息:

Having that singleton variable _Variable is a bit strange -- when you parse like this, you lose the name of the variable. When your parser is expanded a bit, you will want to use arguments to your DCG rules to communicate information out of the rules:

variable(Variable) -->
    \+ literal,  
    [Variable].

例如:

?- phrase((integer, variable(Var1), float, variable(Var2)), [I, bar, F, foo]).
Var1 = bar,
Var2 = foo,
I = 1,
F = 0.1.

这篇关于如何在Prolog中创建与另一个规则相反的DCG规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆